import copy

from django.contrib.auth import get_user_model
from django.test import TestCase, override_settings
from rest_framework import status
from rest_framework.test import APIClient

from basic_info.models import (
    Merchant,
    MerchantTypeEnum,
    Supplier,
    WareHouse,
    WareHouseModeEnum,
    ProductCategory,
    Product,
    ProductUnitEnum,
    Employee,
    EmployeeStatusEnum,
)
from business import models as business_models


@override_settings(
    CELERY_TASK_ALWAYS_EAGER=True,
    CELERY_TASK_EAGER_PROPAGATES=True,
)
class PrePurchaseOrderAPITestCase(TestCase):
    def setUp(self):
        self.merchant = Merchant.objects.create(name='预采购商户', type=MerchantTypeEnum.FACTORY)
        self.supplier = Supplier.objects.create(
            merchant=self.merchant,
            name='预采购供应商',
        )
        self.warehouse = WareHouse.objects.create(
            merchant=self.merchant,
            name='预采购仓库',
            mode=WareHouseModeEnum.UNRESTRICTED,
        )
        category = ProductCategory.objects.create(
            merchant=self.merchant,
            name='预采购品类',
            product_prefix='PPR',
        )
        self.product = Product.objects.create(
            merchant=self.merchant,
            category=category,
            name='预采购产品',
            human_id='PPR-001',
            unit=ProductUnitEnum.METER,
        )

        User = get_user_model()
        self.user = User.objects.create_user(username='pre_purchase_user', password='pass123')
        self.employee = Employee.objects.create(
            merchant=self.merchant,
            sys_user=self.user,
            name='预采购员',
            status=EmployeeStatusEnum.ACTIVE,
        )

        self.client = APIClient()
        self.client.force_authenticate(user=self.user)

        self.payload = {
            'supplier': self.supplier.id,
            'warehouse': self.warehouse.id,
            'kind': business_models.PurchaseOrderKindEnum.WHOLESALE,
            'remarks': '预采购单备注',
            'items': [
                {
                    'product_id': self.product.id,
                    'quantity': '12.5',
                    'unit': '米',
                    'order_quantity': 7,
                    'remarks': '明细备注',
                }
            ],
        }

    def _create(self, payload=None) -> int:
        resp = self.client.post('/api/v1/pre-purchase-orders/', payload or self.payload, format='json')
        self.assertEqual(resp.status_code, status.HTTP_201_CREATED)
        return resp.data['id']

    def test_create_pre_purchase_order_success(self):
        resp = self.client.post('/api/v1/pre-purchase-orders/', self.payload, format='json')
        self.assertEqual(resp.status_code, status.HTTP_201_CREATED)
        self.assertIn('id', resp.data)
        self.assertIn('human_id', resp.data)
        self.assertEqual(resp.data['supplier'], self.supplier.id)
        self.assertEqual(resp.data['warehouse'], self.warehouse.id)
        self.assertEqual(len(resp.data['items']), 1)

    def test_list_pre_purchase_orders(self):
        self._create()
        resp = self.client.get('/api/v1/pre-purchase-orders/')
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertIn('results', resp.data)
        self.assertGreaterEqual(len(resp.data['results']), 1)

    def test_get_detail(self):
        order_id = self._create()
        resp = self.client.get(f'/api/v1/pre-purchase-orders/{order_id}/')
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertEqual(resp.data['id'], order_id)
        self.assertIn('items', resp.data)

    def test_update_pre_purchase_order(self):
        order_id = self._create()
        payload = copy.deepcopy(self.payload)
        payload['remarks'] = '更新备注'
        payload['items'][0]['quantity'] = '20'
        resp = self.client.put(f'/api/v1/pre-purchase-orders/{order_id}/', payload, format='json')
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertEqual(resp.data['remarks'], '更新备注')
        self.assertEqual(str(resp.data['items'][0]['quantity']), '20.00')

    def test_delete_pre_purchase_order(self):
        order_id = self._create()
        resp = self.client.delete(f'/api/v1/pre-purchase-orders/{order_id}/')
        self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
        self.assertFalse(business_models.PrePurchaseOrder.objects.filter(id=order_id).exists())
