from django.conf import settings
from django.core.cache import cache
from django.db.models import Count, Q
from django.db.models.query import QuerySet
from django.http import request
from django.shortcuts import render
from django.utils import timezone
from rest_framework import status
from rest_framework.decorators import action, permission_classes
from rest_framework.exceptions import PermissionDenied
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin
from rest_framework.permissions import IsAdminUser
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from utils.pagination import PageOrNot

from apps.system.mixins import CreateUpdateCustomMixin, CreateUpdateModelAMixin, OptimizationMixin
from apps.system.models import Organization
from apps.system.permission import get_permission_list, has_permission
from apps.system.permission_data import RbacFilterSet

from .models import *
from .serializers import *
from .permission import IsSubInspectTaskLeader, IsInspectRecordChecker
# Create your views here.
class DocumentViewSet(OptimizationMixin, PageOrNot, CreateUpdateModelAMixin, ModelViewSet):
    perms_map = {'get': '*', 'post': 'qualitydocument_create',
                 'put': 'qualitydocument_update', 'delete': 'qualitydocument_delete'}
    queryset = Document.objects.all()
    serializer_class = DocumentSerializer
    ordering = ['-id']
    search_fields = ['name']


class InspectTemplateViewSet(PageOrNot, CreateUpdateCustomMixin, ModelViewSet):
    """
    检查表模板
    """
    perms_map = {'get': '*', 'post': 'inspectitem',
                 'put': 'inspectitem', 'delete': 'inspectitem'}
    queryset = InspectTemplate.objects.all()
    serializer_class = InspectTemplateSerializer
    ordering = ['id']

class InspectItemViewSet(PageOrNot, CreateUpdateCustomMixin, ModelViewSet):
    """
    检查表清单：增删改查
    """
    perms_map = {'get': '*', 'post': 'inspectitem',
                 'put': 'inspectitem', 'delete': 'inspectitem'}
    queryset = InspectItem.objects.all()
    serializer_class = InspectItemSerializer
    search_fields = ['name', 'require']
    filterset_fields = ['type','cate', 'template']
    ordering = ['sortnum', 'cate__sort', 'create_time']


class InspectTaskViewSet(OptimizationMixin, CreateUpdateCustomMixin, ModelViewSet):
    perms_map = {'get': '*', 'post': 'inspecttask_create',
                 'put': 'inspecttask_update', 'delete': 'inspecttask_delete'}
    queryset = InspectTask.objects.all()
    serializer_class = InspectTaskSerializer
    search_fields = ['name']
    ordering = ['-create_time']

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        instance.delete(soft=False)
        return Response(status=status.HTTP_204_NO_CONTENT)
    
    @action(methods=['put'], detail=True, perms_map = {'put':'inspecttask_start'})
    def start(self, request, *args, **kwargs):
        """
        发布任务
        """
        obj = self.get_object()
        if obj.state != '已完成':
            obj.state = '执行中'
            obj.save()
            # 修改子任务状态
            SubInspectTask.objects.filter(inspecttask=obj, state='待发布').update(state='执行中')
            return Response(status=status.HTTP_200_OK)
        return Response('任务状态错误', status=status.HTTP_400_BAD_REQUEST)


class SubtaskViewSet(PageOrNot, CreateUpdateCustomMixin, OptimizationMixin, ModelViewSet):
    perms_map = {'get': '*', 'post': 'inspecttask_create',
                 'put': 'inspecttask_update', 'delete': 'inspecttask_delete'}
    queryset = SubInspectTask.objects.all()
    serializer_class = SubtaskListSerializer
    filterset_fields = ['inspecttask', 'state']
    ordering = ['-create_time']
    
    def get_queryset(self):
        queryset = self.queryset
        if hasattr(self.get_serializer_class(), 'setup_eager_loading'):
            queryset = self.get_serializer_class().setup_eager_loading(queryset)
        if has_permission('inspecttask_create', self.request.user):
            return queryset
        else:
            return queryset.filter(team_subtask__member__id=self.request.user.id).exclude(state='待发布')

    @action(methods=['get'], detail=False, perms_map = {'get':'*'})
    def self(self, request, *args, **kwargs):
        """
        我的检查任务
        """
        queryset = self.queryset
        queryset = queryset.filter(team_subtask__member=self.request.user).exclude(state='待发布')
        # 筛选
        for backend in list(self.filter_backends):
            queryset = backend().filter_queryset(self.request, queryset, self)
        serializer = SubtaskListSerializer(queryset, many=True)
        return Response(serializer.data)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        instance.delete(soft=False)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def update(self, request, *args, **kwargs):
        instance = self.get_object()
        if request.data.get('name', None):
            instance.name = request.data.get('name')
            instance.update_by = request.user
            instance.save()
        return Response(status=status.HTTP_200_OK)

    @action(methods=['get'], detail=True, perms_map = {'get':'*'})
    def depts(self, request, *args, **kwargs):
        """
        子任务涉及的部门
        """
        obj = self.get_object()
        data =  obj.dept_subtask.filter(subtask=obj).values('dept', 'dept__name', 'state', 'subtask', 'id')
        return Response(data)
    
    @action(methods=['get'], detail=True, perms_map = {'get':'*'})
    def members(self, request, *args, **kwargs):
        """
        子任务的检查组成员
        """
        obj = self.get_object()
        data = obj.team_subtask.filter(subtask=obj).values('member', 'member__name', 'type')
        return Response(data)

    def create(self, request, *args, **kwargs):
        """
        创建子任务
        form:{inspecttask:id, name:'', leader:id, members:[id]}
        """
        obj = SubInspectTask()
        inspecttask = InspectTask.objects.get(pk=request.data['inspecttask'])
        obj.inspecttask = inspecttask
        obj.name = request.data['name']
        obj.create_by = request.user
        obj.save()
        InspectTeam.objects.create(member=User.objects.get(pk=request.data['leader']), type='组长', subtask=obj)
        if request.data.get('members', False) and request.data.get('depts', False):
            members = []
            depts = []
            records = []
            for dept in request.data['depts']:
                mdept = Organization.objects.get(pk=dept)
                if not InspectRecord.objects.filter(dept=mdept, subtask=obj).exists():
                    data = {}
                    data['dept'] = mdept
                    data['subtask'] = obj
                    depts.append(InspectDept(**data))
                    for i in InspectItem.objects.filter(is_deleted=False, template=inspecttask.template):
                        r = {}
                        r['dept'] = mdept
                        r['item'] = i
                        r['subtask'] = obj
                        r['create_by'] = request.user
                        records.append(InspectRecord(**r))
            for member in request.data['members']:
                if member != request.data['leader']:
                    mmember = User.objects.get(pk=member)
                    data = {}
                    data['member'] = mmember
                    data['subtask'] = obj
                    members.append(InspectTeam(**data))
            InspectTeam.objects.bulk_create(members)
            InspectDept.objects.bulk_create(depts)
            InspectRecord.objects.bulk_create(records)
            return Response(status=status.HTTP_201_CREATED)
        return Response('组织和成员不能为空', status=status.HTTP_400_BAD_REQUEST)



class InspectDeptViewSet(OptimizationMixin, ListModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet):
    """
    子任务涉及组织表
    """
    perms_map = {'get':'*', 'put':'inspecttask_update', 'post':'inspecttask_update', 'delete':'inspecttask_update'}
    queryset = InspectDept.objects.all()
    serializer_class = InspectDeptSerializer
    filterset_fields = ['subtask']

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        obj = serializer.save(create_time=timezone.now())
        records = []
        if not InspectRecord.objects.filter(dept=obj.dept, subtask=obj.subtask).exists():
            for i in InspectItem.objects.filter(is_deleted=False, template=obj.subtask.inspecttask.template):
                r = {}
                r['dept'] = obj.dept
                r['item'] = i
                r['subtask'] = obj.subtask
                r['create_by'] = request.user
                records.append(InspectRecord(**r))
            InspectRecord.objects.bulk_create(records)
        return Response(status=status.HTTP_201_CREATED)

    @action(methods=['put'], detail=True, perms_map = {'put':'inspectrecord_update'})
    def start(self, request, *args, **kwargs):
        """
        对该组织开始检查
        """
        obj = self.get_object()

        if request.user == InspectTeam.objects.get(subtask=obj.subtask, type='组长').member:
            pass
        else:
            raise PermissionDenied

        if obj.state == '待检查':
            obj.state = '检查中'
            obj.start_date = timezone.now().date()
            obj.save()
            return Response(InspectDeptSerializer(instance=obj).data, status=status.HTTP_200_OK)
        return Response('状态错误', status=status.HTTP_400_BAD_REQUEST)

    @action(methods=['put'], detail=True, perms_map = {'put':'inspectrecord_update'})
    def up(self, request, *args, **kwargs):
        """
        组长对该组织检查结果提交
        """
        obj = self.get_object()

        if request.user == InspectTeam.objects.get(subtask=obj.subtask, type='组长').member:
            pass
        else:
            raise PermissionDenied

        if obj.state == '检查中':
            if InspectRecord.objects.filter(checked=False, subtask=obj.subtask, dept=obj.dept).exists():
                return Response('存在未完成检查记录', status=status.HTTP_400_BAD_REQUEST)
            else:
                if 'note' in request.data and request.data['note']:
                    obj.note = request.data['note']
                obj.state = '已提交'
                obj.save()
                # 更新主任务和子任务状态
                if not InspectDept.objects.filter(subtask=obj.subtask).exclude(state='已提交').exists():
                    obj.subtask.state = '已完成'
                    obj.subtask.save()
                    if not SubInspectTask.objects.filter(inspecttask=obj.subtask.inspecttask).exclude(state='已完成').exists():
                        obj.subtask.inspecttask.state = '已完成'
                        obj.subtask.inspecttask.save()
                return Response(InspectDeptSerializer(instance=obj).data, status=status.HTTP_200_OK)
        else:
            return Response('检查状态错误', status=status.HTTP_400_BAD_REQUEST)


class InspectTeamViewSet(PageOrNot, OptimizationMixin, ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet):
    """
    子任务涉及组员表
    """
    perms_map = {'get':'*', 'put':'inspecttask_update', 'post':'inspecttask_update', 'delete':'inspecttask_update'}
    queryset = InspectTeam.objects.all()
    serializer_class = InspectTeamSerializer
    filterset_fields = ['subtask']
    ordering = ['type']
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        if instance.type=='组长':
            return Response('组长不可删除', status=status.HTTP_400_BAD_REQUEST)
        instance.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

class InspectRecordViewSet(OptimizationMixin, PageOrNot, ModelViewSet):
    perms_map = {'get': '*', 'post': 'inspectrecord_create',
                 'put': 'inspectrecord_update', 'delete': 'inspectrecord_delete'}
    queryset = InspectRecord.objects.all()
    serializer_class = InspectRecordListSerializer
    filterset_fields = ['subtask', 'dept', 'item']
    ordering = ['item__sortnum']

    def get_serializer_class(self):
        if self.action == 'retrieve':
            return InspectRecordDetailSerializer
        return InspectRecordListSerializer

    @action(methods=['post'], detail=False, perms_map = {'post':'inspectrecord_update'})
    def appoint(self, request, *args, **kwargs):
        """
        检查项目指派
        传{records: [id], checker:id}
        """
        data = request.data
        records = InspectRecord.objects.filter(id__in=data['records'])
        subtask = records.first().subtask
        if request.user == InspectTeam.objects.get(subtask=subtask, type='组长').member:
            pass
        else:
            raise PermissionDenied
        checker = User.objects.get(pk=data['checker'])
        records.filter(checked=False).update(checker=checker)
        # 子任务下未分配检查项目按该逻辑分配
        
        items = records.values_list('item', flat=True)
        InspectRecord.objects.filter(item__in=items, subtask=subtask, checker__isnull=True, checked= False).update(checker=checker)
        return Response(status=status.HTTP_200_OK)
    
    @action(methods=['put'], detail=True, perms_map = {'put':'inspectrecord_update'})
    def check(self, request, *args, **kwargs):
        """
        提交单条记录检查结果
        """
        instance = self.get_object()
        leader = InspectTeam.objects.get(subtask=instance.subtask, type='组长').member
        if request.user == instance.checker or instance.checker == None or request.user == leader:
            pass
        else:
            raise PermissionDenied
        if instance.subtask.state == '执行中':
            serializer = InspectRecordCheckSerializer(instance, data=request.data)
            serializer.is_valid(raise_exception=True)
            serializer.save(checker=request.user, checked=True, check_time=timezone.now())
            return Response(InspectRecordListSerializer(instance=instance).data, status=status.HTTP_200_OK)
        return Response('任务状态错误', status=status.HTTP_400_BAD_REQUEST)