
from django.conf import settings
from django.db import transaction
from django.utils import timezone
from rest_framework import serializers
from rest_framework.decorators import action
from rest_framework.exceptions import ParseError
from rest_framework.mixins import ListModelMixin
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response

from apps.hrm.errors import NO_NEED_LEVEL_REMARK
from apps.hrm.filters import (CertificateFilterSet, ClockRecordFilterSet, EmployeeFilterSet,
                              NotWorkRemarkFilterSet)
from apps.hrm.models import Certificate, ClockRecord, Employee, NotWorkRemark, Attendance
from apps.hrm.serializers import (CertificateCreateUpdateSerializer, CertificateSerializer, ChannelAuthoritySerializer,
                                  ClockRecordListSerializer,
                                  EmployeeCreateUpdateSerializer, EmployeeDetailSerializer, EmployeeImproveSerializer,
                                  EmployeeNotWorkRemarkSerializer,
                                  EmployeeSerializer,
                                  ClockRecordSimpleSerializer, ClockRecordCreateSerializer,
                                  NotWorkRemarkListSerializer, CorrectSerializer, AttendanceSerializer)
from apps.hrm.services import HrmService

from apps.third.dahua import dhClient
from apps.third.tapis import dhapis
from apps.utils.export import export_excel
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
from apps.utils.mixins import BulkCreateModelMixin, BulkDestroyModelMixin

epTypeOptions = {'employee': '正式员工', 'remployee': '相关方',
                 'visitor': '访客', 'driver': '货车司机'}
epStateOptions = {10: '在职', 20: '离职', 30: '退休'}
crOptions = {10: '上班打卡', 20: '下班打卡', 30: ''}
crEoptions = {10: '在岗时间短', 20: '在岗时间长', 30: '缺卡', 40: '加班'}

# Create your views here.


class EmployeeViewSet(CustomModelViewSet):
    """
    人员管理
    """
    queryset = Employee.objects.exclude(user__is_superuser=True)
    select_related_fields = ['user']
    filterset_class = EmployeeFilterSet
    serializer_class = EmployeeSerializer
    retrieve_serializer_class = EmployeeDetailSerializer
    create_serializer_class = EmployeeCreateUpdateSerializer
    update_serializer_class = EmployeeCreateUpdateSerializer
    partial_update_serializer_class = EmployeeCreateUpdateSerializer
    search_fields = ['name', 'number',
                     'user__username', 'id_number', 'id', 'phone']
    ordering = ['-pk']

    # def filter_queryset(self, queryset):
    #     if not self.detail:
    #         self.request.query_params._mutable = True
    #         self.request.query_params.setdefault('type', 'employee')
    #     return super().filter_queryset(queryset)

    @action(methods=['get'], detail=False, perms_map={'get': '*'},
            serializer_class=serializers.Serializer)
    def info(self, request, pk=None):
        """个人信息

        个人信息
        """
        user = request.user
        ep, _ = Employee.objects.get_or_create(user=user,
                                               defaults={
                                                   "user": user,
                                                   "name": user.name,
                                                   "phone": user.phone,
                                                   "belong_dept": user.belong_dept,
                                                   "post": user.post,
                                                   "type": user.type
                                               })
        return Response(EmployeeSerializer(instance=ep).data)

    @action(methods=['post'], detail=False, permission_classes=[IsAuthenticated],
            serializer_class=EmployeeImproveSerializer)
    @transaction.atomic
    def improve_info(self, request, *args, **kwargs):
        """完善个人信息

        完善个人信息
        """
        user = request.user
        ep = user.employee
        serializer = EmployeeImproveSerializer(instance=ep, data=request.data)
        serializer.is_valid(raise_exception=True)
        vdata = serializer.validated_data
        if vdata.get('photo', None):
            dhClient.request(**dhapis['person_img_upload'],
                             file_path_rela=vdata['photo'])
        serializer.save()
        if ep.type == 'remployee':
            from apps.rpm.services import sync_to_rep
            sync_to_rep(ep)
        elif ep.type in ['visitor', 'driver']:
            from apps.vm.services import sync_to_visitor
            sync_to_visitor(ep)
        return Response()

    @action(methods=['post'], detail=True, perms_map={'post': 'employee.notworkremark'},
            serializer_class=EmployeeNotWorkRemarkSerializer)
    def not_work_remark(self, request, pk=None):
        """
        填写离岗说明
        """
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        obj = self.get_object()
        if not obj.is_atwork:
            remark = request.data.get('not_work_remark', '')
            obj.not_work_remark = remark
            obj.save()
            now = timezone.now()
            instance, created = NotWorkRemark.objects.get_or_create(
                not_work_date=now.date(),
                user=obj.user,
                defaults={
                    "not_work_date": now.date(),
                    "user": obj.user,
                    "remark": remark,
                    "create_by": request.user,
                }
            )
            if not created:
                instance.remark = remark
                instance.update_by = request.user
                instance.save()
            return Response()
        raise ParseError(**NO_NEED_LEVEL_REMARK)

    @transaction.atomic
    @action(methods=['post'], detail=True, perms_map={'post': 'employee.channel_authority'},
            serializer_class=serializers.Serializer)
    def channel_authority(self, request, pk=None):
        """重新门禁授权

        重新门禁授权
        """
        obj = self.get_object()
        if obj.third_info.get('dh_face_card', None):
            HrmService.door_auth(ep=obj)
        else:
            raise ParseError('该员工缺少主卡')
        # objs = Employee.objects.filter(pk__in=vdata['pks'], third_info__dh_face_card__isnull=False)
        # infos = objs.values('third_info')
        # cards = []
        # for i in infos:
        #     if isinstance(i['third_info'], dict) and 'dh_face_card' in i['third_info']:
        #         cards.append(i['third_info']['dh_face_card'])
        # details = []
        # for i in vdata['channels']:
        #     details.append({
        #         "privilegeType": 1,
        #         "resouceCode": i
        #     })
        # if cards and details:
        #     json_data = {
        #         "cardNumbers": cards,
        #         "timeQuantumId": 1,
        #         "cardPrivilegeDetails": details
        #     }
        #     dhClient.request(**dhapis['card_door_authority'], json=json_data)
        #     for i in objs:
        #         i.third_info['dh_channels'] = vdata['channels']
        #     Employee.objects.bulk_update(objs, fields=['third_info'])
        return Response()

    @transaction.atomic
    @action(methods=['post'], detail=False, perms_map={'post': 'employee.face_bind_1'},
            serializer_class=serializers.Serializer)
    def face_bind_1(self, request, pk=None):
        """同步人脸库1

        全部人脸库
        """
        # 获取设备
        # json_data = {
        #     "pageNum": 1,
        #     "pageSize": 1000,
        #     "ownerCodes": ['001'],
        #     "showChildNodeData": 1,
        #     # "isOnline":1
        # }
        # _, res = dhClient.request(**dhapis['dev_page'], json=json_data)
        # devs = []
        # if res['pageData']:
        #     for i in res['pageData']:
        #         devs.append(i['deviceCode'])
        # 编辑人像库
        json_data = {
            "groupid": settings.DAHUA_FACEGROUPID_1,
            "groupname": "全体人员",
            "groupdetail": "全体人员",
            "grouptype": 3,
            "deviceCodeList": [settings.DAHUA_IVSS_CODE],
            "syncState": 0
        }
        dhClient.request(**dhapis['face_group_update'], json=json_data)
        # 人像绑定
        dhClient.face_bind()
        return Response()

    @action(methods=['get'], detail=False, perms_map={'get': 'employee.face_bind_1'},
            serializer_class=serializers.Serializer)
    def face_status_1(self, request, pk=None):
        """人像下发状态

        人像下发状态
        """
        params = {'id': settings.DAHUA_FACEGROUPID_1}
        _, res = dhClient.request(**dhapis['face_group_info'], params=params)
        return Response(res)

    @action(methods=['get'], detail=False, perms_map={'get': '*'},
            serializer_class=serializers.Serializer)
    def export_excel(self, request, pk=None):
        """导出excel
        导出excel
        """
        field_data = ['人员类型', '人员', '手机号', '身份证号', '所属部门', '在职状态', '定位卡号']
        queryset = self.filter_queryset(self.get_queryset())
        if queryset.count() > 1000:
            raise ParseError('数据量超过1000,请筛选后导出')
        odata = EmployeeSerializer(queryset, many=True).data
        # 处理数据
        data = []
        for i in odata:
            data.append(
                [epTypeOptions[i['type']],
                 i['name'],
                 i['phone'],
                 i['id_number'],
                 i.get('belong_dept_name', ''),
                 epStateOptions[i['job_state']],
                 i['blt_'].get('code', '') if 'blt_' in i and i['blt_'] else '']
            )
        return Response({'path': export_excel(field_data, data, '人员信息')})


class AttendanceViewSet(CustomModelViewSet):
    """
    list: 到岗记录

    到岗记录
    """
    queryset = Attendance.objects.all()
    serializer_class = AttendanceSerializer
    select_related_fields = ['user',
                             'user__belong_dept', 'user__post', 'shift', 'team']
    filterset_fields = ['user',
                        'user__belong_dept', 'user__post', 'state', 'work_date', 'user__name', 'user__phone']
    search_fields = ['user__name', 'user__phone']
    ordering = ['-work_date', 'shift', '-create_time']
    ordering_fields = ['work_date', 'shift', 'create_time']


class ClockRecordViewSet(BulkCreateModelMixin, ListModelMixin, BulkDestroyModelMixin, CustomGenericViewSet):
    """
    打卡记录
    """
    perms_map = {'get': '*', 'post': 'clockrecord.create',
                 'delete': 'clockrecord.delete'}
    queryset = ClockRecord.objects.all()
    select_related_fields = ['employee']
    search_fields = ['employee__name', 'employee__number', 'employee__phone']
    serializer_class = ClockRecordListSerializer
    create_serializer_class = ClockRecordCreateSerializer
    filterset_class = ClockRecordFilterSet
    ordering = ['-create_time']

    @action(methods=['get'], detail=False, perms_map={'get': '*'},
            serializer_class=serializers.Serializer)
    def export_excel(self, request, pk=None):
        """导出excel
        导出excel
        """
        field_data = ['人员类型', '人员', '编号', '身份证号',
                      '所属部门', '触发形式', '打卡时间', '打卡推测', '异常推测']
        queryset = self.filter_queryset(self.get_queryset())
        odata = ClockRecordListSerializer(queryset, many=True).data
        # 处理数据
        data = []
        for i in odata:
            data.append(
                [epTypeOptions[i['employee_']['type']],
                 i['employee_']['name'],
                 i['employee_']['number'],
                 i['employee_']['id_number'],
                 i['employee_'].get('belong_dept_name', ''),
                 i['detail'].get('deviceName', None),
                 i['create_time'],
                 crOptions[i['type']],
                 crEoptions[i['exception_type']] if i['exception_type'] else '']
            )
        return Response({'path': export_excel(field_data, data, '打卡记录')})

    @action(methods=['post'], detail=False, perms_map={'post': '*'},
            serializer_class=serializers.Serializer, logging_methods=[])
    def dahua(self, request):
        """
        大华刷脸分页带my_info

        大华刷脸分页带my_info
        """
        request.data.update({
            "openType": "61",
        })
        _, res = dhClient.request(**dhapis['swipe_list'], json=request.data)
        ids = []
        if res.get('pageData', None):
            for i in res['pageData']:
                ids.append(i['id'])
            crs_info = ClockRecordSimpleSerializer(
                instance=ClockRecord.objects.filter(detail__id__in=ids), many=True).data
            crs_dict = {}
            for i in crs_info:
                crs_dict[i['detail']['id']] = i
            for i in res['pageData']:
                i['my_info'] = {}
                if i['id'] in crs_dict:
                    i['my_info'] = crs_dict[i['id']]
        return Response(res)

    # @action(methods=['post'], detail=False, perms_map={'post': '*'},
    #         serializer_class=CorrectSerializer)
    # def correct_swip(self, request, pk=None):
    #     """
    #     重跑一段时间的打卡记录

    #     重跑一段时间的打卡记录
    #     """
    #     sr = CorrectSerializer(data=request.data)
    #     sr.is_valid(raise_exception=True)
    #     vdata = sr.validated_data
    #     from apps.hrm.tasks import correct_swip_task
    #     correct_swip_task.delay(vdata['start_time'], vdata['end_time'])
    #     return Response()

    # @action(methods=['post'], detail=False, perms_map={'post': '*'},
    #         serializer_class=CorrectSerializer)
    # def correct_enter_or_exit(self, request, pk=None):
    #     """
    #     变更一段时间日志刷脸类型

    #     变更一段时间日志刷脸类型
    #     """
    #     from apps.monitor.models import DrfRequestLog
    #     sr = CorrectSerializer(data=request.data)
    #     sr.is_valid(raise_exception=True)
    #     vdata = sr.validated_data
    #     for i in DrfRequestLog.objects.filter(path='/api/third/dahua/c_swip/', data__contains='办公楼考勤面板'
    #                                           , create_time__gte=vdata['start_time']
    #                                           , create_time__lte=vdata['end_time']).filter(data__contains = "'enterOrExit': 1" ):
    #         data = i.data
    #         i.data = data.replace("'enterOrExit': 1", "'enterOrExit': 3")
    #         i.save()
    #     return Response()


class NotWorkRemarkViewSet(ListModelMixin, CustomGenericViewSet):
    """
    离岗说明
    """
    perms_map = {'get': '*'}
    queryset = NotWorkRemark.objects.all()
    select_related_fields = ['user']
    serializer_class = NotWorkRemarkListSerializer
    filterset_class = NotWorkRemarkFilterSet
    ordering = ['-pk']


class CertificateViewSet(CustomModelViewSet):
    queryset = Certificate.objects.all()
    create_serializer_class = CertificateCreateUpdateSerializer
    update_serializer_class = CertificateCreateUpdateSerializer
    serializer_class = CertificateSerializer
    filterset_class = CertificateFilterSet
    search_fields = ['name', 'number', 'employee__name']

    def perform_create(self, serializer):
        ins: Certificate = serializer.save()
        ins.get_state(need_update=True)

    def perform_update(self, serializer):
        ins: Certificate = serializer.save()
        ins.get_state(need_update=True)