from django.db.models import Avg, Count, Max, Min
from django.http import HttpResponse
from django.utils import timezone
from rest_framework.views import APIView

from core.responses import error_response, success_response

from apps.pipeline.models import PipelineStage

from .exporters import EXPORT_FORMATS
from .permissions import CanViewReports
from .services import (
    build_funnel,
    filtered_applications,
    filtered_candidates,
    filtered_jobs,
    parse_filters,
    pct,
    stage_breakdown,
)


class DashboardSummaryView(APIView):
    """GET /api/v1/reports/dashboard-summary/ — top-level KPI cards."""

    permission_classes = [CanViewReports]

    def get(self, request):
        filters = parse_filters(request)
        candidates = filtered_candidates(filters)
        applications = filtered_applications(filters)

        total_candidates = candidates.count()
        average = applications.filter(score__isnull=False).aggregate(v=Avg("score"))["v"]
        hired = (
            applications.filter(stage__outcome=PipelineStage.Outcome.WON)
            .values("candidate_id").distinct().count()
        )

        return success_response({
            "total_candidates": total_candidates,
            "total_jds": filtered_jobs(filters).count(),
            "average_score": round(average, 1) if average is not None else 0,
            "hired_candidates": hired,
            "conversion_rate": pct(hired, total_candidates),
        })


class CandidatesByStageView(APIView):
    """GET /api/v1/reports/candidates-by-stage/ — pipeline distribution.

    Stages are data-driven (PipelineStage master), so the response is a list
    ordered by the pipeline order rather than a fixed stage map."""

    permission_classes = [CanViewReports]

    def get(self, request):
        applications = filtered_applications(parse_filters(request))
        return success_response(stage_breakdown(applications))


class CandidateScoresView(APIView):
    """GET /api/v1/reports/candidate-scores/ — score analytics overall & per JD."""

    permission_classes = [CanViewReports]

    def get(self, request):
        filters = parse_filters(request)
        scored = filtered_applications(filters).filter(score__isnull=False)

        agg = scored.aggregate(avg=Avg("score"), high=Max("score"), low=Min("score"))
        job_scores = [
            {
                "job_id": row["job_id"],
                "job_title": row["job__title"],
                "average_score": round(row["avg"], 1),
                "candidates": row["candidates"],
            }
            for row in scored.values("job_id", "job__title")
            .annotate(avg=Avg("score"), candidates=Count("id"))
            .order_by("-avg")
        ]

        return success_response({
            "overall_average": round(agg["avg"], 1) if agg["avg"] is not None else 0,
            "highest_score": agg["high"] or 0,
            "lowest_score": agg["low"] or 0,
            "scored_candidates": scored.count(),
            "job_scores": job_scores,
        })


class ConversionFunnelView(APIView):
    """GET /api/v1/reports/conversion-funnel/ — how far candidates progress."""

    permission_classes = [CanViewReports]

    def get(self, request):
        applications = filtered_applications(parse_filters(request))
        return success_response({"funnel": build_funnel(applications)})


class BaseExportView(APIView):
    """Shared plumbing for report exports (format negotiation + file response)."""

    permission_classes = [CanViewReports]

    def perform_content_negotiation(self, request, force=False):
        # DRF treats ?format= as a renderer suffix and would 404 on csv/pdf.
        # We stream raw bytes ourselves, so always accept the default renderer.
        return super().perform_content_negotiation(request, force=True)

    def send_export(self, request, headers, rows, basename):
        fmt = (request.query_params.get("format") or "csv").lower()
        if fmt not in EXPORT_FORMATS:
            return error_response(f"Unsupported format '{fmt}'. Use csv, excel or pdf.")
        build, content_type, ext = EXPORT_FORMATS[fmt]
        content = build(headers, rows)
        filename = f"{basename}_{timezone.now().strftime('%Y%m%d_%H%M')}.{ext}"
        response = HttpResponse(content, content_type=content_type)
        response["Content-Disposition"] = f'attachment; filename="{filename}"'
        return response


class ReportExportView(BaseExportView):
    """GET /api/v1/reports/export/?format=csv|excel|pdf — filtered pipeline report."""

    def get(self, request):
        filters = parse_filters(request)
        headers = [
            "Candidate", "Email", "Phone", "Status", "Job Description",
            "Client", "Stage", "Score", "Interview Result", "Recruiter", "Applied On",
        ]
        rows = [
            [
                f"{app.candidate.first_name} {app.candidate.last_name}".strip(),
                app.candidate.email or "",
                app.candidate.phone_number or "",
                app.candidate.status,
                app.job.title,
                app.job.client.name if app.job.client else "",
                app.stage.name if app.stage else "",
                app.score if app.score is not None else "",
                app.interview_result or "",
                app.created_by.email if app.created_by else "",
                app.created_at.strftime("%d/%m/%Y"),
            ]
            for app in filtered_applications(filters).order_by("-created_at")
        ]
        return self.send_export(request, headers, rows, "recruitment_report")
