"""Consolidated Recruiter Dashboard endpoint — every section in one request.

    GET /api/[v1/]dashboard/recruiter/all/
        ?jd_id=&client_id=&recruiter_id=&from_date=&to_date=&status=

The dashboard used to need eight round trips to paint (two dashboard endpoints,
the assigned-JD list twice, the client list, and two page-level counts), and
several re-fired on every filter change. This returns all of it at once, so
applying a filter costs exactly one request.

It introduces NO new business logic and NO new permission rules: each section is
produced by calling the existing view that already owns it, with the query
parameters translated to the names that view expects — so the numbers come from
literally the same code as before. Those endpoints all remain in place,
unchanged, for backward compatibility and for the other dashboards using them.

Sections returned under `data`:
    stats           /dashboard/recruiter/          (ratios, TAT, funnel counts)
    overview        /dashboard/recruiter/overview/ (summary, action_points,
                    performance, jd_metrics, rejection_analytics, jd_breakdown)
    assigned_jds    /jobs/my-assigned/             (JD filter options + table)
    recruiter_work  /dashboard/recruiter-work/     (recruiter-wise work rows)
    clients         /clients/                      (client filter options)

Scoping and RBAC are unchanged: every underlying view scopes server-side off the
request user, so a recruiter still only ever sees their own data.
"""

from django.http import QueryDict
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView

from core.responses import success_response

from apps.clients.models import Client
from apps.jobs.views import JobDescriptionViewSet, _is_manager

from .recruiter_work_views import RecruiterWorkView
from .recruiter_overview_views import RecruiterOverviewView
from .views import RecruiterDashboardView


class _ScopedRequest:
    """Minimal stand-in for a DRF request used to call the existing views.

    Those views read exactly two things — `user` and `query_params` — so this
    hands them the same user and a QueryDict carrying the parameter names they
    already understand. Nothing else about them changes.
    """

    def __init__(self, user, params):
        self.user = user
        qd = QueryDict(mutable=True)
        for key, value in params.items():
            if value not in (None, ""):
                qd[key] = value
        qd._mutable = False
        self.query_params = qd
        self.GET = qd
        self.data = {}
        self.method = "GET"


def _payload(response):
    """Unwrap a view's Response into the plain dict the frontend consumes.

    `success_response` wraps its body in `{success, message, data}` while some
    older views return the bare dict — handle both.
    """
    body = getattr(response, "data", None)
    if isinstance(body, dict) and "data" in body and set(body) <= {"success", "message", "data"}:
        return body["data"]
    return body


class RecruiterDashboardAllView(APIView):
    """Everything the Recruiter Dashboard renders, in a single response."""

    permission_classes = [IsAuthenticated]

    def get(self, request):
        params = request.query_params

        jd_id = (params.get("jd_id") or params.get("jd") or "").strip()
        client_id = (params.get("client_id") or params.get("client") or "").strip()
        from_date = (params.get("from_date") or "").strip()
        to_date = (params.get("to_date") or "").strip()
        status = (params.get("status") or "").strip()

        # `recruiter_id` lets a manager/admin pull up one recruiter's dashboard.
        # A recruiter passing someone else's id is ignored — the scope stays
        # their own, so this cannot be used to widen access.
        target_user = request.user
        recruiter_id = (params.get("recruiter_id") or "").strip()
        if recruiter_id.isdigit() and int(recruiter_id) != request.user.id:
            if _is_manager(request.user) or getattr(request.user, "role", "") == "ADMIN":
                from django.contrib.auth import get_user_model
                target_user = (
                    get_user_model().objects.filter(pk=int(recruiter_id)).first() or request.user
                )

        # Shared filter set, in the names the existing views already read.
        common = {
            "jd": jd_id,
            "client": client_id,
            "status": status,
            "from_date": from_date,
            "to_date": to_date,
        }

        stats = _payload(RecruiterDashboardView().get(_ScopedRequest(target_user, common)))
        overview = _payload(RecruiterOverviewView().get(_ScopedRequest(target_user, common)))
        assigned = _payload(
            JobDescriptionViewSet.my_assigned(
                JobDescriptionViewSet(), _ScopedRequest(target_user, common)
            )
        )

        # Recruiter-wise work uses date_from/date_to and is scoped by role; for a
        # recruiter it returns just their own row. A 403 (role not permitted)
        # degrades to an empty list rather than failing the whole dashboard.
        work_response = RecruiterWorkView().get(
            _ScopedRequest(target_user, {"date_from": from_date, "date_to": to_date})
        )
        work = _payload(work_response) if work_response.status_code == 200 else {"recruiters": []}

        # Client filter options — same list and ordering the standalone
        # ClientFilterSelect fetches, so the dropdown is unchanged.
        clients = [
            {"id": c.id, "name": c.name}
            for c in Client.objects.all().order_by("name")[:200]
        ]

        return success_response({
            "stats": stats,
            "overview": overview,
            "assigned_jds": assigned or [],
            "recruiter_work": (work or {}).get("recruiters", []),
            "clients": clients,
            # Echo back what was actually applied, so the UI can confirm its
            # filter state matches the data it just received.
            "filters": {
                "jd_id": jd_id,
                "client_id": client_id,
                "recruiter_id": str(target_user.id),
                "from_date": from_date,
                "to_date": to_date,
                "status": status,
            },
        })
