from django.utils import timezone
from rest_framework.views import APIView
from rest_framework import generics, status
from rest_framework.response import Response
from rest_framework.permissions import AllowAny, IsAdminUser
from drf_spectacular.utils import (
    extend_schema, OpenApiExample, OpenApiParameter, OpenApiResponse
)
from drf_spectacular.types import OpenApiTypes
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter, OrderingFilter

from .models import AdmissionInquiry, AdmissionStatusHistory
from .serializers import (
    AdmissionInquiryListSerializer,
    AdmissionInquiryDetailSerializer,
    AdmissionInquiryWriteSerializer,
    AdmissionStatusUpdateSerializer,
)
from core.filters import AdmissionInquiryFilter


@extend_schema(
    tags=["Admissions"],
    summary="Submit an admission inquiry",
    description=(
        "Public endpoint — no authentication required. "
        "Prospective students fill this form to express interest in a program. "
        "The submission is saved with status `pending` and reviewed by the admin team. "
        "Document URLs (citizenship, transcript, photo) should be uploaded separately "
        "to a file storage endpoint and the returned URLs passed here."
    ),
    request=AdmissionInquiryWriteSerializer,
    responses={
        201: OpenApiResponse(
            response=AdmissionInquiryWriteSerializer,
            description="Inquiry submitted successfully.",
        ),
        400: OpenApiResponse(description="Validation error — check field-level errors in response."),
    },
    examples=[
        OpenApiExample(
            "Full Application",
            summary="Complete form submission",
            description="A fully filled admission inquiry for BSc.CSIT.",
            value={
                "full_name": "Aarav Sharma",
                "email": "aarav.sharma@gmail.com",
                "phone": "9841234567",
                "gender": "male",
                "date_of_birth": "2004-03-15",
                "address": "Kathmandu, Bagmati Province",
                "nationality": "Nepali",
                "last_institution": "Siddhartha Vanasthali School",
                "last_qualification": "+2 Science",
                "last_gpa_or_percent": "3.65 GPA",
                "passing_year": 2024,
                "program": 3,
                "academic_year": "2026-27",
                "message": "I am interested in the BSc.CSIT program and want to know about the entrance exam schedule.",
                "source": "website",
                "citizenship_url": "https://storage.example.com/docs/citizenship_aarav.jpg",
                "transcript_url": "https://storage.example.com/docs/transcript_aarav.pdf",
                "photo_url": "https://storage.example.com/photos/aarav.jpg",
            },
            request_only=True,
        ),
        OpenApiExample(
            "Minimal Inquiry",
            summary="Minimal required fields only",
            description="Only name, email, and program are the practical minimums.",
            value={
                "full_name": "Sita Rai",
                "email": "sita.rai@example.com",
                "program": 1,
                "academic_year": "2026-27",
                "source": "social_media",
            },
            request_only=True,
        ),
        OpenApiExample(
            "Submission Response",
            summary="Successful submission response",
            value={
                "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                "full_name": "Aarav Sharma",
                "email": "aarav.sharma@gmail.com",
                "program": 3,
                "academic_year": "2026-27",
                "status": "pending",
                "created_at": "2026-06-29T10:30:00+05:45",
            },
            response_only=True,
            status_codes=["201"],
        ),
        OpenApiExample(
            "Validation Error",
            summary="400 — invalid fields",
            value={
                "email": ["Enter a valid email address."],
                "passing_year": ["Enter a valid passing year between 1990 and 2030."],
            },
            response_only=True,
            status_codes=["400"],
        ),
    ],
)
class AdmissionInquiryCreateView(generics.CreateAPIView):
    """
    POST admissions
    Public. No auth required. Saves with status=pending.
    """
    serializer_class = AdmissionInquiryWriteSerializer
    permission_classes = [AllowAny]



@extend_schema(
    tags=["Admissions"],
    summary="List all admission inquiries (admin)",
    description=(
        "Admin-only. Returns a paginated, filterable list of all inquiries. "
        "Use `status`, `source`, `program`, and `academic_year` filters to segment. "
        "`search` matches `full_name`, `email`, and `phone`. "
        "`ordering` supports `created_at`, `-created_at`, `full_name`."
    ),
    parameters=[
        OpenApiParameter("status",        OpenApiTypes.STR,  description="Filter by status: pending | reviewing | shortlisted | accepted | rejected | waitlisted | withdrawn"),
        OpenApiParameter("source",        OpenApiTypes.STR,  description="Filter by source: website | walk_in | referral | social_media | other"),
        OpenApiParameter("program",       OpenApiTypes.INT,  description="Filter by program ID"),
        OpenApiParameter("academic_year", OpenApiTypes.STR,  description="Filter by academic year e.g. 2026-27"),
        OpenApiParameter("created_after", OpenApiTypes.DATE, description="Show inquiries created on or after this date (YYYY-MM-DD)"),
        OpenApiParameter("created_before",OpenApiTypes.DATE, description="Show inquiries created on or before this date (YYYY-MM-DD)"),
        OpenApiParameter("search",        OpenApiTypes.STR,  description="Search by full_name, email, or phone"),
        OpenApiParameter("ordering",      OpenApiTypes.STR,  description="Sort by: created_at | -created_at | full_name"),
    ],
    responses={
        200: OpenApiResponse(response=AdmissionInquiryListSerializer(many=True)),
        403: OpenApiResponse(description="Authentication required. Admin access only."),
    },
    examples=[
        OpenApiExample(
            "Paginated List Response",
            response_only=True,
            status_codes=["200"],
            value={
                "count": 42,
                "next": "https://api.newsummitcollege.edu.np/api/v1/admissions?page=2",
                "previous": None,
                "results": [
                    {
                        "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                        "full_name": "Aarav Sharma",
                        "email": "aarav.sharma@gmail.com",
                        "phone": "9841234567",
                        "gender": "male",
                        "program_name": "BSc. Computer Science & IT (BSc.CSIT)",
                        "academic_year": "2026-27",
                        "status": "pending",
                        "source": "website",
                        "created_at": "2026-06-29T10:30:00+05:45",
                    }
                ],
            },
        ),
    ],
)
class AdmissionInquiryListView(generics.ListAPIView):
    """
    GET admissions
    Admin only. Paginated, filterable, searchable.
    """
    serializer_class = AdmissionInquiryListSerializer
    permission_classes = [IsAdminUser]
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_class = AdmissionInquiryFilter
    search_fields = ["full_name", "email", "phone"]
    ordering_fields = ["created_at", "full_name", "status"]
    ordering = ["-created_at"]
    queryset = AdmissionInquiry.objects.select_related("program", "reviewed_by").all()


@extend_schema(
    tags=["Admissions"],
    summary="Retrieve full inquiry detail (admin)",
    description=(
        "Admin-only. Returns full applicant data including document URLs, "
        "admin notes, reviewer info, and complete status change history."
    ),
    responses={
        200: OpenApiResponse(response=AdmissionInquiryDetailSerializer),
        404: OpenApiResponse(description="Inquiry not found."),
    },
    examples=[
        OpenApiExample(
            "Full Detail Response",
            response_only=True,
            status_codes=["200"],
            value={
                "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                "full_name": "Aarav Sharma",
                "email": "aarav.sharma@gmail.com",
                "phone": "9841234567",
                "gender": "male",
                "date_of_birth": "2004-03-15",
                "address": "Kathmandu, Bagmati Province",
                "nationality": "Nepali",
                "last_institution": "Siddhartha Vanasthali School",
                "last_qualification": "+2 Science",
                "last_gpa_or_percent": "3.65 GPA",
                "passing_year": 2024,
                "program": 3,
                "program_name": "BSc. Computer Science & IT (BSc.CSIT)",
                "academic_year": "2026-27",
                "citizenship_url": "https://storage.example.com/docs/citizenship_aarav.jpg",
                "transcript_url": "https://storage.example.com/docs/transcript_aarav.pdf",
                "photo_url": "https://storage.example.com/photos/aarav.jpg",
                "status": "reviewing",
                "reviewed_by_name": "Admin User",
                "reviewed_at": "2026-06-29T14:00:00+05:45",
                "admin_notes": "Documents verified. Called applicant on 9841234567.",
                "status_history": [
                    {
                        "id": 1,
                        "old_status": "pending",
                        "new_status": "reviewing",
                        "changed_by_name": "Admin User",
                        "note": "Started document review.",
                        "changed_at": "2026-06-29T14:00:00+05:45",
                    }
                ],
                "created_at": "2026-06-29T10:30:00+05:45",
                "updated_at": "2026-06-29T14:00:00+05:45",
            },
        ),
    ],
)
class AdmissionInquiryDetailView(generics.RetrieveUpdateDestroyAPIView):
    """
    GET admissions/<id>
    Admin only. Full detail with status history.
    """
    serializer_class = AdmissionInquiryDetailSerializer
    permission_classes = [IsAdminUser]
    queryset = AdmissionInquiry.objects.select_related(
        "program", "reviewed_by"
    ).prefetch_related("status_history__changed_by")
    http_method_names = ['get', 'patch', 'delete']


@extend_schema(
    tags=["Admissions"],
    summary="Update inquiry status (admin)",
    description=(
        "Admin-only. Changes the status of an admission inquiry and records "
        "the change in `AdmissionStatusHistory` for a full audit trail. "
        "The requesting admin is automatically recorded as `reviewed_by`. "
        "\n\n**Status flow:**\n"
        "`pending` → `reviewing` → `shortlisted` → `accepted` or `rejected`\n\n"
        "Other valid transitions: any status → `withdrawn` or `waitlisted`."
    ),
    request=AdmissionStatusUpdateSerializer,
    responses={
        200: OpenApiResponse(
            response=AdmissionInquiryDetailSerializer,
            description="Status updated. Full inquiry detail returned.",
        ),
        400: OpenApiResponse(description="Invalid status value."),
        404: OpenApiResponse(description="Inquiry not found."),
    },
    examples=[
        OpenApiExample(
            "Move to Reviewing",
            request_only=True,
            value={"status": "reviewing", "note": "Documents received. Starting review."},
        ),
        OpenApiExample(
            "Accept Applicant",
            request_only=True,
            value={"status": "accepted", "note": "All criteria met. Admission granted for 2026-27."},
        ),
        OpenApiExample(
            "Reject Applicant",
            request_only=True,
            value={"status": "rejected", "note": "GPA below minimum requirement of 2.5."},
        ),
        OpenApiExample(
            "Successful Response",
            response_only=True,
            status_codes=["200"],
            value={
                "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                "full_name": "Aarav Sharma",
                "status": "accepted",
                "reviewed_by_name": "Admin User",
                "reviewed_at": "2026-06-29T16:00:00+05:45",
                "status_history": [
                    {"old_status": "pending",    "new_status": "reviewing", "changed_by_name": "Admin User", "note": "Documents received.", "changed_at": "2026-06-29T14:00:00+05:45"},
                    {"old_status": "reviewing",  "new_status": "shortlisted","changed_by_name": "Admin User", "note": "Passed screening.",  "changed_at": "2026-06-29T15:00:00+05:45"},
                    {"old_status": "shortlisted","new_status": "accepted",   "changed_by_name": "Admin User", "note": "All criteria met.",  "changed_at": "2026-06-29T16:00:00+05:45"},
                ],
            },
        ),
    ],
)
class AdmissionStatusUpdateView(APIView):
    """
    PATCH admissions/<id>/status
    Admin only. Updates status and writes to audit history.
    """
    permission_classes = [IsAdminUser]

    def patch(self, request, pk):
        inquiry = generics.get_object_or_404(AdmissionInquiry, pk=pk)
        serializer = AdmissionStatusUpdateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        old_status = inquiry.status
        new_status = serializer.validated_data["status"]
        note = serializer.validated_data.get("note", "")

        # Write audit record
        AdmissionStatusHistory.objects.create(
            inquiry=inquiry,
            old_status=old_status,
            new_status=new_status,
            changed_by=request.user,
            note=note,
        )

        # Update inquiry
        inquiry.status = new_status
        inquiry.reviewed_by = request.user
        inquiry.reviewed_at = timezone.now()
        inquiry.save(update_fields=["status", "reviewed_by", "reviewed_at", "updated_at"])

        return Response(
            AdmissionInquiryDetailSerializer(inquiry).data,
            status=status.HTTP_200_OK,
        )