from datetime import timedelta
from rest_framework.serializers import ModelSerializer
from rest_framework import serializers
from apps.hrm.services import HrmService
from apps.utils.fields import MyFilePathField
from django.utils import timezone


from apps.utils.serializers import CustomModelSerializer
from apps.utils.constants import EXCLUDE_FIELDS
from apps.hrm.models import (Certificate, ClockRecord, Employee, Probation,
                             NotWorkRemark, Attendance, Resignation, EmpNeed, EmpJoin, EmpPersonInfo, EmpContract, Leave, EmployeeTransfer)
from apps.system.serializers import DeptSimpleSerializer, UserSimpleSerializer
from django.db import transaction
from django.core.cache import cache
from apps.utils.tools import check_id_number_strict, get_info_from_id
from rest_framework.exceptions import ParseError
from django.conf import settings
import datetime
from apps.wf.serializers import TicketSimpleSerializer


class EmployeeShortSerializer(CustomModelSerializer):
    belong_dept_name = serializers.CharField(
        source='belong_dept.name', read_only=True)

    class Meta:
        model = Employee
        fields = ['id', 'name', 'belong_dept_name',
                  'user', 'third_info', 'type']


class EmployeeSimpleSerializer(CustomModelSerializer):
    belong_dept_name = serializers.CharField(
        source='belong_dept.name', read_only=True)
    post_name = serializers.CharField(source='post.name', read_only=True)
    location = serializers.SerializerMethodField()

    class Meta:
        model = Employee
        fields = ['id', 'type', 'name', 'belong_dept', 'belong_dept_name', 'post',
                  'post_name', 'photo', 'third_info', 'number', 'id_number', 'location']

    def get_location(self, obj):
        key_str = 'ep_{}'.format(obj.id)
        return cache.get(key_str, None)

# class EmployeeBaseSerializer(CustomModelSerializer):
#     def save(self, **kwargs):
#         if self.validated_data.get('user', None):
#             user = self.validated_data['user']
#             self.validated_data['name'] = user.name
#             self.validated_data['belong_dept'] = user.belong_dept
#         return super().save(**kwargs)


class EmployeeCreateUpdateSerializer(CustomModelSerializer):
    id_number = serializers.CharField(
        label="身份证号", validators=[check_id_number_strict])

    class Meta:
        model = Employee
        exclude = EXCLUDE_FIELDS + ['is_atwork', 'last_check_time',
                                    'not_work_remark',
                                    'third_info',
                                    'type', 'phone', 'belong_dept', 'post', 'user']
        extra_kwargs = {
            'number': {'required': True},
            'photo': {'required': True},
            'id_number': {'required': True},
        }

    @transaction.atomic
    def create(self, validated_data):
        instance = super().create(validated_data)
        if instance.type == 'employee':
            # 如果是内部员工
            HrmService.sync_dahua_employee(ep=instance)
        return instance

    def update(self, instance, validated_data):
        id_number = validated_data['id_number']
        ret = get_info_from_id(id_number)
        validated_data['gender'] = ret['gender']
        old_photo = instance.photo
        old_job_state = instance.job_state
        old_name = instance.name
        instance = super().update(instance, validated_data)
        if old_photo != instance.photo:  # 如果照片有变动,需要更新人脸库
            # 使用的是face_recongition
            face_data, msg = HrmService.get_facedata_from_img_x(
                settings.BASE_DIR + instance.photo)
            in_face_data = instance.face_data
            if face_data:
                if isinstance(in_face_data, dict):
                    in_face_data['dlib'] = face_data
                    instance.face_data = in_face_data
                    instance.save()
                else:
                    instance.face_data = {'dlib': face_data}
                    instance.save()
            else:
                raise ParseError(msg)
            from apps.hrm.tasks import update_all_facedata_cache
            update_all_facedata_cache.delay()
        if instance.user and instance != old_name:
            instance.user.name = instance.name
            instance.user.save()
        if instance.type == 'remployee':  # 如果是相关方
            from apps.rpm.services import sync_to_rep
            sync_to_rep(instance)
        elif instance.type in ['visitor', 'driver']:  # 如果是访客或司机
            from apps.vm.services import sync_to_visitor
            sync_to_visitor(instance)
        if instance.job_state in [20, 30] and instance.user:  # 如果离职了删除账户
            instance.user.is_deleted = True
            instance.user.save()
            # 同时去除门禁授权
        # 如果是正式员工或相关方且有门禁权限:
        now = timezone.now()
        if instance.type in ['employee', 'remployee']:
            start_time = None
            end_time = None
            # 如果是正式员工,给长时间期限
            if instance.third_info.get('dh_face_card', None) is None and instance.type == 'employee':
                start_time = now
                end_time = now + timedelta(days=7300)
            if instance.job_state in [20, 30] and old_job_state == 10:  # 离职或退休
                start_time = now
                end_time = now + timedelta(hours=8)
            # 正式员工重新在职
            elif instance.job_state == 10 and old_job_state in [20, 30] and instance.type == 'employee':
                start_time = now
                end_time = now + timedelta(days=7300)
            HrmService.sync_dahua_employee(ep=instance, old_photo=old_photo,
                                           start_time=start_time, end_time=end_time)
        return instance


class EmployeeImproveSerializer(CustomModelSerializer):
    photo_f = MyFilePathField(source='photo', read_only=True)
    signature_f = MyFilePathField(source='signature', read_only=True)

    class Meta:
        model = Employee
        fields = ['photo', 'id_number', 'email', 'gender',
                  'signature', 'photo_f', 'signature_f', 'phone']
        extra_kwargs = {
            'number': {'required': True},
            'photo': {'required': True},
            'id_number': {'required': True},
        }

    def update(self, instance, validated_data):
        id_number = validated_data['id_number']
        ret = get_info_from_id(id_number)
        validated_data['gender'] = ret['gender']
        return super().update(instance, validated_data)


class ChannelAuthoritySerializer(serializers.Serializer):
    # pks = serializers.ListField(child=serializers.CharField(max_length=20), label="员工ID列表")
    start_time = serializers.DateTimeField(label="开始时间")
    end_time = serializers.DateTimeField(label="结束时间")


class EmployeeSerializer(CustomModelSerializer):
    belong_dept_ = DeptSimpleSerializer(source='belong_dept', read_only=True)
    user_ = UserSimpleSerializer(source='user', read_only=True)
    belong_dept_name = serializers.CharField(
        source='belong_dept.name', read_only=True)
    post_name = serializers.CharField(source='post.name', read_only=True)
    blt_ = serializers.SerializerMethodField()
    photo_f = MyFilePathField(source='photo', read_only=True)
    signature_f = MyFilePathField(source='signature', read_only=True)

    class Meta:
        model = Employee
        fields = '__all__'
        read_only_fields = ['is_atwork', 'last_check_time', 'not_work_remark']

    def get_blt_(self, obj):
        if hasattr(obj, 'blt'):
            from apps.third.serializers import TDeviceSimpleSerializer
            return TDeviceSimpleSerializer(instance=obj.blt).data
        # if hasattr(obj, 'tdevice'):
        #     from apps.third.serializers import TDeviceSimpleSerializer
        #     return TDeviceSimpleSerializer(instance=obj.tdevice).data
        return


class EmployeeDetailSerializer(EmployeeSerializer):
    # door_range = serializers.SerializerMethodField()
    location = serializers.SerializerMethodField()

    # def get_door_range(self, obj):
    #     third_info = obj.third_info
    #     dh_face_card = third_info.get('dh_face_card', None)
    #     if dh_face_card:
    #         _, res = dhClient.request(**dhapis['card_detail'], params={'cardNumber': dh_face_card})
    #         return [res['startDate'], res['endDate']]

    def get_location(self, obj):
        key_str = 'ep_{}'.format(obj.id)
        return cache.get(key_str, None)


class EmployeeNotWorkRemarkSerializer(ModelSerializer):
    class Meta:
        model = Employee
        fields = ['not_work_remark']


class ClockRecordListSerializer(serializers.ModelSerializer):
    employee_ = EmployeeSimpleSerializer(source='employee', read_only=True)

    class Meta:
        model = ClockRecord
        fields = '__all__'


class ClockRecordCreateSerializer(serializers.ModelSerializer):
    clock_time = serializers.DateTimeField(label='打卡时间', required=True)

    class Meta:
        model = ClockRecord
        fields = ['id', 'type', 'employee', 'clock_time']

    def validate(self, attrs):
        attrs['trigger'] = 'manual'
        return attrs


class ClockRecordSimpleSerializer(serializers.ModelSerializer):
    class Meta:
        model = ClockRecord
        fields = ['id', 'type', 'exception_type', 'detail']


class NotWorkRemarkListSerializer(serializers.ModelSerializer):
    class Meta:
        model = NotWorkRemark
        fields = '__all__'


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

    class Meta:
        model = Certificate
        exclude = EXCLUDE_FIELDS


class CertificateSerializer(CustomModelSerializer):
    employee_name = serializers.CharField(
        source='employee.name', read_only=True)
    file_f = MyFilePathField(source='file', read_only=True)

    class Meta:
        model = Certificate
        fields = '__all__'


class CorrectSerializer(serializers.Serializer):
    start_time = serializers.DateTimeField()
    end_time = serializers.DateTimeField()


class AttendanceSerializer(CustomModelSerializer):
    user_name = serializers.CharField(
        source='user.name', read_only=True)
    belong_dept_name = serializers.CharField(
        source='user.belong_dept.name', read_only=True)
    shift_name = serializers.CharField(source='shift.name', read_only=True)
    post_name = serializers.CharField(
        source='user.post.name', read_only=True)
    team_name = serializers.CharField(source='team.name', read_only=True)
    work_time_start = serializers.DateTimeField(read_only=True)
    work_time_end = serializers.DateTimeField(read_only=True)

    class Meta:
        model = Attendance
        fields = '__all__'
        extra_kwargs = {'team': {'required': True}, 'post': {'required': True}}

    def create(self, validated_data):
        user = validated_data['user']
        shift = validated_data['shift']
        work_date = validated_data['work_date']
        att = Attendance.objects.filter(
            user=user, work_date=work_date, shift=shift).first()
        if att:
            att.note = validated_data.get('note', '')
            att.state = validated_data['state']
            att.update_by = self.context['request'].user
            att.save()
            return att
        else:
            start_time_o = shift.start_time_o
            end_time_o = shift.end_time_o
            if end_time_o >= start_time_o:
                validated_data['work_time_start'] = datetime.datetime.combine(
                    work_date, start_time_o)
                validated_data['work_time_end'] = datetime.datetime.combine(
                    work_date, end_time_o)
            else:
                validated_data['work_time_start'] = datetime.datetime.combine(
                    work_date, start_time_o) - datetime.timedelta(days=1)
                validated_data['work_time_end'] = datetime.datetime.combine(
                    work_date, end_time_o)
            return super().create(validated_data)

    def update(self, instance, validated_data):
        new_data = {}
        new_data['note'] = validated_data.get('note', '')
        new_data['state'] = validated_data['state']
        return super().update(instance, validated_data)


class ResignationSerializer(CustomModelSerializer):
    belong_dept_name = serializers.CharField(source="employee.belong_dept.name", read_only=True)
    post_name = serializers.CharField(source="employee.post.name", read_only=True)
    ticket_ = TicketSimpleSerializer(source="ticket", read_only=True)
    employee_name = serializers.CharField(source="employee.name", read_only=True)
    employee_id_number = serializers.CharField(source="employee.id_number", read_only=True)
    class Meta:
        model = Resignation
        fields = '__all__'
    
    def update(self, instance, validated_data):
        validated_data.pop('employee')
        return super().update(instance, validated_data)
    
    def create(self, validated_data):
        employee:Employee = validated_data['employee']
        if employee.job_state == Employee.JOB_ON:
            pass
        else:
            raise ParseError('员工不在职,不可创建申请')
        if Resignation.objects.filter(employee=employee).exists():
            raise ParseError('该员工已存在离职申请')
        return super().create(validated_data)


class EmpNeedSerializer(CustomModelSerializer):
    dept_need_name = serializers.CharField(source='dept_need.name', read_only=True)
    ticket_ = TicketSimpleSerializer(source='ticket', read_only=True)
    class Meta:
        model = EmpNeed
        fields = '__all__'


class EmpJoinSerializer(CustomModelSerializer):
    ticket_ = TicketSimpleSerializer(source='ticket', read_only=True)
    dept_name = serializers.CharField(source='dept_need.name', read_only=True)
    class Meta:
        model = EmpJoin
        fields = '__all__'


class EmpPersonInfoSerializer(CustomModelSerializer):
    class Meta:
        model = EmpPersonInfo
        fields = (
            'name',
            'gender',
            'IDcard',
            'phone',
            'post',
            'note',
        )


class LeaveSerializer(CustomModelSerializer):
    ticket_ = TicketSimpleSerializer(source='ticket', read_only=True)
    employee_name = serializers.CharField(source='employee.name', read_only=True)
    post_name = serializers.CharField(source="employee.post.name", read_only=True)
    belong_dept_name = serializers.CharField(source='employee.belong_dept.name', read_only=True)
    class Meta:
        model = Leave 
        fields = '__all__'


class TransferSerializer(CustomModelSerializer):
    ticket_ = TicketSimpleSerializer(source='ticket', read_only=True)
    employee_name = serializers.CharField(source='employee.name', read_only=True)
    post_name = serializers.CharField(source="employee.post.name", read_only=True)
    belong_dept_name = serializers.CharField(source='employee.belong_dept.name', read_only=True)
    new_post_name = serializers.CharField(source="new_post.name", read_only=True)
    original_post_name = serializers.CharField(source="original_post.name", read_only=True)
    new_dept_name = serializers.CharField(source="new_dept.name", read_only=True)
    original_dept_name = serializers.CharField(source="original_dept.name", read_only=True)
    class Meta:
        model = EmployeeTransfer 
        fields = '__all__'

    def create(self, validated_data):
        is_change = validated_data['is_change']
        if is_change:
           if validated_data['new_dept'] == validated_data['original_dept']:
               raise ParseError('新旧部门相同，无需调动')
        else:
            if validated_data['new_post'] == validated_data['original_post']:
                raise ParseError('新旧岗位相同，无需调动')

        return super().create(validated_data)


class ProbationSerializer(CustomModelSerializer):
    ticket_ = TicketSimpleSerializer(source='ticket', read_only=True)
    employee_name = serializers.CharField(source='empperson.name', read_only=True)
    post_name = serializers.CharField(source="empperson.reg_post", read_only=True)
    reg_dept_name = serializers.CharField(source='empperson.reg_dept.name', read_only=True)
    IDcard = serializers.CharField(source="empperson.IDcard", read_only=True)
    class Meta:
        model = Probation 
        fields = '__all__'


class EmpContractSerializer(CustomModelSerializer):
    ticket_ = TicketSimpleSerializer(source='ticket', read_only=True)
    employee_name = serializers.CharField(source='employee.name', read_only=True)
    post_name = serializers.CharField(source="employee.post.name", read_only=True)
    dept_name = serializers.CharField(source='employee.belong_dept.name', read_only=True)
    gender = serializers.CharField(source="employee.gender", read_only=True)
    join_date = serializers.CharField(source="employee.start_date", read_only=True)
    end_contract = serializers.CharField(source="employee.contract_end_date", read_only=True)
    batch_employees = serializers.SerializerMethodField()

    def get_batch_employees(self, obj):
        if obj.ticket_id:
            siblings = EmpContract.objects.filter(ticket_id=obj.ticket_id).select_related(
                'employee', 'employee__post', 'employee__belong_dept')
            if siblings.count() > 1:
                return [{
                    'employee_name': s.employee.name if s.employee else '',
                    'post_name': s.employee.post.name if s.employee and s.employee.post else '',
                    'dept_name': s.employee.belong_dept.name if s.employee and s.employee.belong_dept else '',
                    'join_date': str(s.employee.start_date or '') if s.employee else '',
                    'end_contract': str(s.employee.contract_end_date or '') if s.employee else '',
                } for s in siblings]
        return []

    class Meta:
        model = EmpContract
        fields = '__all__'