from django.db import transaction
from django.utils import timezone
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

from users.models import CompanyUser

from .models import DocumentRecord, EmployeeDocument
from .serializers import (
    DocumentRecordSerializer,
    EmployeeDocumentReorderSerializer,
    EmployeeDocumentSerializer,
    EmployeeRecordQuerySerializer,
    RequestDocumentRecordSerializer,
)


class CompanyAdminRequiredMixin:
    def get_admin_membership(self, user, company_id):
        return CompanyUser.objects.filter(
            user=user,
            company_id=company_id,
            status=CompanyUser.Status.ACTIVE,
            user_type=CompanyUser.UserType.ADMIN,
        ).first()


class EmployeeDocumentListCreateView(CompanyAdminRequiredMixin, APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        serializer = EmployeeDocumentSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        company_id = serializer.validated_data['company'].id
        if not self.get_admin_membership(request.user, company_id):
            return Response({'detail': 'Only active company admins can add employee documents.'}, status=status.HTTP_403_FORBIDDEN)

        employee_document = serializer.save()
        return Response(EmployeeDocumentSerializer(employee_document).data, status=status.HTTP_201_CREATED)

    def get(self, request):
        company_id = request.query_params.get('company_id')
        user_id = request.query_params.get('user_id')
        is_required = request.query_params.get('is_required')

        if not company_id or not user_id:
            return Response({'detail': 'company_id and user_id are required.'}, status=status.HTTP_400_BAD_REQUEST)

        membership = CompanyUser.objects.filter(
            user=request.user,
            company_id=company_id,
            status=CompanyUser.Status.ACTIVE,
        ).first()
        if not membership:
            return Response({'detail': 'You are not an active member of this company.'}, status=status.HTTP_403_FORBIDDEN)

        queryset = EmployeeDocument.objects.filter(company_id=company_id, user_id=user_id).order_by('sort_id', 'id')

        if is_required is not None:
            normalized = is_required.strip().lower()
            if normalized in {'true', '1', 'yes'}:
                queryset = queryset.filter(is_required=True)
            elif normalized in {'false', '0', 'no'}:
                queryset = queryset.filter(is_required=False)
            else:
                return Response({'detail': 'is_required must be true or false.'}, status=status.HTTP_400_BAD_REQUEST)

        return Response(EmployeeDocumentSerializer(queryset, many=True).data, status=status.HTTP_200_OK)


class EmployeeDocumentDetailView(CompanyAdminRequiredMixin, APIView):
    permission_classes = [IsAuthenticated]

    def patch(self, request, document_id):
        employee_document = EmployeeDocument.objects.filter(id=document_id).first()
        if not employee_document:
            return Response({'detail': 'Employee document not found.'}, status=status.HTTP_404_NOT_FOUND)

        if not self.get_admin_membership(request.user, employee_document.company_id):
            return Response({'detail': 'Only active company admins can edit employee documents.'}, status=status.HTTP_403_FORBIDDEN)

        serializer = EmployeeDocumentSerializer(employee_document, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_200_OK)

    def delete(self, request, document_id):
        employee_document = EmployeeDocument.objects.filter(id=document_id).first()
        if not employee_document:
            return Response({'detail': 'Employee document not found.'}, status=status.HTTP_404_NOT_FOUND)

        if not self.get_admin_membership(request.user, employee_document.company_id):
            return Response({'detail': 'Only active company admins can delete employee documents.'}, status=status.HTTP_403_FORBIDDEN)

        employee_document.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


class EmployeeDocumentReorderView(CompanyAdminRequiredMixin, APIView):
    permission_classes = [IsAuthenticated]

    @transaction.atomic
    def post(self, request):
        serializer = EmployeeDocumentReorderSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        company_id = serializer.validated_data['company_id']
        user_id = serializer.validated_data['user_id']

        if not self.get_admin_membership(request.user, company_id):
            return Response({'detail': 'Only active company admins can reorder employee documents.'}, status=status.HTTP_403_FORBIDDEN)

        for item in serializer.validated_data['documents']:
            employee_document = EmployeeDocument.objects.filter(
                id=item['id'],
                company_id=company_id,
                user_id=user_id,
            ).first()
            if not employee_document:
                return Response(
                    {'detail': f"Employee document {item['id']} not found for provided user/company."},
                    status=status.HTTP_404_NOT_FOUND,
                )
            employee_document.sort_id = item['sort_id']
            employee_document.save(update_fields=['sort_id', 'last_updated'])

        queryset = EmployeeDocument.objects.filter(company_id=company_id, user_id=user_id).order_by('sort_id', 'id')
        return Response(EmployeeDocumentSerializer(queryset, many=True).data, status=status.HTTP_200_OK)


class RequestDocumentRecordView(CompanyAdminRequiredMixin, APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        serializer = RequestDocumentRecordSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        employee_document = EmployeeDocument.objects.filter(id=serializer.validated_data['employee_document_id']).first()
        if not employee_document:
            return Response({'detail': 'Employee document not found.'}, status=status.HTTP_404_NOT_FOUND)

        if not self.get_admin_membership(request.user, employee_document.company_id):
            return Response({'detail': 'Only active company admins can request documents.'}, status=status.HTTP_403_FORBIDDEN)

        record = DocumentRecord.objects.create(
            employee_document=employee_document,
            status=DocumentRecord.Status.REQUESTED,
            deadline=serializer.validated_data.get('deadline'),
        )
        return Response(DocumentRecordSerializer(record).data, status=status.HTTP_201_CREATED)


class DocumentRecordApproveView(CompanyAdminRequiredMixin, APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, record_id):
        record = DocumentRecord.objects.filter(id=record_id).select_related('employee_document').first()
        if not record:
            return Response({'detail': 'Document record not found.'}, status=status.HTTP_404_NOT_FOUND)

        company_id = record.employee_document.company_id
        if not self.get_admin_membership(request.user, company_id):
            return Response({'detail': 'Only active company admins can approve documents.'}, status=status.HTTP_403_FORBIDDEN)

        record.status = DocumentRecord.Status.APPROVED
        record.approved_by = request.user
        record.rejected_by = None
        record.last_update = timezone.now()
        record.save(update_fields=['status', 'approved_by', 'rejected_by', 'last_update'])
        return Response(DocumentRecordSerializer(record).data, status=status.HTTP_200_OK)


class DocumentRecordRejectView(CompanyAdminRequiredMixin, APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, record_id):
        record = DocumentRecord.objects.filter(id=record_id).select_related('employee_document').first()
        if not record:
            return Response({'detail': 'Document record not found.'}, status=status.HTTP_404_NOT_FOUND)

        company_id = record.employee_document.company_id
        if not self.get_admin_membership(request.user, company_id):
            return Response({'detail': 'Only active company admins can reject documents.'}, status=status.HTTP_403_FORBIDDEN)

        record.status = DocumentRecord.Status.REJECTED
        record.rejected_by = request.user
        record.approved_by = None
        record.last_update = timezone.now()
        record.save(update_fields=['status', 'rejected_by', 'approved_by', 'last_update'])
        return Response(DocumentRecordSerializer(record).data, status=status.HTTP_200_OK)


class EmployeeDocumentRecordListByUserCompanyView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        serializer = EmployeeRecordQuerySerializer(data=request.query_params)
        serializer.is_valid(raise_exception=True)

        company_id = serializer.validated_data['company_id']
        user_id = serializer.validated_data['user_id']

        membership = CompanyUser.objects.filter(
            user=request.user,
            company_id=company_id,
            status=CompanyUser.Status.ACTIVE,
        ).first()
        if not membership:
            return Response({'detail': 'You are not an active member of this company.'}, status=status.HTTP_403_FORBIDDEN)

        records = DocumentRecord.objects.filter(
            employee_document__company_id=company_id,
            employee_document__user_id=user_id,
        ).select_related('employee_document', 'approved_by', 'rejected_by').order_by('-last_update', '-id')

        return Response(DocumentRecordSerializer(records, many=True).data, status=status.HTTP_200_OK)


class DocumentRecordDetailView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, record_id):
        record = DocumentRecord.objects.filter(id=record_id).select_related('employee_document', 'approved_by', 'rejected_by').first()
        if not record:
            return Response({'detail': 'Document record not found.'}, status=status.HTTP_404_NOT_FOUND)

        company_id = record.employee_document.company_id
        membership = CompanyUser.objects.filter(
            user=request.user,
            company_id=company_id,
            status=CompanyUser.Status.ACTIVE,
        ).first()
        if not membership:
            return Response({'detail': 'You are not an active member of this company.'}, status=status.HTTP_403_FORBIDDEN)

        return Response(DocumentRecordSerializer(record).data, status=status.HTTP_200_OK)
