from __future__ import annotations

from io import BytesIO

from fastapi import APIRouter, File, Form, Request, UploadFile
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, validate_csrf
from app.core.security.session_auth import get_current_user
from app.core.templating import templates
from app.modules.core.rbac.deps import get_user_permissions, get_user_roles
from app.modules.firm_admin_dashboard.service import (
    build_dashboard_payload,
    build_user_onboarding_payload,
    can_access_firm_admin_dashboard,
    build_firm_user_import_template,
    create_firm_internal_user,
    get_onboarding_role_config,
    import_firm_internal_users,
)

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

VALID_TABS = {
    "overview": "modules/firm_admin_dashboard/templates/firm_admin_dashboard/partials/overview.html",
    "branches": "modules/firm_admin_dashboard/templates/firm_admin_dashboard/partials/branches.html",
    "users": "modules/firm_admin_dashboard/templates/firm_admin_dashboard/partials/users.html",
    "firm-settings": "modules/firm_admin_dashboard/templates/firm_admin_dashboard/partials/firm_settings.html",
    "services": "modules/firm_admin_dashboard/templates/firm_admin_dashboard/partials/services.html",
    "financial-years": "modules/firm_admin_dashboard/templates/firm_admin_dashboard/partials/financial_years.html",
    "reports": "modules/firm_admin_dashboard/templates/firm_admin_dashboard/partials/reports.html",
    "wizards": "modules/firm_admin_dashboard/templates/firm_admin_dashboard/partials/wizards.html",
    "audit-logs": "modules/firm_admin_dashboard/templates/firm_admin_dashboard/partials/audit_logs.html",
}


def _redirect_login():
    return RedirectResponse(url="/login", status_code=303)


def _ctx(request: Request, db, current_user, *, active_tab: str = "overview", **extra):
    payload = build_dashboard_payload(db, request, current_user)
    ctx = {
        "request": request,
        "current_user": current_user,
        "current_user_roles": get_user_roles(db, current_user.id),
        "current_user_permissions": get_user_permissions(db, current_user.id),
        "csrf_token": get_or_create_csrf_token(request),
        "title": "Firm Administration",
        "active_tab": active_tab,
        **payload,
    }
    ctx.update(extra)
    return ctx


def _onboarding_ctx(request: Request, db, current_user, role: str, **extra):
    payload = build_user_onboarding_payload(db, request, current_user, role)
    ctx = {
        "request": request,
        "current_user": current_user,
        "current_user_roles": get_user_roles(db, current_user.id),
        "current_user_permissions": get_user_permissions(db, current_user.id),
        "csrf_token": get_or_create_csrf_token(request),
        "title": "Add Firm User",
        **payload,
    }
    ctx.update(extra)
    return ctx


@router.get("/dashboard")
def dashboard(request: Request, tab: str = "overview"):
    db = CommonSessionLocal()
    try:
        current_user = get_current_user(request, db=db)
        if not current_user:
            return _redirect_login()
        if not can_access_firm_admin_dashboard(db, current_user):
            return ui_access_denied()
        active_tab = tab if tab in VALID_TABS else "overview"
        return templates.TemplateResponse(
            "modules/firm_admin_dashboard/templates/firm_admin_dashboard/dashboard.html",
            _ctx(request, db, current_user, active_tab=active_tab),
        )
    finally:
        db.close()


@router.get("/dashboard/tab/{tab_name}")
def dashboard_tab(request: Request, tab_name: str):
    db = CommonSessionLocal()
    try:
        current_user = get_current_user(request, db=db)
        if not current_user:
            return _redirect_login()
        if not can_access_firm_admin_dashboard(db, current_user):
            return ui_access_denied()
        active_tab = tab_name if tab_name in VALID_TABS else "overview"
        return templates.TemplateResponse(VALID_TABS[active_tab], _ctx(request, db, current_user, active_tab=active_tab))
    finally:
        db.close()


@router.get("/users/new")
def user_onboarding_form(request: Request, role: str = "staff"):
    db = CommonSessionLocal()
    try:
        current_user = get_current_user(request, db=db)
        if not current_user:
            return _redirect_login()
        if not can_access_firm_admin_dashboard(db, current_user):
            return ui_access_denied()
        if not get_onboarding_role_config(role):
            return RedirectResponse(url="/firm-admin/dashboard?tab=users", status_code=303)
        return templates.TemplateResponse(
            "modules/firm_admin_dashboard/templates/firm_admin_dashboard/user_onboarding.html",
            _onboarding_ctx(request, db, current_user, role),
        )
    finally:
        db.close()


@router.post("/users/new")
def user_onboarding_submit(
    request: Request,
    role: str = Form(...),
    email: str = Form(...),
    full_name: str = Form(...),
    branch_id: int = Form(...),
    employee_code: str = Form(""),
    mobile: str = Form(""),
    department: str = Form(""),
    designation: str = Form(""),
    date_of_joining: str = Form(""),
    employment_type: str = Form("full_time"),
    consultant_type: str = Form("external_consultant"),
    firm_name: str = Form(""),
    specialisation: str = Form(""),
    gstin: str = Form(""),
    pan: str = Form(""),
    address: str = Form(""),
    remarks: str = Form(""),
    csrf_token: str = Form(...),
):
    validate_csrf(request, csrf_token)
    db = CommonSessionLocal()
    try:
        current_user = get_current_user(request, db=db)
        if not current_user:
            return _redirect_login()
        if not can_access_firm_admin_dashboard(db, current_user):
            return ui_access_denied()
        if not get_onboarding_role_config(role):
            return RedirectResponse(url="/firm-admin/dashboard?tab=users", status_code=303)

        try:
            result = create_firm_internal_user(
                db,
                request=request,
                actor=current_user,
                role_key=role,
                email=email,
                full_name=full_name,
                branch_id=branch_id,
                employee_code=employee_code,
                mobile=mobile,
                department=department,
                designation=designation,
                date_of_joining=date_of_joining,
                employment_type=employment_type,
                consultant_type=consultant_type,
                firm_name=firm_name,
                specialisation=specialisation,
                gstin=gstin,
                pan=pan,
                address=address,
                remarks=remarks,
            )
        except Exception as exc:
            db.rollback()
            return templates.TemplateResponse(
                "modules/firm_admin_dashboard/templates/firm_admin_dashboard/user_onboarding.html",
                _onboarding_ctx(
                    request,
                    db,
                    current_user,
                    role,
                    flash=str(exc),
                    form_data={
                        "email": email,
                        "full_name": full_name,
                        "branch_id": branch_id,
                        "employee_code": employee_code,
                        "mobile": mobile,
                        "department": department,
                        "designation": designation,
                        "date_of_joining": date_of_joining,
                        "employment_type": employment_type,
                        "consultant_type": consultant_type,
                        "firm_name": firm_name,
                        "specialisation": specialisation,
                        "gstin": gstin,
                        "pan": pan,
                        "address": address,
                        "remarks": remarks,
                    },
                ),
                status_code=400,
            )

        return templates.TemplateResponse(
            "modules/firm_admin_dashboard/templates/firm_admin_dashboard/user_onboarding_done.html",
            _ctx(request, db, current_user, active_tab="users", title="Invite Link", onboarding_result=result),
        )
    finally:
        db.close()

@router.get("/users/import")
def user_import_form(request: Request):
    db = CommonSessionLocal()
    try:
        current_user = get_current_user(request, db=db)
        if not current_user:
            return _redirect_login()
        if not can_access_firm_admin_dashboard(db, current_user):
            return ui_access_denied()
        return templates.TemplateResponse(
            "modules/firm_admin_dashboard/templates/firm_admin_dashboard/user_import.html",
            _ctx(request, db, current_user, active_tab="users", title="Import Firm Users"),
        )
    finally:
        db.close()


@router.get("/users/import/template")
def user_import_template(request: Request):
    db = CommonSessionLocal()
    try:
        current_user = get_current_user(request, db=db)
        if not current_user:
            return _redirect_login()
        if not can_access_firm_admin_dashboard(db, current_user):
            return ui_access_denied()
        content = build_firm_user_import_template(db, request, current_user)
        return StreamingResponse(
            BytesIO(content),
            media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            headers={"Content-Disposition": 'attachment; filename="firm_admin_user_import_template.xlsx"'},
        )
    finally:
        db.close()


@router.post("/users/import")
async def user_import_submit(request: Request, import_file: UploadFile = File(...), csrf_token: str = Form(...)):
    validate_csrf(request, csrf_token)
    db = CommonSessionLocal()
    try:
        current_user = get_current_user(request, db=db)
        if not current_user:
            return _redirect_login()
        if not can_access_firm_admin_dashboard(db, current_user):
            return ui_access_denied()
        if not import_file.filename or not import_file.filename.lower().endswith((".xlsx", ".xlsm")):
            return templates.TemplateResponse(
                "modules/firm_admin_dashboard/templates/firm_admin_dashboard/user_import.html",
                _ctx(request, db, current_user, active_tab="users", title="Import Firm Users", flash="Please upload an .xlsx Excel file."),
                status_code=400,
            )
        try:
            content = await import_file.read()
            result = import_firm_internal_users(db, request=request, actor=current_user, content=content)
        except Exception as exc:
            db.rollback()
            return templates.TemplateResponse(
                "modules/firm_admin_dashboard/templates/firm_admin_dashboard/user_import.html",
                _ctx(request, db, current_user, active_tab="users", title="Import Firm Users", flash=str(exc)),
                status_code=400,
            )
        return templates.TemplateResponse(
            "modules/firm_admin_dashboard/templates/firm_admin_dashboard/user_import_done.html",
            _ctx(request, db, current_user, active_tab="users", title="Import Result", import_result=result),
        )
    finally:
        db.close()

