from apps.third.filters import TDeviceFilterSet, DoorAuthFilter
from apps.third.models import BltBind, TDevice, Tlog, DoorAuth
from apps.third.serializers import BindAreaSerializer, BltBindCreateSerializer, BltQuerySerializer, BltSerializer, LabelLocationSerializer, TDeviceSerializer, TDeviceUpdateSerializer, TlogSerializer, DoorAuthSerializer
from apps.utils.viewsets import CustomGenericViewSet
from rest_framework.mixins import ListModelMixin, CreateModelMixin
from apps.third.dahua import dhClient
from apps.third.xunxi import xxClient
from apps.third.speaker import spClient
from apps.third.tapis import xxapis, dhapis, spapis
from rest_framework.response import Response
from rest_framework.serializers import Serializer
from rest_framework.decorators import action
from apps.am.models import Area
from rest_framework.views import APIView
from rest_framework.exceptions import ParseError
from django.db import transaction
from rest_framework.mixins import ListModelMixin, CreateModelMixin, DestroyModelMixin, UpdateModelMixin
from apps.utils.serializers import PkSerializer
from apps.hrm.serializers import EmployeeShortSerializer
from apps.hrm.models import Employee
from django.core.cache import cache


class BltViewSet(CustomGenericViewSet):
    """定位标签列表

    定位标签列表
    """
    perms_map = {}
    queryset = TDevice.objects.filter(type=TDevice.DEVICE_BLT)
    serializer_class = TDeviceSerializer

    @action(methods=['get'], detail=False, perms_map={'get': '*'})
    def count_bind(self, request):
        """统计绑定定位卡人/设备数

        统计绑定定位卡人/设备数
        """
        qs = self.queryset.exclude(employee=None)
        ret = {}
        ret['total'] = qs.count()
        ret['count_employee'] = qs.filter(employee__type='employee').count()
        ret['count_remployee'] = qs.filter(employee__type='remployee').count()
        ret['count_visitor'] = qs.filter(employee__type='visitor').count()
        ret['count_driver'] = qs.filter(employee__type='driver').count()
        return Response(ret)

    @action(methods=['get'], detail=False, perms_map={'get': '*'})
    def count_now(self, request):
        """统计在厂且绑定标签数

        统计在厂且绑定标签数
        """
        json = {
            "pageNum": 1,
            "numPerPage": 2000,
            "online": "online"
        }
        _, res = xxClient.request(**xxapis['blt_list'], json=json)
        ret = {}
        ret['total_blt'] = res['totalCount']
        blt_list = res['recordList']
        macs = []
        for i in blt_list:
            if 'online' in i and i['online']:
                macs.append(i['mac'])
        qs = self.queryset.filter(code__in=macs).exclude(employee=None)
        ret['total'] = qs.count()
        ret['count_employee'] = qs.filter(employee__type='employee').count()
        ret['count_remployee'] = qs.filter(employee__type='remployee').count()
        ret['count_visitor'] = qs.filter(employee__type='visitor').count()
        ret['count_driver'] = qs.filter(employee__type='driver').count()
        return Response(ret)

    @action(methods=['post'], detail=False, perms_map={'post': 'blt.all'},
            serializer_class=BltQuerySerializer, logging_methods=[])
    def all(self, request):
        """全部在线标签列表信息

        全部在线标签列表信息
        """
        data = request.data
        area = None
        if data.get('area', None):
            try:
                area = Area.objects.get(id=data['area'])
                railId = area.third_info['xx_rail']['id']
            except Exception:
                raise ParseError('围栏未绘制')
            json = {
                "railId": railId,
                "type": ""
            }
            _, res = xxClient.request(**xxapis['rail_ibeacon_list'], json=json)
        else:
            json = {
                "pageNum": 1,
                "numPerPage": 2000,
                "online": "online"
            }
            _, res = xxClient.request(**xxapis['blt_list'], json=json)
        count_people = 0
        blt_list = res['recordList']
        macs = []
        for i in blt_list:
            if 'online' in i and i['online'] is False:
                pass
            else:
                if 'userId' in i:
                    i['mac'] = i['userId']
                macs.append(i['mac'])
        qs = self.queryset.filter(code__in=macs).exclude(employee=None)
        if data.get('depts', []):
            qs = qs.filter(employee__belong_dept=data['depts'])
        qs_data = BltSerializer(instance=qs, many=True).data
        qs_dict = {}
        for i in qs_data:
            qs_dict[i['code']] = i
        blt_list_n = []
        for i in blt_list:
            i['my_info'] = {}
            if i['mac'] in qs_dict:
                i['my_info'] = qs_dict[i['mac']]
                blt_list_n.append(i)
        if area:
            # 更新区域下的总人数
            count_people = qs.filter(obj_cate='people').count()
            area.count_people = count_people
            area.save()
        return Response(blt_list_n)


class TDeviceViewSet(ListModelMixin, UpdateModelMixin, DestroyModelMixin, CustomGenericViewSet):
    """
    三方设备接口
    """
    perms_map = {'get': '*', 'put': 'tdevice.update',
                 'delete': 'tdevice.delete'}
    queryset = TDevice.objects.all()
    serializer_class = TDeviceSerializer
    update_serializer_class = TDeviceUpdateSerializer
    ordering = ['-create_time']
    filterset_class = TDeviceFilterSet
    select_related_fields = ['employee', 'area',
                             'employee__post', 'employee__belong_dept']

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
        else:
            serializer = self.get_serializer(queryset, many=True)
        data = serializer.data
        typex = self.request.query_params.get('type', None)
        if typex == str(TDevice.DEVICE_BLT):  # 如果是定位标签加载实时的三方信息
            macs = []
            for i in data:
                macs.append(i['code'])
            json = {
                "macList": macs
            }
            _, res = xxClient.request(**xxapis['blt_info'], json=json)
            macs_dict = {}
            for i in res['success']:
                macs_dict[i['mac']] = i
            for i in res['error']:
                macs_dict[i['mac']] = i
            for i in data:
                i['third_info'] = macs_dict.get(i['code'], {})
        elif typex == str(TDevice.DEVICE_VCHANNEL):
            codes = [i['code'] for i in data]
            json = {
                'unitTypeList': ["1"],
                'includeSubOwnerCodeFlag': True,
                'channelCodeList': codes,
                'pageSize': len(codes)
            }
            _, res = dhClient.request(**dhapis['channel_list'], json=json)
            codes_dict = {}
            for i in res['pageData']:
                codes_dict[i['channelCode']] = i
            for i in data:
                i['third_info'] = codes_dict.get(i['code'], {})
        if page is not None:
            return self.get_paginated_response(data)
        else:
            return Response(data)

    # @action(methods=['post'], detail=False, perms_map={'post': '*'},
    #         serializer_class=PkSerializer)
    # def start_mtask(self, request):
    #     """开启视频算法监控

    #     开启视频算法监控
    #     """
    #     sr = PkSerializer(data=request.data)
    #     sr.is_valid(raise_exception=True)
    #     vdata = sr.validated_data
    #     from apps.ecm.tasks import monitor_check
    #     monitor_check(vdata)
    #     return Response()

    # @action(methods=['post'], detail=False, perms_map={'post': '*'},
    #         serializer_class=PkSerializer)
    # def stop_mtask(self, request):
    #     """停止视频算法监控

    #     停止视频算法监控
    #     """
    #     sr = PkSerializer(data=request.data)
    #     sr.is_valid(raise_exception=True)
    #     vdata = sr.validated_data
    #     vcids = TDevice.objects.filter(id__in=vdata, type=TDevice.DEVICE_VCHANNEL).values_list('id', flat=True)
    #     for id in vcids:
    #         ckey = 'vchannel_' + id
    #         cache.delete(ckey)
    #     return Response()

    @action(methods=['post'], detail=False, perms_map={'post': '*'},
            serializer_class=Serializer)
    @transaction.atomic
    def blt_sync(self, request):
        """同步标签mac至平台

        同步标签mac至平台
        """
        json = {
            "pageNum": 1,
            "numPerPage": 1000
        }
        _, res = xxClient.request(**xxapis['blt_list'], json=json)
        blt_list = res['recordList']
        for i in blt_list:
            TDevice.objects.get_or_create(code=i['mac'], defaults={
                                          "code": i['mac'], "type": TDevice.DEVICE_BLT})
        return Response()

    @action(methods=['post'], detail=False, perms_map={'post': '*'},
            serializer_class=Serializer)
    @transaction.atomic
    def speaker_sync(self, request):
        """同步喇叭通道

        同步喇叭通道
        """
        params = {
            "page": 1,
            "pageSize": 1000
        }
        _, res = spClient.request(**spapis['device_list'], params=params)
        rows = res.get('rows', [])
        t_l = []
        filtered_rows = [i for i in rows if i['name'] != '采集器']
        for i in filtered_rows:
            t_l.append(i['sn'])
            td = TDevice.objects.filter(code=i['sn']).first()
            if td:
                pass
            else:
                td = TDevice(code=i['sn'], type=TDevice.DEVICE_SPEAKER)
            td.name = i['name']
            td.save()
        TDevice.objects.filter(type=TDevice.DEVICE_SPEAKER).exclude(
            code__in=t_l).delete()  # 移除不需要的
        return Response()

    @action(methods=['post'], detail=False, perms_map={'post': '*'},
            serializer_class=Serializer)
    def vchannel_sync(self, request):
        """同步视频通道

        同步视频通道
        """
        json = {
            "pageNum": 1,
            "pageSize": 1000,
            'unitTypeList': ["1"],
            'includeSubOwnerCodeFlag': True
        }
        _, res = dhClient.request(**dhapis['channel_list'], json=json)

        if res.get('pageData', None):
            t_l = []
            for i in res['pageData']:
                t_l.append(i['channelCode'])
                td = TDevice.objects.filter(code=i['channelCode']).first()
                if td:
                    pass
                else:
                    td = TDevice(code=i['channelCode'],
                                 type=TDevice.DEVICE_VCHANNEL)
                td.name = i['channelName']
                td.save()
            TDevice.objects.filter(type=TDevice.DEVICE_VCHANNEL).exclude(
                code__in=t_l).delete()
        return Response()

    @action(methods=['post'], detail=False, perms_map={'post': '*'},
            serializer_class=Serializer)
    @transaction.atomic
    def dchannel_sync(self, request):
        """同步门禁通道

        同步门禁通道
        """
        json = {
            "pageNum": 1,
            "pageSize": 1000,
            'unitTypeList': ["7"],
            'includeSubOwnerCodeFlag': True
        }
        _, res = dhClient.request(**dhapis['channel_list'], json=json)
        if res.get('pageData', None):
            for i in res['pageData']:
                td = TDevice.objects.filter(code=i['channelCode']).first()
                if td:
                    pass
                else:
                    td = TDevice(code=i['channelCode'],
                                 type=TDevice.DEVICE_DCHANNEL)
                td.name = i['channelName']
                # td.access_list = ['employee', 'remployee', 'visitor']
                td.save()
        return Response()

    @action(methods=['post'], detail=False, perms_map={'post': '*'},
            serializer_class=BltBindCreateSerializer)
    @transaction.atomic
    def blt_bind(self, request):
        """绑定/解绑定位卡

        绑定/解绑定位卡
        """
        serializer = BltBindCreateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        vdata = serializer.validated_data
        code = vdata['code']
        blt = TDevice.objects.filter(
            code=code, type=TDevice.DEVICE_BLT).first()
        if blt:
            if vdata['type'] == BltBind.BLT_BIND and vdata['employee']:
                if blt.employee:
                    raise ParseError('该定位卡已绑定人员,请先解绑')
                else:
                    blt.employee = vdata['employee']
                    blt.obj_cate = 'people'
                    blt.save()
                    vdata['obj_cate'] = 'people'
                    vdata.pop('code')
                    vdata['blt'] = blt
                    BltBind.objects.create(**vdata)
            elif vdata['type'] == BltBind.BLT_UNBIND:
                ep_old = blt.employee
                if blt.employee:
                    blt.employee = None
                    blt.save()
                    vdata['obj_cate'] = 'people'
                    vdata.pop('code')
                    vdata['blt'] = blt
                    vdata['employee'] = ep_old
                    BltBind.objects.create(**vdata)
        else:
            raise ParseError('该定位卡在系统中不存在')
        return Response()

    @action(methods=['post'], detail=False, perms_map={'post': '*'},
            serializer_class=Serializer, logging_methods=[])
    def blt(self, request):
        """定位标签列表

        定位标签列表
        """
        _, res = xxClient.request(**xxapis['blt_list'], json=request.data)
        macs = []
        for i in res['recordList']:
            macs.append(i['mac'])
        qs = self.queryset.filter(code__in=macs)
        qs_data = BltSerializer(instance=qs, many=True).data
        qs_dict = {}
        for i in qs_data:
            qs_dict[i['code']] = i
        for i in res['recordList']:
            i['my_info'] = {}
            if i['mac'] in qs_dict:
                i['my_info'] = qs_dict[i['mac']]
        return Response(res)

    @action(methods=['post'], detail=False, perms_map={'post': '*'},
            serializer_class=Serializer, logging_methods=[])
    def vchannel(self, request):
        """
        视频通道列表

        视频通道列表
        """
        request.data.update({
            'unitTypeList': ["1"],
            'includeSubOwnerCodeFlag': True
        })
        _, res = dhClient.request(**dhapis['channel_list'], json=request.data)
        codes = []
        if res.get('pageData', None):
            for i in res['pageData']:
                codes.append(i['channelCode'])
            tds_info = TDeviceSerializer(
                instance=TDevice.objects.filter(code__in=codes), many=True).data
            tds_dict = {}
            for i in tds_info:
                tds_dict[i['code']] = i
            for i in res['pageData']:
                i['my_info'] = {}
                if i['channelCode'] in tds_dict:
                    i['my_info'] = tds_dict[i['channelCode']]
        return Response(res)

    @action(methods=['post'], detail=False, perms_map={'post': '*'},
            serializer_class=Serializer, logging_methods=[])
    def speaker(self, request):
        """
        喇叭列表

        喇叭列表
        """
        # print(request.data)
        _, res = spClient.request(**spapis['device_list'], params=request.data)
        codes = []
        filtered_rows = [i for i in res.get('rows', []) if i['name'] != '采集器']
        for i in filtered_rows:
            codes.append(i['sn'])
        tds_info = TDeviceSerializer(
            instance=TDevice.objects.filter(code__in=codes), many=True).data
        tds_dict = {}
        for i in tds_info:
            tds_dict[i['code']] = i
        for i in filtered_rows:
            i['my_info'] = {}
            if i['sn'] in tds_dict:
                i['my_info'] = tds_dict[i['sn']]
        res['rows'] = filtered_rows
        return Response(res)

    @action(methods=['post'], detail=False, perms_map={'post': '*'},
            serializer_class=Serializer, logging_methods=[])
    def dchannel(self, request):
        """
        闸机通道列表

        闸机通道列表
        """
        request.data.update({
            'unitTypeList': ["7"],
            'includeSubOwnerCodeFlag': True
        })
        _, res = dhClient.request(**dhapis['channel_list'], json=request.data)
        codes = []
        if res.get('pageData', None):
            for i in res['pageData']:
                codes.append(i['channelCode'])
            tds_info = TDeviceSerializer(
                instance=TDevice.objects.filter(code__in=codes), many=True).data
            tds_dict = {}
            for i in tds_info:
                tds_dict[i['code']] = i
            for i in res['pageData']:
                i['my_info'] = {}
                if i['channelCode'] in tds_dict:
                    i['my_info'] = tds_dict[i['channelCode']]
        return Response(res)

    @action(methods=['post'], detail=False, perms_map={'post': '*'},
            serializer_class=Serializer, logging_methods=[])
    def dchannel_auth(self, request):
        """
        门禁权限

        门禁权限
        """
        _, res = dhClient.request(
            **dhapis['card_door_authority_list'], json=request.data)
        codes = []
        if res.get('pageData', None):
            for i in res['pageData']:
                codes.append(i['cardNumber'])
            eps_info = EmployeeShortSerializer(
                instance=Employee.objects.filter(third_info__dh_face_card__in=codes), many=True).data
            eps_dict = {}
            for i in eps_info:
                eps_dict[i['third_info']['dh_face_card']] = i
            for i in res['pageData']:
                i['my_info'] = {}
                if i['cardNumber'] in eps_dict:
                    i['my_info'] = eps_dict[i['cardNumber']]
        return Response(res)

    @action(methods=['post'], detail=True, perms_map={'post': 'tdevice.label_location'},
            serializer_class=LabelLocationSerializer)
    def label_location(self, request, pk=None):
        """
        标注坐标位置

        标注坐标位置
        """
        obj = self.get_object()
        sr = LabelLocationSerializer(instance=obj, data=request.data)
        sr.is_valid(raise_exception=True)
        sr.save()
        return Response()
        # serializer = self.get_serializer(data=request.data)
        # serializer.is_valid(raise_exception=True)
        # vdata = serializer.validated_data
        # td = TDevice.objects.filter(code=vdata['code']).first()
        # if td:
        #     td.location = vdata['location']
        #     td.type = vdata['type']
        #     td.area = vdata['area']
        #     td.name = vdata['name']
        #     td.update_by = request.user
        #     td.save()
        #     td.areas.clear()
        #     for i in vdata['areas']:
        #         td.areas.add(i)
        # else:
        #     td = TDevice()
        #     td.type = vdata['type']
        #     td.code = vdata['code']
        #     td.location = vdata['location']
        #     td.area = vdata['area']
        #     td.name = vdata['name']
        #     td.create_by = request.user
        #     td.save()
        #     td.areas.clear()
        #     for i in vdata['areas']:
        #         td.areas.add(i)
        # return Response()

    @action(methods=['post'], detail=False, perms_map={'post': 'tdevice.bind_area'},
            serializer_class=BindAreaSerializer)
    def bind_area(self, request):
        """
        批量绑定所在区域

        批量绑定所在区域
        """
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        vdata = serializer.validated_data
        TDevice.objects.filter(id__in=vdata['ids']).update(area=vdata['area'])
        return Response()
        # area = Area.objects.get(id=vdata['area'])
        # for i in vdata['codes']:
        #     td = TDevice.objects.filter(code=i['code']).first()
        #     if td:
        #         td.area = area
        #         td.update_by = request.user
        #         td.save()
        #     else:
        #         td = TDevice()
        #         td.type = TDevice.DEVICE_VCHANNEL
        #         td.code = i['code']
        #         td.area = area
        #         td.create_by = request.user
        #         td.save()
        # return Response()


class TlogViewSet(ListModelMixin, CustomGenericViewSet):
    perms_map = {'get': '*'}
    queryset = Tlog.objects.all()
    serializer_class = TlogSerializer
    filterset_fields = ['result', 'id']


class DoorAuthViewSet(ListModelMixin, DestroyModelMixin, CustomGenericViewSet):
    """
    list: 门禁权限

    门禁权限
    """
    perms_map = {'get': '*', 'delete': 'doorauth.delete'}
    queryset = DoorAuth.objects.all()
    serializer_class = DoorAuthSerializer
    filterset_class = DoorAuthFilter
    select_related_fields = ['dchannel', 'employee']
    search_fields = ['employee__name']
    ordering = '-create_time'

    @transaction.atomic
    def perform_destroy(self, instance):
        dh_face_card = instance.employee.third_info['dh_face_card']
        dh_id = instance.employee.third_info['dh_id']
        rdict = {"personIdsString": str(dh_id),
                 "cardNumberString": str(dh_face_card), "channelCode": instance.dchannel.code}
        dhClient.request(**dhapis['card_door_authority_delete'], json=rdict)
        instance.delete()
