from django.db import transaction
from django.db.models.aggregates import Count
from rest_framework import exceptions, serializers
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin
from apps.mtm.models import Material
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse
from apps.inm.signals import update_inm
from apps.sam.serializers import ContractCreateUpdateSerializer, ContractSerializer, CustomerCreateUpdateSerializer, CustomerSerializer, OrderCreateUpdateSerializer, OrderSerializer, SaleCreateSerializer, SaleListSerializer, SaleProductCreateSerializer, SaleProductListSerializer
from apps.sam.models import Contract, Customer, Order, Sale, SaleProduct
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from apps.system.mixins import CreateUpdateCustomMixin
from django.shortcuts import render
from rest_framework.decorators import action
from django.db.models import F
from rest_framework.response import Response
from django.utils import timezone
# Create your views here.
class CustomerViewSet(CreateUpdateCustomMixin, ModelViewSet):
    """
    客户-增删改查
    """
    perms_map = {'*': '*'}
    queryset = Customer.objects.all()
    serializer_class = CustomerSerializer
    search_fields = ['name', 'contact']
    filterset_fields = []
    ordering_fields = ['create_time']
    ordering = ['-create_time']

    def get_serializer_class(self):
        if self.action in ['create', 'update']:
            return CustomerCreateUpdateSerializer
        return CustomerSerializer


class ContractViewSet(CreateUpdateCustomMixin, ModelViewSet):
    """
    合同-增删改查
    """
    perms_map = {'*': '*'}
    queryset = Contract.objects.select_related('customer').all()
    serializer_class = ContractSerializer
    search_fields = ['name']
    filterset_fields = []
    ordering_fields = ['create_time']
    ordering = ['-create_time']

    def get_serializer_class(self):
        if self.action in ['create', 'update']:
            return ContractCreateUpdateSerializer
        return ContractSerializer

class OrderViewSet(CreateUpdateCustomMixin, ModelViewSet):
    """
    订单-增删改查
    """
    perms_map = {'*': '*'}
    queryset = Order.objects.select_related('contract', 'customer').all()
    serializer_class = OrderSerializer
    search_fields = ['number', 'product']
    filterset_fields = ['product', 'contract', 'customer']
    ordering_fields = ['create_time']
    ordering = ['-create_time']

    def get_serializer_class(self):
        if self.action in ['create', 'update']:
            return OrderCreateUpdateSerializer
        return super().get_serializer_class()

    @action(methods=['get'], detail=False, perms_map={'get':'*'})
    def toplan(self, request, pk=None):
        queryset = Order.objects.filter(count__gt=F('planed_count')).order_by('-id')
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class SaleViewSet(CreateUpdateCustomMixin, ListModelMixin, RetrieveModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet):
    """
    销售记录
    """
    perms_map = {'*': '*'}
    queryset = Sale.objects.select_related('customer', 'order', 'product', 'order__contract').all()
    serializer_class = SaleListSerializer
    search_fields = ['customer__name', 'order__number']
    filterset_fields = ['product', 'order', 'customer']
    ordering_fields = ['create_time']
    ordering = ['-create_time']

    def get_serializer_class(self):
        if self.action == 'create':
            return SaleCreateSerializer
        elif self.action == 'retrieve':
            return SaleListSerializer
        return super().get_serializer_class()

    def create(self, request, *args, **kwargs):
        data = request.data
        serializer = SaleCreateSerializer(data=data)
        serializer.is_valid(raise_exception=True)
        vdata = serializer.validated_data
        with transaction.atomic():
            iproducts = vdata.pop('iproducts')
            vdata['count'] = len(iproducts)
            sale = Sale.objects.create(**vdata)
            i_l = []
            for i in iproducts:
                i_d ={}
                i_d['sale'] = sale
                i_d['number'] = i.number
                i_d['iproduct'] = i
                i_l.append(SaleProduct(**i_d))
            SaleProduct.objects.bulk_create(i_l)
        return Response()

    @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=serializers.Serializer)
    @transaction.atomic
    def audit(self, request, pk=None):
        """
        审核
        """
        obj = self.get_object()
        if obj.is_audited:
            raise exceptions.APIException('已审核通过')
        # 创建出库记录
        fifo = FIFO()
        fifo.type = FIFO.FIFO_TYPE_SALE_OUT
        fifo.is_audited = True
        fifo.auditor = request.user
        fifo.inout_date = timezone.now()
        fifo.create_by = request.user
        fifo.save()
        # 出库条目 暂时不校验是否军检
        # spds = SaleProduct.objects.filter(sale=obj)
        # for i in spds:
        #     if i.is_mtested and i.is_mtestok:
        #         pass
        #     else:
        #         raise exceptions.APIException('存在未军检产品')
        # 创建出库条目
        ips = IProduct.objects.filter(sale_iproduct__sale=obj)
        items = ips.values('warehouse', 'material', 'batch').annotate(total=Count('id'))
        for i in items:
            warehouse = WareHouse.objects.get(id=i['warehouse'])
            material = Material.objects.get(id=i['material'])
            fifoitem = FIFOItem()
            fifoitem.is_tested = True
            fifoitem.is_testok = True
            fifoitem.warehouse = warehouse
            fifoitem.material = material
            fifoitem.count = i['total']
            fifoitem.batch = i['batch']
            fifoitem.fifo = fifo
            fifoitem.save()
            items_p = ips.filter(warehouse=warehouse, batch=i['batch'])
            ipxs = []
            for i in items_p:       
                # 创建出库明细半成品
                ip = {}
                ip['fifoitem'] = fifoitem
                ip['number'] = i.number
                ip['material'] = i.material
                ip['iproduct'] = i
                ipxs.append(FIFOItemProduct(**ip))
            FIFOItemProduct.objects.bulk_create(ipxs)
        # 更新成品库情况
        ips.update(is_saled=True)
        # 更新库存
        update_inm(fifo)
        # 变更审核状态
        obj.is_audited = True
        obj.save()
        # 变更订单状态
        if obj.order:
            order = obj.order
            order.delivered_count = order.delivered_count + obj.count
            order.save()
        return Response()

class SaleProductViewSet(ListModelMixin, DestroyModelMixin, CreateModelMixin, GenericViewSet):
    """
    销售记录关联产品
    """
    perms_map = {'*': '*'}
    queryset = SaleProduct.objects.select_related('iproduct', 'iproduct__material', 'iproduct__warehouse').all()
    serializer_class = SaleProductListSerializer
    search_fields = []
    filterset_fields = ['sale', 'iproduct']
    ordering_fields = ['create_time']
    ordering = ['id']

    def get_serializer_class(self):
        if self.action == 'create':
            return SaleProductCreateSerializer
        return super().get_serializer_class()

    def destroy(self, request, *args, **kwargs):
        obj = self.get_object()
        sale = obj.sale
        if sale.is_audited:
            raise exceptions.APIException('该销售记录已审核,不可删除产品')
        sale.count = SaleProduct.objects.filter(sale=obj.sale).count()
        sale.save()
        obj.delete()
        return Response()
    
    