from django.conf import settings
from django.db.models import Count, Q
from django.shortcuts import get_object_or_404
from rest_framework import generics, status
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from accounts.permissions import IsAdmin

from .models import CustomsDocument, Folder
from .serializers import (
    CustomsDocumentDetailSerializer,
    CustomsDocumentSerializer,
    CustomsDocumentUploadSerializer,
    CustomsDocumentReviewSerializer,
    FolderSerializer,
    FolderWriteSerializer,
)


class CustomsDocumentUploadView(generics.CreateAPIView):
    """POST /api/documents/upload/ - uploads a customs PDF and classifies it."""
    queryset = CustomsDocument.objects.all()
    serializer_class = CustomsDocumentUploadSerializer
    permission_classes = [IsAuthenticated]


class OcrStatusView(APIView):
    """GET /api/documents/ocr-status/ - admin-only health check.

    Says whether a cloud OCR provider is actually usable on THIS server, which
    is the difference between scans being read automatically and every scan
    landing in "À confirmer". Deliberately never returns the key itself.
    """
    permission_classes = [IsAdmin]

    def get(self, request):
        from documents.ocr import configured_providers

        providers = [name for name, _ in configured_providers()]
        return Response({
            'ocr_available': bool(providers),
            'providers': providers,
            'ocr_space_key_set': bool(settings.OCR_SPACE_API_KEY),
            'google_vision_key_set': bool(settings.GOOGLE_VISION_API_KEY),
            'hint': (
                'OK — les scans sont lus automatiquement.' if providers else
                "Aucune clé OCR sur ce serveur : tous les scans resteront « À "
                "confirmer ». Ajoutez OCR_SPACE_API_KEY dans les variables "
                "d'environnement de l'application Python (cPanel), puis "
                'redémarrez-la.'
            ),
        })


class CustomsDocumentListView(generics.ListAPIView):
    """GET /api/documents/ - paginated list, filterable by ?status=, ?q=, ?folder=.
    ?folder=<id> restricts to that folder; ?folder=none restricts to root-level
    (folder-less) documents. Documents whose folder has been archived are never
    returned here — see ArchivedDocumentListView.
    """
    serializer_class = CustomsDocumentSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        queryset = CustomsDocument.objects.filter(
            Q(folder__isnull=True) | Q(folder__is_archived=False)
        )
        params = self.request.query_params

        status_param = params.get('status')
        if status_param:
            queryset = queryset.filter(status=status_param)

        folder_param = params.get('folder')
        if folder_param == 'none':
            queryset = queryset.filter(folder__isnull=True)
        elif folder_param:
            queryset = queryset.filter(folder_id=folder_param)

        q = params.get('q', '').strip()
        if q:
            queryset = queryset.filter(
                Q(original_filename__icontains=q) | Q(officer_name__icontains=q)
            )

        return queryset


class CustomsDocumentDetailView(generics.RetrieveDestroyAPIView):
    """GET /api/documents/<id>/ - detail (any authenticated user).
    DELETE /api/documents/<id>/ - admin only.
    """
    queryset = CustomsDocument.objects.all()
    serializer_class = CustomsDocumentDetailSerializer

    def get_permissions(self):
        if self.request.method == 'DELETE':
            return [IsAdmin()]
        return [IsAuthenticated()]


class CustomsDocumentReviewView(APIView):
    """POST /api/documents/<id>/review/ - admin confirms classification."""
    permission_classes = [IsAdmin]

    def post(self, request, pk):
        document = get_object_or_404(CustomsDocument, pk=pk)
        serializer = CustomsDocumentReviewSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        review_status = serializer.validated_data['status']
        officer_name = serializer.validated_data.get('officer_name', '').strip()
        if review_status == CustomsDocument.Status.VALIDATED and not officer_name:
            return Response(
                {'officer_name': 'Le nom du Customs Officer est obligatoire.'},
                status=status.HTTP_400_BAD_REQUEST,
            )
        document.status = review_status
        document.officer_name = officer_name or None
        # An admin's decision overrides the pipeline; flag it so the automatic
        # classification is never blamed for a hand-made call.
        document.auto_classified = False
        document.save(update_fields=['status', 'officer_name', 'auto_classified'])
        return Response(CustomsDocumentSerializer(document).data)


class ArchivedDocumentListView(generics.ListAPIView):
    """GET /api/documents/archived/ - documents whose folder has been archived,
    filterable by ?status=, ?q= (same as the main list)."""
    serializer_class = CustomsDocumentSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        queryset = CustomsDocument.objects.filter(folder__is_archived=True)
        params = self.request.query_params

        status_param = params.get('status')
        if status_param:
            queryset = queryset.filter(status=status_param)

        q = params.get('q', '').strip()
        if q:
            queryset = queryset.filter(
                Q(original_filename__icontains=q) | Q(officer_name__icontains=q)
            )

        return queryset


class FolderListCreateView(generics.ListCreateAPIView):
    """GET /api/documents/folders/ - active folders with document counts.
    POST /api/documents/folders/ - create a folder (any authenticated user).
    Unpaginated — a plain array, not the {count, results} shape the other
    document endpoints use, since the folder count per user is small and the
    frontend needs the full set at once for the folder grid.
    """
    permission_classes = [IsAuthenticated]
    pagination_class = None

    def get_queryset(self):
        return Folder.objects.filter(is_archived=False).annotate(
            document_count=Count('documents'),
            validated_count=Count(
                'documents', filter=Q(documents__status=CustomsDocument.Status.VALIDATED)
            ),
            not_validated_count=Count(
                'documents', filter=Q(documents__status=CustomsDocument.Status.NOT_VALIDATED)
            ),
            pending_review_count=Count(
                'documents', filter=Q(documents__status=CustomsDocument.Status.PENDING_REVIEW)
            ),
        )

    def get_serializer_class(self):
        return FolderWriteSerializer if self.request.method == 'POST' else FolderSerializer


class FolderDetailView(generics.RetrieveUpdateAPIView):
    """GET /api/documents/folders/<id>/ - detail (any authenticated user).
    PATCH /api/documents/folders/<id>/ - rename (any authenticated user).
    """
    queryset = Folder.objects.filter(is_archived=False)
    serializer_class = FolderWriteSerializer
    permission_classes = [IsAuthenticated]


class FolderArchiveView(generics.GenericAPIView):
    """POST /api/documents/folders/<id>/archive/ - admin only. Soft-deletes the
    folder: its documents keep their `folder` FK (visible in Archives with the
    folder's name) instead of being deleted or orphaned back to root."""
    queryset = Folder.objects.filter(is_archived=False)
    permission_classes = [IsAdmin]

    def post(self, request, pk):
        folder = self.get_object()
        folder.is_archived = True
        folder.save(update_fields=['is_archived'])
        return Response(status=204)
