from __future__ import annotations

import csv
import io

from fastapi import APIRouter, Request
from fastapi.responses import RedirectResponse, StreamingResponse

from app.core.db.common import CommonSessionLocal
from app.core.http_responses import ui_access_denied
from app.core.security.csrf import get_or_create_csrf_token
from app.core.security.session_auth import get_current_user
from app.core.templating import templates
from app.modules.aqmm_dashboard.service import build_aqmm_dashboard_payload, can_view_aqmm_dashboard
from app.modules.core.rbac.deps import get_user_permissions, get_user_roles

router = APIRouter(prefix="/aqmm", tags=["aqmm-dashboard-ui"])


def _ctx(request: Request, db, user, **extra):
    base = {
        "request": request,
        "current_user": user,
        "current_user_roles": get_user_roles(db, user.id),
        "current_user_permissions": get_user_permissions(db, user.id),
        "csrf_token": get_or_create_csrf_token(request),
        "title": "AQMM Dashboard",
    }
    base.update(extra)
    return base


@router.get("/dashboard")
def dashboard(request: Request, financial_year: str = "", q: str = ""):
    db = CommonSessionLocal()
    try:
        user = get_current_user(request, db=db)
        if not user:
            return RedirectResponse(url="/login", status_code=303)
        if not can_view_aqmm_dashboard(db, user):
            return ui_access_denied()
        payload = build_aqmm_dashboard_payload(db, request, user, financial_year=financial_year, q=q)
        return templates.TemplateResponse(
            "modules/aqmm_dashboard/templates/aqmm_dashboard/dashboard.html",
            _ctx(request, db, user, **payload),
        )
    finally:
        db.close()


@router.get("/dashboard/export.csv")
def dashboard_export_csv(request: Request, financial_year: str = "", q: str = ""):
    db = CommonSessionLocal()
    try:
        user = get_current_user(request, db=db)
        if not user:
            return RedirectResponse(url="/login", status_code=303)
        if not can_view_aqmm_dashboard(db, user):
            return ui_access_denied()
        payload = build_aqmm_dashboard_payload(db, request, user, financial_year=financial_year, q=q)

        buf = io.StringIO()
        writer = csv.writer(buf)
        writer.writerow([
            "Client",
            "Service",
            "FY",
            "Status",
            "AQMM Status",
            "KYC",
            "Independence",
            "Conflict",
            "Engagement Letter",
            "AQMM Tasks",
            "Evidence Pending",
            "Manager Review Pending",
            "Partner Review Pending",
            "Review Partner Pending",
            "Closure Status",
            "Blockers",
        ])
        for item in payload["engagements"]:
            row = item["row"]
            closure = item.get("closure")
            counts = item["counts"]
            writer.writerow([
                row.client.client_name if row.client else "",
                row.catalogue.service_name if row.catalogue else "",
                row.financial_year or "",
                row.status or "",
                row.quality_workflow_status or "",
                row.quality_kyc_status or "",
                row.quality_independence_status or "",
                row.quality_conflict_status or "",
                row.quality_engagement_letter_status or "",
                counts.get("total", 0),
                counts.get("evidence_pending", 0),
                counts.get("manager_pending", 0),
                counts.get("partner_pending", 0),
                counts.get("review_partner_pending", 0),
                closure.closure_status if closure else "not_started",
                "; ".join(item.get("blockers") or []),
            ])

        data = buf.getvalue().encode("utf-8-sig")
        filename = f"aqmm_dashboard_{financial_year or 'all'}.csv"
        return StreamingResponse(
            iter([data]),
            media_type="text/csv",
            headers={"Content-Disposition": f'attachment; filename="{filename}"'},
        )
    finally:
        db.close()
