from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin
from rest_framework.decorators import action
from apps.ability.models import QAction, QActionItem, QOrg, QTask, Quali, QualiLib
from apps.ability.serializers_qtask import QActionDetailSerializer, QActionListSerializer, QActionQualiCreateSerializer, QActionQualiUpdateSerializer, QActionServiceSerializer, QOrgListSerializer, QTaskCreateUpdateSerializer, QTaskListSerializer, QualiCreateSerializer, QualiLibListSerializer, QualiListSerializer, QualiSerializer, QualiUpdateSerializer
from django.db import transaction
from rest_framework.response import Response
from rest_framework import status
from apps.system.mixins import CreateUpdateCustomMixin
from utils.pagination import PageOrNot
from rest_framework.exceptions import ParseError
from rest_framework import serializers
from rest_framework.exceptions import ParseError

class QualiLibViewSet(PageOrNot, ListModelMixin, GenericViewSet):
    perms_map = {'get': '*'}
    queryset = QualiLib.objects.all()
    serializer_class = QualiLibListSerializer
    search_fields = ['name']
    ordering = ['-create_time']

class QualiViewSet(ListModelMixin, GenericViewSet):
    perms_map = {'get': '*'}
    queryset = Quali.objects.all()
    serializer_class = QualiListSerializer
    search_fields = ['name', 'type', 'grade']
    ordering = ['org__sort']

class QTaskViewSet(CreateUpdateCustomMixin, CreateModelMixin, ListModelMixin, UpdateModelMixin, GenericViewSet):
    perms_map = {'get': 'qtask_view', 'post': 'qtask_create'}
    queryset = QTask.objects.all()
    serializer_class = QTaskListSerializer
    ordering = ['-create_time']

    def get_serializer_class(self):
        if self.action in ['create', 'update']:
            return QTaskCreateUpdateSerializer
        return super().get_serializer_class()
    
    @action(methods=['put'], detail=True, perms_map = {'put':'qtask_start'})
    @transaction.atomic
    def start(self, request, *args, **kwargs):
        """
        发布任务
        """
        obj = self.get_object()
        if obj.state == '待发布':
            obj.state = '进行中'
            obj.save()
            QOrg.objects.filter(qtask=obj).update(state='待报送')
            return Response()
        return Response('任务状态错误', status=status.HTTP_400_BAD_REQUEST)

class QOrgViewSet(ListModelMixin, GenericViewSet):
    perms_map = {'get': 'qtask_view'}
    queryset = QOrg.objects.select_related('qtask', 'org')
    filterset_fields = ['qtask', 'org', 'qtask__state']
    serializer_class = QOrgListSerializer
    ordering = ['-create_time']

    @action(methods=['get'], detail=False, perms_map = {'post':'qtask_my'})
    def my(self, request, *args, **kwargs):
        """
        我的报送任务
        """
        user = self.request.user
        queryset = self.filter_queryset(self.get_queryset().filter(org=user.dept))

        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)

def cal_count(qtask, org):
    qs = QAction.objects.filter(qtask=qtask, belong_dept=org)
    qorg = QOrg.objects.get(qtask=qtask, org=org)
    qorg.count = qs.count()
    qorg.count_confirmed = qs.filter(confirmed=True).count()
    qorg.save()


class QActionViewSet(PageOrNot, ListModelMixin, DestroyModelMixin, RetrieveModelMixin,GenericViewSet):
    perms_map = {'get': 'qtask_view'}
    queryset = QAction.objects.select_related('file', 'atype', 'afield', 'qtask', 'belong_dept')
    filterset_fields = ['qtask', 'belong_dept', 'atype', 'afield']

    def get_serializer_class(self):
        if self.action == 'list':
            return QActionListSerializer
        elif self.action == 'retrieve':
            return QActionDetailSerializer
        return super().get_serializer_class()

    @action(methods=['get'], detail=False, perms_map = {'post':'qaction_my'})
    def my(self, request, *args, **kwargs):
        """
        我的报送操作
        """
        user = self.request.user
        queryset = self.filter_queryset(self.get_queryset().filter(belong_dept=user.dept))

        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)
    
    def perform_destroy(self, instance):
        if not instance.confirmed:
            instance.delete(soft=False)
        raise ParseError('报送已确认, 不可删除')

    @action(methods=['post'], detail=False,
            perms_map = {'post':'qaction_create'}, serializer_class=QActionServiceSerializer)
    @transaction.atomic
    def service_update(self, request, *args, **kwargs):
        """
        更新提供服务
        """
        user = request.user
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save(create_by=user, belong_dept=user.dept)
        vdata = serializer.validated_data
        cal_count(vdata['qtask'], user.dept)
        return Response()

    @action(methods=['post'], detail=False,
            perms_map = {'post':'qaction_create'}, serializer_class=QActionQualiCreateSerializer)
    @transaction.atomic
    def quali_create(self, request, *args, **kwargs):
        """
        新增资质
        """
        user = request.user
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save(create_by=user, belong_dept=user.dept)
        vdata = serializer.validated_data
        cal_count(vdata['qtask'], user.dept)
        return Response()

    @action(methods=['post'], detail=False,
            perms_map = {'post':'qaction_update'}, serializer_class=QActionQualiUpdateSerializer)
    @transaction.atomic
    def quali_update(self, request, *args, **kwargs):
        """
        修改资质
        """
        user = request.user
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save(create_by=user, belong_dept=user.dept)
        vdata = serializer.validated_data
        cal_count(vdata['qtask'], user.dept)
        return Response()
    
    @action(methods=['post'], detail=False,
            perms_map = {'post':'ability_create'}, serializer_class=QActionQualiCreateSerializer)
    @transaction.atomic
    def ability_create(self, request, *args, **kwargs):
        """
        新增能力
        """
        user = request.user
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save(create_by=user, belong_dept=user.dept)
        vdata = serializer.validated_data
        cal_count(vdata['qtask'], user.dept)
        return Response()

    @action(methods=['put'], detail=True, perms_map = {'put':'qaction_confirm'},
            serializer_class=serializers.Serializer)
    @transaction.atomic
    def confirm(self, request, *args, **kwargs):
        """
        确认
        """
        obj = self.get_object()
        if obj.confirmed:
            raise ParseError('该动作已确认')
        if obj.action == 'service.update':
            org = obj.org
            org.service = obj.service
            org.save()
        elif obj.action == 'quali:create':
            serializer = QualiCreateSerializer(data=obj.value2)
            serializer.save(org=obj.belong_dept, create_by=obj.create_by)
        elif obj.action == 'quali:update':
            quali = Quali.objects.get(id=obj.value2.get('id'))
            old_data = QualiSerializer(instance=quali).data
            obj.value1 = old_data
            s = QualiUpdateSerializer(instance=quali, data=obj.value2)
            s.save(update_by=obj.create_by)
            # 比较差别
            for k, v in obj.value2.items():
                if v != old_data[k]:
                    QActionItem.objects.create(action='update', field=k, vaule1=old_data[k], value2=v, qaction=obj)
                if k == 'citys':
                    old_citys = set(old_data['citys'])
                    new_citys = set(v)
                    removes = old_citys.difference(new_citys)
                    adds = new_citys.difference(old_citys)
                    for i in removes:
                        QAction.objects.create(action='city:remove', field='citys', city=i, qaction=obj)
                    for i in adds:
                        QAction.objects.create(action='city:add', field='citys', city=i, qaction=obj)
        elif obj.action == 'ability:create':
            pass
        obj.confirmed = True
        obj.save()
        return Response(status=status.HTTP_200_OK)
        
        


    