from django.shortcuts import render
from apps.pum.models import Supplier, PuPlan, PuPlanItem, PuOrder, PuOrderItem, SupplierAudit, QuotationApply, PuContract, PuContractRecord
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet, EuModelViewSet
from apps.pum.serializers import (SupplierSerializer, PuPlanSerializer, PuPlanItemSerializer, QuotationApplySerializer,
                                  PuOrderSerializer, PuOrderItemSerializer, AddSerializer, SupplierAuditSerializer,
                                  PuContractSerializer, PuContractRecordSerializer)
from rest_framework.exceptions import ParseError, PermissionDenied
from rest_framework.decorators import action
from rest_framework import serializers
from apps.pum.filters import PuPlanItemFilter, PuOrderFilter
from django.db import transaction
from rest_framework.response import Response
from django.utils import timezone
from apps.pum.services import PumService
from apps.wf.mixins import TicketMixin
from apps.wf.models import Ticket
# Create your views here.


class SupplierViewSet(CustomModelViewSet):
    """
    list: 供应商

    供应商
    """
    queryset = Supplier.objects.all()
    serializer_class = SupplierSerializer
    search_fields = ['name', 'contact']
    filterset_fields = ['can_outsource']

    def perform_destroy(self, instance):
        if PuOrder.objects.filter(supplier=instance).exists():
            raise ParseError('该供应商存在采购订单不可删除')
        instance.delete()

class SupplierAuditViewSet(TicketMixin, CustomModelViewSet):
    """
    list: 供应商审核

    供应商审核
    """
    queryset = SupplierAudit.objects.all()
    serializer_class = SupplierAuditSerializer
    search_fields = ['name', 'material_name', 'material_cate']
    workflow_key = "wf_supplieraudit"

    @staticmethod
    def add_supplier(ticket: Ticket, transition, new_ticket_data: dict):
        supplieraudit = SupplierAudit.objects.get(ticket=ticket)
        if Supplier.objects.filter(name=supplieraudit.name).exists():
            raise ParseError('供应商名称已存在')
        Supplier.objects.create(name=supplieraudit.name)

class PuPlanViewSet(CustomModelViewSet):
    """
    list: 采购计划

    采购计划
    """
    queryset = PuPlan.objects.all()
    serializer_class = PuPlanSerializer
    search_fields = ['name', 'number']
    filterset_fields = ['state']

    def perform_destroy(self, instance):
        if PuPlanItem.objects.filter(pu_plan=instance).exists():
            raise ParseError('该计划存在明细不可删除')
        instance.delete(soft=False)

    @action(methods=['post'], detail=True, perms_map={'post': 'pu_plan.submit'}, serializer_class=serializers.Serializer)
    def submit(self, request, *args, **kwargs):
        """提交采购计划

        提交采购计划
        """
        puplan = self.get_object()
        user = request.user
        if puplan.create_by != user:
            raise PermissionDenied('非创建人不可提交')
        if puplan.state != PuPlan.PUPLAN_CREATE:
            raise ParseError('采购计划状态异常')
        puplan.submit_time = timezone.now()
        puplan.submit_user = user
        puplan.state = PuPlan.PUPLAN_SUBMITED
        puplan.save()
        return Response()


class PuPlanItemViewSet(CustomModelViewSet):
    """
    list: 采购计划明细

    采购计划明细
    """
    queryset = PuPlanItem.objects.all()
    serializer_class = PuPlanItemSerializer
    filterset_class = PuPlanItemFilter
    select_related_fields = ['material', 'pu_plan',
                             'pu_order', 'create_by', 'belong_dept']
    ordering_fields = ['create_time', 'material', 'need_date', 'need_count']
    ordering = ['create_time']

    def perform_destroy(self, instance):
        user = self.request.user
        pu_plan = instance.pu_plan
        if pu_plan.state == PuPlan.PUPLAN_CREATE and user != instance.create_by:
            raise ParseError('非创建人不可删除')
        elif instance.pu_order is not None:
            raise ParseError('存在采购订单不可删除')
        instance.delete()
        PumService.cal_pu_plan_total_price(pu_plan)


class PuOrderViewSet(CustomModelViewSet):
    """
    list: 采购订单

    采购订单
    """
    queryset = PuOrder.objects.all()
    serializer_class = PuOrderSerializer
    filterset_class = PuOrderFilter
    search_fields = ['number', 'supplier__name', 'item_puorder__material__name', 'item_puorder__material__specification', 'item_puorder__material__model']
    select_related_fields = ['create_by', 'update_by', 'supplier']

    def perform_destroy(self, instance):
        if instance.state != PuOrder.PUORDER_CREATE:
            raise ParseError('采购订单非创建中不可删除')
        instance.delete(soft=False)

    @action(methods=['post'], detail=True, perms_map={'post': 'pu_order.submit'}, serializer_class=serializers.Serializer)
    @transaction.atomic
    def submit(self, request, *args, **kwargs):
        """提交采购订单

        提交采购订单
        """
        puorder = self.get_object()
        user = request.user
        if puorder.delivery_date is None or puorder.number is None:
            raise ParseError('订单信息不全')
        if puorder.create_by != user:
            raise PermissionDenied('非创建人不可提交')
        if puorder.state != PuOrder.PUORDER_CREATE:
            raise ParseError('采购计划状态异常')
        puorder.submit_time = timezone.now()
        puorder.submit_user = user
        puorder.state = PuOrder.PUORDER_SUBMITED
        puorder.save()
        PumService.change_puplan_state_when_puorder_sumbit(puorder)
        return Response()


class PuOrderItemViewSet(CustomModelViewSet):
    """
    list: 采购订单明细

    采购订单明细
    """
    perms_map = {'get': '*', 'post': 'pu_order.update', 'put': 'pu_order.update', 'delete': 'pu_order.update'}
    queryset = PuOrderItem.objects.all()
    serializer_class = PuOrderItemSerializer
    filterset_fields = ['material', 'pu_order']
    ordering = ['create_time']

    def perform_destroy(self, instance):
        pu_order = instance.pu_order
        if pu_order.state != PuOrder.PUORDER_CREATE:
            raise ParseError('采购订单非创建中不可删除')
        instance.delete()
        PumService.cal_pu_order_total_price(pu_order)

    @action(methods=['post'], detail=False, perms_map={'post': 'pu_order.update'}, serializer_class=AddSerializer)
    @transaction.atomic
    def add_from_planitems(self, request, *args, **kwargs):
        """从计划明细创建/变更采购订单明细

        从计划明细创建/变更采购订单明细
        """
        data = request.data
        sr = AddSerializer(data=data)
        sr.is_valid(raise_exception=True)
        vdata = sr.validated_data
        puorder = vdata['pu_order']
        if puorder.state != PuOrder.PUORDER_CREATE:
            raise ParseError('该采购订单不可用')
        for item in vdata['pu_planitems']:
            if item.pu_plan.state == PuPlan.PUPLAN_CREATE:
                raise ParseError('存在不可选择的计划明细')
            if item.pu_order and item.pu_order.state != PuOrder.PUORDER_CREATE:
                raise ParseError('存在计划明细已指定进行中的采购订单')
            puorderitem, is_created = PuOrderItem.objects.get_or_create(
                pu_order=puorder, material=item.material,
                defaults={'pu_order': puorder,
                          'material': item.material, 
                          'count': item.need_count,
                          'unit_price': item.unit_price,
                          'total_price': item.total_price
                          }
            )
            if not is_created:
                puorderitem.count = puorderitem.count + item.need_count
                if item.total_price:
                    puorderitem.total_price = puorderitem.total_price if puorderitem.total_price else 0 + item.total_price
                puorderitem.save()
            if puorder.delivery_date is None:
                puorder.delivery_date = item.need_date
            elif item.need_date < puorder.delivery_date:
                puorder.delivery_date = item.need_date
            puorder.save()
            item.pu_order = puorder
            item.save()
        return Response()

class QuotationApplyViewSet(TicketMixin, CustomModelViewSet):
    """
    list: 报价申请

    报价申请
    """
    queryset = QuotationApply.objects.all()
    serializer_class = QuotationApplySerializer
    filterset_fields = ['product_name', 'customer_name','apply_date', 'quoter']
    search_fields = ['product_name', 'customer_name','contact_person']
    ordering = ['create_time']
    workflow_key = "wf_quotation"


class PuContractViewSet(CustomModelViewSet):
    """
    list: 采购合同

    采购合同
    """
    queryset = PuContract.objects.all()
    serializer_class = PuContractSerializer
    search_fields = ['name', 'number', 'supplier__name']
    select_related_fields = ['supplier', 'create_by', 'update_by']
    filterset_fields = ['supplier', 'status', 'settlement_status']

    def perform_destroy(self, instance):
        if PuOrder.objects.filter(contract=instance).exists():
            raise ParseError('该采购合同存在采购订单不可删除')
        instance.delete()


class PuContractRecordViewSet(CustomModelViewSet):
    """
    list: 采购合同付款流水

    采购合同付款流水
    """
    perms_map = {
        'get': '*',
        'post': 'pu_contract.update',
        'put': 'pu_contract.update',
        'patch': 'pu_contract.update',
        'delete': 'pu_contract.update',
    }
    queryset = PuContractRecord.objects.all()
    serializer_class = PuContractRecordSerializer
    search_fields = ['contract__number', 'contract__name', 'voucher_no', 'remark']
    select_related_fields = ['contract', 'contract__supplier', 'create_by', 'update_by']
    filterset_fields = {
        'contract': ['exact'],
        'stage_type': ['exact', 'in'],
        'pay_method': ['exact', 'in'],
    }

    def perform_destroy(self, instance):
        if instance.contract.status == PuContract.STATUS_TERMINATED:
            raise ParseError('合同已终止，不可删除付款流水')
        instance.delete()
