from apps.hrm.models import Certificate
from apps.opm.models import GasCheck, Operation, Opl, OplCate, OplCert, OplWorker
from apps.system.models import Dictionary
from apps.system.serializers import DeptSimpleSerializer, DictSimpleSerializer, UserSimpleSerializer
from apps.utils.fields import MyFilePathField
from apps.utils.serializers import CustomModelSerializer
from apps.utils.constants import EXCLUDE_FIELDS
from rest_framework import serializers
from django.db import transaction
from rest_framework.exceptions import ParseError, ValidationError
from apps.am.serializers import AreaSimpleSerializer
from apps.wf.serializers import TicketSerializer
from apps.system.serializers import FileSerializer
from apps.third.serializers import TDeviceSimpleSerializer
from django.core.cache import cache
from apps.wf.models import Ticket


class OplCateCreateUpdateSerializer(CustomModelSerializer):
    class Meta:
        model = OplCate
        exclude = EXCLUDE_FIELDS


class OplCateSerializer(CustomModelSerializer):

    class Meta:
        model = OplCate
        fields = '__all__'


class OplCateSimpleSerializer(CustomModelSerializer):
    class Meta:
        model = OplCate
        fields = ['id', 'name', 'code', 'sort']


class OplCateDetailSerializer(CustomModelSerializer):
    measure_options_ = DictSimpleSerializer(source='measure_options', read_only=True, many=True)
    risk_options_ = DictSimpleSerializer(source='risk_options', read_only=True, many=True)
    close_options_ = DictSimpleSerializer(source='close_options', read_only=True, many=True)

    class Meta:
        model = OplCate
        fields = '__all__'


class OperationCreateUpdateSerializer(CustomModelSerializer):
    class Meta:
        model = Operation
        exclude = EXCLUDE_FIELDS + ['number']
    
    def validate(self, attrs):
        dept_ter = attrs['dept_ter']
        dept_bus = attrs['dept_bus']
        if dept_ter.type != 'dept' or dept_bus.type != 'dept':
            raise ValidationError('属地和业务部门需为本部')
        return super().validate(attrs)


class OperationPartialUpdateSerializer(CustomModelSerializer):
    class Meta:
        model = Operation
        fields = ['vchannels', 'dept_ter', 'dept_bus']


class OperationSerializer(CustomModelSerializer):
    class Meta:
        model = Operation
        fields = "__all__"


class OperationDetailSerializer(CustomModelSerializer):
    area_ = AreaSimpleSerializer(source='area', read_only=True)
    dept_ter_ = DeptSimpleSerializer(source='dept_ter', read_only=True)
    dept_bus_ = DeptSimpleSerializer(source='dept_bus', read_only=True)
    coordinator_ = UserSimpleSerializer(source='coordinator', read_only=True)
    coordinator_name = serializers.CharField(source='coordinator.name', read_only=True)
    create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
    cates_ = OplCateSimpleSerializer(source='cates', read_only=True, many=True)
    vchannels_ = TDeviceSimpleSerializer(source='vchannels', read_only=True, many=True)

    class Meta:
        model = Operation
        fields = "__all__"


class OplWorkerCreateSerializer(CustomModelSerializer):
    certificates = serializers.PrimaryKeyRelatedField(label='证书ID', many=True, queryset=Certificate.objects.all())

    class Meta:
        model = OplWorker
        fields = ['id', 'worker', 'duty', 'certificates', 'opl']

    def create(self, validated_data):
        opl = validated_data['opl']
        ticket = opl.ticket
        if ticket and ticket.state.type != 1:
            raise ParseError('许可证已处理不可新增')
        certificates = validated_data.pop('certificates')
        if certificates:
            pass
        else:
            certificates = list(Certificate.objects.filter(employee__user=validated_data['worker']))
        if OplWorker.objects.filter(worker=validated_data['worker'], opl=validated_data['opl']).exists():
            raise ParseError('该成员已加入')
        with transaction.atomic():
            oplw = super().create(validated_data)
            for x in certificates:
                if x.state == Certificate.CERT_EXPIRED:
                    raise ParseError(f'证书{x.number}已过期!')
                oplc = OplCert.objects.filter(opl_worker=oplw, certificate=x).first()
                if oplc:
                    pass
                else:
                    oplc = OplCert()
                    oplc.opl_worker = oplw
                    oplc.certificate = x
                for f in Certificate._meta.fields:
                    if f.name not in ['id']:
                        setattr(oplc, f.name, getattr(x, f.name, None))
                oplc.save()
        return oplw


class OplWorkerUpdateSerializer(CustomModelSerializer):
    certificates = serializers.PrimaryKeyRelatedField(label='证书ID', many=True, queryset=Certificate.objects.all())

    class Meta:
        model = OplWorker
        fields = ['id', 'duty', 'certificates']

    def update(self, instance, validated_data):
        certificates = validated_data.pop('certificates')
        with transaction.atomic():
            oplw = super().update(instance, validated_data)
            for x in certificates:
                if x.state == Certificate.CERT_EXPIRED:
                    raise ParseError(f'证书{x.number}已过期!')
                oplc = OplCert.objects.filter(opl_worker=oplw, certificate=x).first()
                if oplc:
                    pass
                else:
                    oplc = OplCert()
                    oplc.opl_worker = oplw
                    oplc.certificate = x
                for f in Certificate._meta.fields:
                    if f.name not in ['id']:
                        setattr(oplc, f.name, getattr(x, f.name, None))
                oplc.save()
        return oplw


class OplCertSerializer(CustomModelSerializer):
    file_f = MyFilePathField(source='file', read_only=True)

    class Meta:
        model = OplCert
        fields = ['certificate', 'name', 'type', 'number', 'issue_date',
                  'expiration_date', 'review_date', 'file', 'file_f']


class OplWorkerSerializer(CustomModelSerializer):
    worker_ = UserSimpleSerializer(source='worker', read_only=True)
    worker_name = serializers.CharField(source='worker.name', read_only=True)
    certificates_ = serializers.SerializerMethodField()

    class Meta:
        model = OplWorker
        fields = '__all__'

    def get_certificates_(self, obj):
        cs = OplCert.objects.filter(opl_worker=obj)
        return OplCertSerializer(instance=cs, many=True).data


class GasCheckCreateUpdateSerializer(CustomModelSerializer):
    class Meta:
        model = GasCheck
        exclude = EXCLUDE_FIELDS


class GasCheckSerializer(CustomModelSerializer):
    checker_ = UserSimpleSerializer(source='checker', read_only=True)

    class Meta:
        model = GasCheck
        fields = '__all__'


class OplCreateUpdateSerializer(CustomModelSerializer):
    id = serializers.CharField(read_only=True)
    cate_name = serializers.CharField(source='cate.name', read_only=True)
    cate_code = serializers.CharField(source='cate.code', read_only=True)
    operation_name = serializers.CharField(source='operation.name', read_only=True)

    class Meta:
        model = Opl
        fields = ['id', 'operation', 'level', 'cate', 'start_time', 'end_time',
                  'dept_do', 'charger', 'monitor', 'work_time', 'work_type',
                  'accept_time', 'power', 'power_to', 'power_from',
                  'power_end_time', 'power_start_time', 'power_days',
                  'other_risk', 'other_emr', 'escape_route',
                  'risks_checked', 'measures_checked', 'create_imgs', 'cate_name', 'cate_code', 'operation_name']

    def create(self, validated_data):
        operation = validated_data['operation']
        if operation.state == Operation.OP_DONE:
            raise ParseError('作业已关闭不可创建许可')
        cate = validated_data['cate']
        if Opl.objects.filter(operation=operation, cate=cate).exclude(ticket__act_state=5).exists():
            raise ParseError('该类有效许可证已存在,不可重复申请')
        return super().create(validated_data)


class OplSerializer(CustomModelSerializer):
    cate_name = serializers.CharField(source='cate.name', read_only=True)
    cate_ = OplCateSimpleSerializer(source='cate', read_only=True)

    class Meta:
        model = Opl
        fields = '__all__'


class OplListSerializer(CustomModelSerializer):
    cate_name = serializers.CharField(source='cate.name', read_only=True)
    cate_code = serializers.CharField(source='cate.code', read_only=True)
    operation_name = serializers.CharField(source='operation.name', read_only=True)
    cate_ = OplCateSimpleSerializer(source='cate', read_only=True)
    dept_do_ = DeptSimpleSerializer(source='dept_do', read_only=True)
    charger_ = UserSimpleSerializer(source='charger', read_only=True)
    monitor_ = UserSimpleSerializer(source='monitor', read_only=True)
    ticket_ = TicketSerializer(source='ticket', read_only=True)
    mtask_uid = serializers.SerializerMethodField()
    
    class Meta:
        model = Opl
        fields = '__all__'
    
    def get_mtask_uid(self, obj):
        return cache.get('opl_' + obj.id, None)


class OplDetailSerializer(CustomModelSerializer):
    cate_name = serializers.CharField(source='cate.name', read_only=True)
    cate_code = serializers.CharField(source='cate.code', read_only=True)
    operation_name = serializers.CharField(source='operation.name', read_only=True)
    operation_ = OperationDetailSerializer(source='operation', read_only=True)
    dept_do_ = DeptSimpleSerializer(source='dept_do', read_only=True)
    charger_ = UserSimpleSerializer(source='charger', read_only=True)
    charger_name = serializers.CharField(source='charger.name', read_only=True)
    monitor_name = serializers.CharField(source='monitor.name', read_only=True)
    monitor_ = UserSimpleSerializer(source='monitor', read_only=True)
    ticket_ = TicketSerializer(source='ticket', read_only=True)
    risks_checked_ = serializers.SerializerMethodField()
    measures_checked_ = serializers.SerializerMethodField()
    close_dos_ = serializers.SerializerMethodField()
    create_imgs_ = FileSerializer(source='create_imgs', many=True)
    audit_imgs_ = FileSerializer(source='audit_imgs', many=True)
    work_imgs_ = FileSerializer(source='work_imgs', many=True)
    close_imgs_ = FileSerializer(source='close_imgs', many=True)
    mtask_uid = serializers.SerializerMethodField()

    class Meta:
        model = Opl
        fields = '__all__'

    def get_risks_checked_(self, obj):
        qs = Dictionary.objects.filter(id__in=obj.risks_checked).values('id', 'name')
        return list(qs)

    def get_measures_checked_(self, obj):
        qs = Dictionary.objects.filter(id__in=obj.measures_checked).values('id', 'name')
        return list(qs)

    def get_close_dos_(self, obj):
        qs = Dictionary.objects.filter(id__in=obj.close_dos).values('id', 'name')
        return list(qs)

    def get_mtask_uid(self, obj):
        return cache.get('opl_' + obj.id, None)

class OplCloseSerializer(CustomModelSerializer):
    class Meta:
        model = Opl
        fields = ['close_imgs', 'close_note', 'close_dos', 'close_desc']
