from decimal import Decimal

from rest_framework import serializers
from apps.utils.serializers import CustomModelSerializer
from apps.utils.constants import EXCLUDE_FIELDS_DEPT, EXCLUDE_FIELDS_BASE, EXCLUDE_FIELDS
from rest_framework.exceptions import ValidationError, ParseError

from apps.pum.models import Supplier, PuPlan, PuPlanItem, PuOrder, PuOrderItem, SupplierAudit, QuotationApply, PuContract, PuContractRecord
from apps.mtm.serializers import MaterialSerializer, MaterialSimpleSerializer
from django.db import transaction
from .services import PumService
from apps.wf.serializers import TicketSimpleSerializer
from apps.system.serializers import FileSerializer


class SupplierSerializer(CustomModelSerializer):
    class Meta:
        model = Supplier
        fields = '__all__'
        read_only_fields = EXCLUDE_FIELDS_DEPT


class PuPlanSerializer(CustomModelSerializer):
    class Meta:
        model = PuPlan
        fields = '__all__'
        read_only_fields = EXCLUDE_FIELDS_DEPT + ['state', 'submit_time', 'total_price']

    def update(self, instance, validated_data):
        if instance.state != PuPlan.PUPLAN_CREATE:
            raise ValidationError('该状态下不可编辑')
        return super().update(instance, validated_data)


class PuPlanItemSerializer(CustomModelSerializer):
    material_ = MaterialSerializer(source='material', read_only=True)
    pu_plan_number = serializers.CharField(
        source='pu_plan.number', read_only=True)
    create_by_name = serializers.CharField(
        source='create_by.name', read_only=True)
    belong_dept_name = serializers.CharField(
        source='belong_dept.name', read_only=True)
    note = serializers.CharField(required=False, allow_blank=True)

    class Meta:
        model = PuPlanItem
        fields = '__all__'
        read_only_fields = EXCLUDE_FIELDS + ['pu_order']

    def create(self, validated_data):
        pu_plan = validated_data['pu_plan']
        if pu_plan.state != PuPlan.PUPLAN_CREATE:
            raise ValidationError('该状态下不可添加需求')
        material = validated_data['material']
        self.complete_belong_dept(validated_data)
        if PuPlanItem.objects.filter(material=material, belong_dept=validated_data['belong_dept']).exists():
            raise ValidationError('同部门已提交该物料需求,请确认!')
        ins = super().create(validated_data)
        PumService.cal_pu_plan_total_price(pu_plan)
        return ins

    def complete_belong_dept(self, validated_data):
        belong_dept = validated_data.get('belong_dept', None)
        if belong_dept is None:
            belong_dept = self.context['request'].user.belong_dept
            if belong_dept is None:
                raise ValidationError('所属部门不可为空')
            else:
                validated_data['belong_dept'] = belong_dept
    
    def update(self, instance, validated_data):
        validated_data.pop('pu_plan')
        pu_plan = instance.pu_plan
        if pu_plan.state != PuPlan.PUPLAN_CREATE:
            raise ValidationError('该状态下不可编辑需求')
        material = validated_data['material']
        user = self.context['request'].user

        if instance.create_by != user:
            raise ValidationError('非创建人不可编辑')
        self.complete_belong_dept(validated_data)
        if PuPlanItem.objects.exclude(id=instance.id).filter(material=material, belong_dept=validated_data['belong_dept']).exists():
            raise ValidationError('同部门已提交该物料需求,请确认!')
        ins = super().update(instance, validated_data)
        PumService.cal_pu_plan_total_price(pu_plan)
        return ins


class PuOrderSerializer(CustomModelSerializer):
    supplier_name = serializers.CharField(
        source='supplier.name', read_only=True)
    create_by_name = serializers.CharField(
        source='create_by.name', read_only=True)
    update_by_name = serializers.CharField(
        source='update_by.name', read_only=True)
    materials_ = MaterialSimpleSerializer(
        source='materials', many=True, read_only=True)

    class Meta:
        model = PuOrder
        fields = '__all__'
        read_only_fields = EXCLUDE_FIELDS_DEPT + ['state', 'submit_time', 'total_price']

    def validate(self, attrs):
        contract = attrs.get('contract', None)
        if contract:
            attrs['supplier'] = contract.supplier
        if attrs.get('supplier', None) is None:
            raise ValidationError('未选择供应商')
        return attrs

    def update(self, instance, validated_data):
        validated_data.pop('supplier')
        if instance.state != PuOrder.PUORDER_CREATE:
            raise ValidationError('该状态下不可编辑')
        return super().update(instance, validated_data)


class PuOrderItemSerializer(CustomModelSerializer):
    material_ = MaterialSerializer(source='material', read_only=True)

    class Meta:
        model = PuOrderItem
        fields = '__all__'
        read_only_fields = EXCLUDE_FIELDS_BASE + ['delivered_count']

    def create(self, validated_data):
        pu_order = validated_data['pu_order']
        material = validated_data['material']
        if pu_order.state != PuOrder.PUORDER_CREATE:
            raise ValidationError('采购订单该状态下不可添加明细')
        if PuOrderItem.objects.filter(pu_order=pu_order, material=material).exists():
            raise ValidationError('该物料已添加')
        ins = super().create(validated_data)
        PumService.cal_pu_order_total_price(pu_order)
        return ins

    def update(self, instance, validated_data):
        validated_data.pop('material')
        validated_data.pop('pu_order')
        pu_order = instance.pu_order
        if pu_order.state != PuOrder.PUORDER_CREATE:
            raise ValidationError('采购订单该状态下不可编辑')
        ins = super().update(instance, validated_data)
        PumService.cal_pu_order_total_price(pu_order)
        return ins


class AddSerializer(serializers.Serializer):
    pu_order = serializers.PrimaryKeyRelatedField(
        label='采购订单ID', queryset=PuOrder.objects.all())
    pu_planitems = serializers.PrimaryKeyRelatedField(
        label='计划明细ID', queryset=PuPlanItem.objects.all(), many=True)


class SupplierAuditSerializer(CustomModelSerializer):
    survery_form_ = FileSerializer(source="survery_form", read_only=True)
    business_license_ = FileSerializer(source="business_license", read_only=True)
    quality_certificate_ = FileSerializer(source="quality_certificate", read_only=True)
    ticket_ = TicketSimpleSerializer(source="ticket", read_only=True)
    class Meta:
        model = SupplierAudit
        fields = "__all__"
        read_only_fields = EXCLUDE_FIELDS_BASE + ['ticket']
    
    def create(self, validated_data):
        name = validated_data["name"]
        if Supplier.objects.filter(name=name).exists():
            raise ParseError('供应商名称已存在')
        return super().create(validated_data)

class QuotationApplySerializer(CustomModelSerializer):
    ticket_ = TicketSimpleSerializer(source='ticket', read_only=True)
    class Meta:
        model = QuotationApply
        fields = "__all__"
        read_only_fields = EXCLUDE_FIELDS


class PuContractSerializer(CustomModelSerializer):
    supplier_name = serializers.CharField(source='supplier.name', read_only=True)
    create_by_name = serializers.CharField(source='create_by.name', read_only=True)
    update_by_name = serializers.CharField(source='update_by.name', read_only=True)

    class Meta:
        model = PuContract
        fields = '__all__'
        read_only_fields = EXCLUDE_FIELDS + ['belong_dept', 'paid_amount', 'unpaid_amount', 'pay_progress', 'settlement_status']


class PuContractRecordSerializer(CustomModelSerializer):
    contract_number = serializers.CharField(source='contract.number', read_only=True)
    supplier_name = serializers.CharField(source='contract.supplier.name', read_only=True)

    class Meta:
        model = PuContractRecord
        fields = '__all__'
        read_only_fields = EXCLUDE_FIELDS + ['belong_dept']

    def validate(self, attrs):
        contract = attrs.get('contract', getattr(self.instance, 'contract', None))
        amount = attrs.get('amount', getattr(self.instance, 'amount', None))
        if contract is None or amount is None:
            return attrs
        if contract.status == PuContract.STATUS_TERMINATED:
            raise ValidationError('合同已终止，不可操作付款流水')
        qs = PuContractRecord.objects.filter(contract=contract)
        if self.instance is not None:
            qs = qs.exclude(id=self.instance.id)
        total = sum((item.amount for item in qs), Decimal('0.00')) + amount
        if total > contract.contract_amount:
            raise ValidationError('累计付款金额不可超过合同金额')
        return attrs
