
from threading import Thread

from django.db import transaction
from django.db.models import Count, F
from django.utils import timezone
from rest_framework import serializers
from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied
from rest_framework.mixins import (CreateModelMixin, DestroyModelMixin,
                                   ListModelMixin, RetrieveModelMixin,
                                   UpdateModelMixin)
from rest_framework.response import Response
from rest_framework.exceptions import ParseError
from apps.ecm.filters import EventFilterSet
from apps.ecm.models import (AlgoChannel, Event, EventCate, Eventdo,
                             NotifySetting, Remind)
from apps.ecm.serializers import (AlgoChannelCreateSerializer,
                                  AlgoChannelCreatesSerializer,
                                  AlgoChannelSerializer, EventAggSerializer,
                                  EventCateCreateUpdateSerializer,
                                  EventCateListSerializer, EventDetailSerializer,
                                  EventHandleSerializer, EventSerializer, EventSimpleSerializer,
                                  NotifySettingsSerializer, RemindSerializer)
from apps.ecm.service import update_remind_read
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
from apps.utils.export import export_excel_img
from apps.ecm.tasks import monitor_check
from apps.utils.mixins import BulkDestroyModelMixin

obj_cate_dict = {'people': '人员', 'opl': '作业', 'other': '其他'}
mark_dict = {10: '正常', 20: '误报'}

# Create your views here.


class EventCateViewSet(CreateModelMixin, UpdateModelMixin, ListModelMixin, CustomGenericViewSet):
    perms_map = {'get': '*', 'put': 'event_cate.update', 'post': 'event_cate.create'}
    queryset = EventCate.objects.all()
    list_serializer_class = EventCateListSerializer
    create_serializer_class = EventCateCreateUpdateSerializer
    update_serializer_class = EventCateCreateUpdateSerializer
    serializer_class = EventCateListSerializer
    filterset_fields = ['self_algo', 'trigger']
    ordering = ['priority', 'create_time']


class AlgoChannelViewSet(CreateModelMixin, DestroyModelMixin, ListModelMixin, CustomGenericViewSet):
    perms_map = {'get': '*', 'post': 'event_cate.update', 'delete': 'event_cate.update'}
    queryset = AlgoChannel.objects.all()
    create_serializer_class = AlgoChannelCreateSerializer
    serializer_class = AlgoChannelSerializer
    filterset_fields = ['algo']

    @transaction.atomic
    @action(methods=['post'], detail=False, perms_map={'post': 'event_cate.update'},
            serializer_class=AlgoChannelCreatesSerializer)
    def creates(self, request, pk=None):
        """批量添加摄像头

        批量添加摄像头
        """
        serializer = AlgoChannelCreatesSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        vdata = serializer.validated_data
        for i in vdata['vchannels']:
            AlgoChannel.objects.get_or_create(algo=vdata['algo'], vchannel=i,
                                              defaults={
                "algo": vdata['algo'],
                "vchannel": i
            })
        return Response()

    def perform_create(self, serializer):
        ins = serializer.save()
        if ins.always_on:
            monitor_check([ins.vchannel.id])
    
    def perform_destroy(self, instance):
        vid = instance.vchannel.id
        instance.delete()
        monitor_check([vid])
            


class NotifySettingViewSet(CustomModelViewSet):
    queryset = NotifySetting.objects.all()
    serializer_class = NotifySettingsSerializer
    filterset_fields = ['event_cate', 'obj_cate', 'post', 'user']
    ordering = ['sort', 'create_time']


class EventViewSet(ListModelMixin, RetrieveModelMixin, BulkDestroyModelMixin, CustomGenericViewSet):
    perms_map = {'get': '*', 'delete': 'event.delete'}
    queryset = Event.objects.all()
    serializer_class = EventSerializer
    retrieve_serializer_class = EventDetailSerializer
    select_related_fields = ['area', 'employee', 'handle_user', 'vchannel', 'opl']
    prefetch_related_fields = ['cates']
    filterset_class = EventFilterSet

    @transaction.atomic
    @action(methods=['post'], detail=True, perms_map={'post': 'event.handle'},
            serializer_class=EventHandleSerializer)
    def handle(self, request, pk=None):
        """处理事件

        处理事件
        """
        obj = self.get_object()
        # 判断当前用户有无处理权限(废弃, 通过控权实现即可)
        # if (not Remind.objects.filter(event=obj, recipient=request.user, can_handle=True).exists()) and (
        #         not request.user.is_superuser):
        #     raise PermissionDenied('您无权处理该事件')
        data = request.data
        sr = EventHandleSerializer(instance=obj, data=data)
        sr.is_valid(raise_exception=True)
        sr.save(handle_user=request.user, handle_time=timezone.now())
        Thread(target=update_remind_read, args=(obj, request.user), daemon=True).start()
        return Response()

    def retrieve(self, request, *args, **kwargs):
        obj = self.get_object()
        Thread(target=update_remind_read, args=(obj, request.user), daemon=True).start()
        return super().retrieve(request, *args, **kwargs)

    @transaction.atomic
    @action(methods=['post'], detail=False, perms_map={'post': '*'},
            serializer_class=EventAggSerializer, logging_methods=[])
    def cate_agg(self, request, pk=None):
        """按事件分类聚合

        按事件分类聚合
        """
        slr = EventAggSerializer(data=request.data)
        slr.is_valid(raise_exception=True)
        vdata = slr.validated_data
        ret = {}
        queryset = Eventdo.objects.all()
        if vdata.get('start_create', None):
            queryset = queryset.filter(event__create_time__gte=vdata['start_create'])
        if vdata.get('end_create', None):
            queryset = queryset.filter(event__create_time__lte=vdata['end_create'])
        if vdata.get('is_handled', None):
            if vdata['is_handled']:
                queryset = queryset.exclude(event__handle_user=None)
            else:
                queryset = queryset.filter(event__handle_user=None)
        ret['total_count'] = queryset.count()
        if vdata.get('completed', True):
            ret['details'] = list(EventCate.objects.order_by('priority', 'create_time').annotate(cate=F('id'),
                                  cate__name=F('name'), cate__trigger=F('trigger')).values('cate', 'cate__name'))
            for i in ret['details']:
                i['count'] = queryset.filter(cate__id=i['cate']).count()
        else:
            ret['details'] = list(queryset.order_by('cate__priority', 'cate__create_time').values(
                'cate', 'cate__name', 'cate__trigger').annotate(count=Count('cate')))
        return Response(ret)

    @action(methods=['get'], detail=False, perms_map={'get': '*'},
            serializer_class=serializers.Serializer)
    def export_excel(self, request, pk=None):
        """导出excel
        导出excel
        """
        field_data = [
            {"name": "事件种类", "type": "str"},
            {"name": "发生区域", "type": "str"},
            {"name": "事件类型", "type": "str"},
            {"name": "当事人", "type": "str"},
            {"name": "所属作业", "type": "str"},
            {"name": "发生时间", "type": "str"},
            {"name": "处理人", "type": "str"},
            {"name": "事件标记", "type": "str"},
            {"name": "抓拍图", "type": "img"},
            {"name": "人脸图", "type": "img"},
        ]
        queryset = self.filter_queryset(self.get_queryset())
        if queryset.count() > 15000:
            raise ParseError('数量超过15000,请筛选后导出')
        odata = EventSerializer(queryset, many=True).data
        # 处理数据
        data = []

        for i in odata:
            cates_str = ''
            for m in i['cates_']:
                cates_str = cates_str + m['name'] + '/'
            data.append(
                [
                    cates_str,
                    i.get('area_name', None),
                    obj_cate_dict[i['obj_cate']],
                    i.get('employee_name', None),
                    i.get('operation_name', None),
                    i['create_time'],
                    i.get('handle_user_name', None),
                    mark_dict.get(i['mark'], '正常'),
                    i['global_img_compressed'],
                    i['face_img']
                ]
            )
        return Response({'path': export_excel_img(field_data, data, '事件记录')})


class RemindViewSet(ListModelMixin, CustomGenericViewSet):
    perms_map = {'get': '*'}
    queryset = Remind.objects.all()
    serializer_class = RemindSerializer
    select_related_fields = ['recipient', 'event']
    prefetch_related_fields = ['event__cates']
    filterset_fields = ['event', 'event__cates', 'is_read']

    @action(methods=['get'], detail=False, perms_map={'get': '*'})
    def my(self, request, *args, **kwargs):
        """推送给我的

        推送给我的
        """
        user = self.request.user
        queryset = self.filter_queryset(self.get_queryset().filter(recipient=user))

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


# class MyRemindViewSet(ListModelMixin, CustomGenericViewSet):
#     perms_map = {'get': '*'}
#     serializer_class = RemindSerializer
#     select_related_fields = ['recipient', 'event']
#     prefetch_related_fields = ['event__cates']

#     def get_queryset(self):
#         return Remind.objects.filter(recipient=self.request.user)

#     @action(methods=['post'], detail=True, perms_map={'post': '*'})
#     def label_read(self, request, *args, **kwargs):
#         """标记已读

#         标记已读
#         """
