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,
    Customer,
    WareHouse,
    WareHouseModeEnum,
    ProductCategory,
    Product,
    ProductUnitEnum,
    Employee,
    EmployeeStatusEnum,
)
from business import models as business_models
from stock import models as stock_models


@override_settings(
    CELERY_TASK_ALWAYS_EAGER=True,
    CELERY_TASK_EAGER_PROPAGATES=True,
)
class PreSalesAllocationAPITestCase(TestCase):
    def setUp(self):
        self.merchant = Merchant.objects.create(name='配货商户', type=MerchantTypeEnum.FACTORY)
        self.customer = Customer.objects.create(
            merchant=self.merchant,
            name='配货客户',
            created_by=None,
        )
        self.warehouse = WareHouse.objects.create(
            merchant=self.merchant,
            name='配货仓库',
            mode=WareHouseModeEnum.UNRESTRICTED,
        )
        category = ProductCategory.objects.create(
            merchant=self.merchant,
            name='配货品类',
            product_prefix='ALC',
        )
        self.product = Product.objects.create(
            merchant=self.merchant,
            category=category,
            name='配货产品',
            human_id='ALC-001',
            unit=ProductUnitEnum.METER,
        )

        User = get_user_model()
        self.user = User.objects.create_user(username='allocation_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.order_payload = {
            'customer': self.customer.id,
            'warehouse': self.warehouse.id,
            'kind': business_models.SalesOrderKindEnum.WHOLESALE,
            'remarks': '预销售单备注',
            'items': [
                {
                    'product_id': self.product.id,
                    'quantity': '12.5',
                    'unit': '米',
                    'order_quantity': 7,
                    'remarks': '明细备注',
                }
            ],
        }

        self.stock_record = stock_models.StockChangeRecord.objects.create(
            merchant=self.merchant,
            type=stock_models.StockChangeTypeEnum.ADD,
            warehouse=self.warehouse,
            source_type=stock_models.StockChangeSourceEnum.PURCHASE,
            created_by=self.user,
        )
        self.stock_detail = stock_models.StockChangeDetail.objects.create(
            merchant=self.merchant,
            product=self.product,
            unit=ProductUnitEnum.METER,
            stock_change_record=self.stock_record,
            quantity='12.5',
        )

    def _create_order(self):
        resp = self.client.post('/api/v1/pre-sales-orders/', self.order_payload, format='json')
        self.assertEqual(resp.status_code, status.HTTP_201_CREATED)
        return resp.data

    def test_create_allocation_record(self):
        order = self._create_order()
        item_id = order['items'][0]['id']

        payload = {
            'stock_ids': [self.stock_detail.id],
            'quantity': '5.5',
            'unit': '米',
        }
        resp = self.client.post(
            f'/api/v1/pre-sales-order-items/{item_id}/allocations/',
            payload,
            format='json',
        )
        self.assertEqual(resp.status_code, status.HTTP_201_CREATED)
        self.assertEqual(resp.data['stock_ids'], [self.stock_detail.id])
        self.assertEqual(str(resp.data['quantity']), '5.50')
        self.assertIn('stock_details', resp.data)
        self.assertEqual(resp.data['stock_details'][0]['product_id'], self.product.id)
        self.assertEqual(resp.data['stock_details'][0]['product_name'], self.product.name)
        self.assertEqual(str(resp.data['stock_details'][0]['quantity']), '12.50')

    def test_cancel_allocation_record(self):
        order = self._create_order()
        item_id = order['items'][0]['id']

        create_resp = self.client.post(
            f'/api/v1/pre-sales-order-items/{item_id}/allocations/',
            {
                'stock_ids': [self.stock_detail.id],
                'quantity': '5.5',
                'unit': '米',
            },
            format='json',
        )
        self.assertEqual(create_resp.status_code, status.HTTP_201_CREATED)
        record_id = create_resp.data['id']

        delete_resp = self.client.delete(
            f'/api/v1/pre-sales-order-items/{item_id}/allocations/{record_id}/'
        )
        self.assertEqual(delete_resp.status_code, status.HTTP_200_OK)
        self.assertEqual(delete_resp.data['status'], business_models.AllocationRecordStatusEnum.CANCELLED)
        freeze = stock_models.StockFreeze.objects.get(stock_detail=self.stock_detail)
        self.assertEqual(freeze.status, stock_models.StockFreezeStatusEnum.CANCELLED)

    def test_create_allocation_with_invalid_stock(self):
        order = self._create_order()
        item_id = order['items'][0]['id']

        resp = self.client.post(
            f'/api/v1/pre-sales-order-items/{item_id}/allocations/',
            {
                'stock_ids': [999999],
                'quantity': '5.5',
                'unit': '米',
            },
            format='json',
        )
        self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertIn('库存明细不存在', resp.data['error'])
