from apps.rpm.filters import RpjFilterSet
from apps.rpm.models import Rcertificate, Remployee, Rparty, Rfile, Rpjfile, Rpjmember, Rpj, RpjLog, BlackList
from apps.rpm.serializers import (RcertificateCreateUpdateSerializer,
                                  RcertificateSerializer, RemployeeCreateSerializer, RemployeeSerializer,
                                  RemployeeUpdateSerializer, RpartyAssignSerializer, RpartyCreateUpdateSerializer,
                                  RfileListSerializer, RpartySerializer, RpjListSerializer, RpjfileSerializer,
                                  RpjfileUpdateSerializer, RpjmemberCreateSerializer, RpjLogSerializer,
                                  RpjCreateSerializer, RpjUpdateSerializer, RpjmemberSerializer, RpjmemberUpdateSerializer,
                                  BlackListCreateSerializer, BlackListUpdateSerializer, BlackListSerializer)
from apps.rpm.services import sync_to_rep, rpj_member_leave
from apps.system.models import Dictionary, Post, User, UserPost
from apps.system.serializers import UserCreateSerializer
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
from rest_framework.mixins import ListModelMixin, DestroyModelMixin, UpdateModelMixin
from rest_framework.decorators import action
from rest_framework.response import Response
from django.contrib.auth.hashers import make_password
from django.db import transaction
from rest_framework.exceptions import ParseError
from django.db.models import Q
from apps.utils.constants import DEFAULT_PWD


# Create your views here.
class RpartyViewSet(CustomModelViewSet):
    perms_map = {'get': 'rparty.view', 'post': 'rparty.create',
                 'put': 'rparty.update', 'delete': 'rparty.delete'}
    queryset = Rparty.objects.all()
    create_serializer_class = RpartyCreateUpdateSerializer
    update_serializer_class = RpartyCreateUpdateSerializer
    serializer_class = RpartySerializer
    select_related_fields = ['admin', 'belong_dept', 'create_by']
    search_fields = ['name']
    data_filter = True

    def get_queryset(self):
        queryset = super().get_queryset()
        # 防止越权,加入的逻辑,可以通过岗位控权实现
        user = self.request.user
        if user.is_authenticated and user.type == 'remployee':
            queryset = queryset.filter(dept=user.belong_dept)
        return queryset

    @transaction.atomic
    def destroy(self, request, *args, **kwargs):
        obj = self.get_object()
        if obj.dept:
            obj.dept.delete()
            # 将隶属于该部门的账户禁用
            User.objects.filter(belong_dept=obj.dept).update(is_deleted=True)
        obj.delete()
        return Response(status=204)

    @action(methods=['post'], detail=True, perms_map={'post': 'rparty:assgin'}, serializer_class=RpartyAssignSerializer)
    @transaction.atomic
    def assign(self, request, *args, **kwargs):
        """
        分配账号
        """
        obj = self.get_object()
        post = Post.objects.get(code='remployee_m')
        serializer = RpartyAssignSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        vdata = serializer.validated_data
        if vdata['admin']:
            ins = vdata['admin']
        elif User.objects.get_queryset(all=True).filter(Q(phone=vdata['phone']) | Q(username=vdata['username'])).exists():
            raise ParseError('该账号已存在,请直接选择')
        else:
            serializer = UserCreateSerializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            ins = serializer.save(
                type='remployee', password=make_password(DEFAULT_PWD))
        obj.admin = ins
        obj.save()
        # 岗位设置为相关方岗位
        UserPost.objects.get_or_create(user=ins, dept=obj.dept,
                                       defaults={
                                           'user': ins,
                                           'dept': obj.dept,
                                           'post': post,
                                           'sort': 99
                                       })
        up = UserPost.objects.filter(user=ins).order_by(
            'sort', 'create_time').first()
        if up:
            ins.belong_dept = up.dept
            ins.post = up.post
            ins.update_by = self.request.user
            ins.save()
        # 同步设置rep
        # sync_to_rep(ins.employee)
        return Response()


class RfileViewSet(ListModelMixin, CustomGenericViewSet):
    perms_map = {'get': 'rfile.view'}
    queryset = Rfile.objects.all()
    list_serializer_class = RfileListSerializer
    filterset_fields = ['file_cate']
    ordering = ['file_cate__sort', 'file_cate__create_time']
    data_filter = True
    data_filter_field = 'rparty__dept'

    def get_queryset(self):
        queryset = super().get_queryset()
        # 防止越权,加入的逻辑,可以通过岗位控权实现
        user = self.request.user
        if user.is_authenticated and user.type == 'remployee':
            queryset = queryset.filter(rparty__dept=user.belong_dept)
        return queryset


class RemployeeViewSet(CustomModelViewSet):
    perms_map = {'get': 'remployee.view', 'post': 'remployee.create',
                 'put': 'remployee.update', 'delete': 'remployee.update'}
    queryset = Remployee.objects.all()
    create_serializer_class = RemployeeCreateSerializer
    update_serializer_class = RemployeeUpdateSerializer
    serializer_class = RemployeeSerializer
    search_fields = ['name', 'phone', 'id_number']
    filterset_fields = ['rparty']
    data_filter = True
    data_filter_field = 'rparty__dept'

    def get_queryset(self):
        queryset = super().get_queryset()
        user = self.request.user
        if user.is_authenticated and user.type == 'remployee':
            queryset = queryset.filter(rparty__dept=user.belong_dept)
        return queryset

    @transaction.atomic
    def create(self, request, *args, **kwargs):
        """
        添加人员
        """
        user = self.request.user
        # ep = user.employee
        # if ep.id_number and ep.photo:
        #     pass
        # else:
        #     raise ParseError('请先完善个人信息')
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        vdata = serializer.validated_data
        if user.type == 'remployee':  # 如果是相关方账号
            ins = serializer.save(rparty=user.belong_dept.rparty)
        else:
            if 'rparty' not in vdata:
                raise ParseError('未指定相关方')
            ins = serializer.save()
        return Response({"id": ins.id}, status=201)


class RcertificateViewSet(CustomModelViewSet):
    perms_map = {'get': 'rcertificate.view', 'post': 'rcertificate.create',
                 'put': 'rcertificate.update', 'delete': 'rcertificate.update'}
    queryset = Rcertificate.objects.all()
    create_serializer_class = RcertificateCreateUpdateSerializer
    update_serializer_class = RcertificateCreateUpdateSerializer
    serializer_class = RcertificateSerializer
    filterset_fields = ['remployee', 'remployee__rparty']
    search_fields = ['remployee__name', 'number']
    data_filter = True
    data_filter_field = 'remployee__rparty__dept'

    def get_queryset(self):
        queryset = super().get_queryset()
        user = self.request.user
        if user.is_authenticated and user.type == 'remployee':
            queryset = queryset.filter(
                remployee__rparty__dept=user.belong_dept)
        return queryset


class RpjViewSet(CustomModelViewSet):
    perms_map = {'get': 'rpj.view', 'post': 'rpj.create',
                 'put': 'rpj.update', 'delete': 'rpj.update'}
    queryset = Rpj.objects.all()
    create_serializer_class = RpjCreateSerializer
    update_serializer_class = RpjUpdateSerializer
    serializer_class = RpjListSerializer
    select_related_fields = [
        'rparty', 'belong_dept', 'ticket', 'ticket__state']
    search_fields = ['name']
    filterset_class = RpjFilterSet
    data_filter = True
    data_filter_field = 'rparty__dept'

    def get_queryset(self):
        queryset = super().get_queryset()
        user = self.request.user
        if user.is_authenticated and user.type == 'remployee':
            queryset = queryset.filter(rparty__dept=user.belong_dept)
        return queryset

    @transaction.atomic
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        vdata = serializer.validated_data
        if self.request.user.type == 'remployee':
            vdata['rparty'] = self.request.user.belong_dept.rparty
        if not vdata.get('rparty', None):
            raise ParseError('请指定相关方')
        if BlackList.objects.filter(Q(name=vdata['rparty'].name) | Q(number=vdata['rparty'].number)).exists():
            raise ParseError('该相关方在黑名单中')
        if not vdata.get('belong_dept', None):
            vdata['belong_dept'] = vdata['rparty'].belong_dept
        ins = serializer.save()
        # 同步创建需要提交的资料
        for i in Dictionary.objects.filter(type__code='rparty_file_cate').order_by('sort'):
            Rpjfile.objects.create(rpj=ins, file_cate=i)
        return Response(status=201, data=serializer.data)

    def update(self, request, *args, **kwargs):
        obj = self.get_object()
        ticket = obj.ticket
        if ticket and ticket.state.type != 1:
            raise ParseError('项目工单审批中不可更改')
        return super().update(request, *args, **kwargs)

    @transaction.atomic
    def destroy(self, request, *args, **kwargs):
        obj = self.get_object()
        if obj.state in [Rpj.RPJ_ENTER, Rpj.RPJ_DONE]:
            raise ParseError('该项目不可删除')
        elif obj.state == Rpj.RPJ_WORKING and Remployee.objects.filter(rpj=obj).exists():
            raise ParseError('该项目下有成员在厂不可删除')
        if obj.ticket:
            obj.ticket.delete()
        obj.delete()
        return Response(status=204)


class RpjmemberViewSet(CustomModelViewSet):
    perms_map = {'get': '*', 'post': 'rpj.update',
                 'put': 'rpj.update', 'delete': 'rpj.update'}
    queryset = Rpjmember.objects.all()
    create_serializer_class = RpjmemberCreateSerializer
    update_serializer_class = RpjmemberUpdateSerializer
    serializer_class = RpjmemberSerializer
    select_related_fields = ['remployee']
    prefetch_related_fields = ['rcertificates']
    filterset_fields = ['rpj']

    def destroy(self, request, *args, **kwargs):
        obj = self.get_object()
        ticket = obj.rpj.ticket
        if ticket and ticket.state.type != 1:
            raise ParseError('成员在该状态不可删除')
        return super().destroy(request, *args, **kwargs)

    @action(methods=['put'], detail=True, perms_map={'put': 'rpj.update'})
    @transaction.atomic
    def leave(self, request, pk=None):
        """提前离厂

        提前离厂
        """
        obj = self.get_object()
        rpj = obj.rpj
        if rpj.state not in [Rpj.RPJ_WORKING, Rpj.RPJ_ENTER]:
            raise ParseError('该项目状态成员不可离厂')
        rlog = RpjLog.objects.filter(
            rpj=rpj, remployee=obj.remployee).order_by('-create_time').first()
        if rlog and rlog.operation == 'member_leave':
            raise ParseError('该成员已做离厂操作')
        obj.note = '提前离厂'
        obj.save()
        rpj_member_leave(obj)
        RpjLog.objects.create(rpj=obj.rpj, operation='member_leave', remployee=obj.remployee,
                              create_by=request.user, reason=request.data.get('reason', ''))
        return Response()


class RpjLogViewSet(ListModelMixin, CustomGenericViewSet):
    perms_map = {'get': '*'}
    queryset = RpjLog.objects.all()
    serializer_class = RpjLogSerializer
    select_related_fields = ['rpj', 'remployee', 'create_by']
    filterset_fields = ['rpj', 'remployee']
    ordering = ['-create_time']


class RpjfileViewSet(UpdateModelMixin, DestroyModelMixin, ListModelMixin, CustomGenericViewSet):
    perms_map = {'get': '*', 'put': 'rpj.update', 'delete': 'rpj.update'}
    queryset = Rpjfile.objects.all()
    update_serializer_class = RpjfileUpdateSerializer
    serializer_class = RpjfileSerializer
    select_related_fields = ['rpj']
    prefetch_related_fields = ['files']
    filterset_fields = ['rpj']
    ordering = ['file_cate__sort']

    def update(self, request, *args, **kwargs):
        obj = self.get_object()
        ticket = obj.rpj.ticket
        if ticket and ticket.state.type != 1:
            raise ParseError('项目工单审批中不可更改')
        return super().update(request, *args, **kwargs)

    def destroy(self, request, *args, **kwargs):
        obj = self.get_object()
        ticket = obj.rpj.ticket
        if ticket and ticket.state.type != 1:
            raise ParseError('项目工单审批中不可删除')
        return super().destroy(request, *args, **kwargs)


class BlackListViewSet(CustomModelViewSet):
    queryset = BlackList.objects.all()
    create_serializer_class = BlackListCreateSerializer
    update_serializer_class = BlackListUpdateSerializer
    serializer_class = BlackListSerializer
    select_related_fields = ['create_by', 'update_by']
    search_fields = ['name', 'number']
