from __future__ import annotations

from datetime import datetime

from fastapi import APIRouter, Depends, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from routes.template_filters import create_templates

from dependencies import get_current_user, get_unit_of_work
from models import ScenarioStatus, User
from services.unit_of_work import UnitOfWork

router = APIRouter(tags=["Dashboard"])
templates = create_templates()


def _format_timestamp(moment: datetime | None) -> str | None:
    if moment is None:
        return None
    return moment.strftime("%Y-%m-%d")


def _format_timestamp_with_time(moment: datetime | None) -> str | None:
    if moment is None:
        return None
    return moment.strftime("%Y-%m-%d %H:%M")


def _load_metrics(uow: UnitOfWork) -> dict[str, object]:
    if not uow.projects or not uow.scenarios or not uow.financial_inputs:
        raise RuntimeError("UnitOfWork repositories not initialised")
    total_projects = uow.projects.count()
    active_scenarios = uow.scenarios.count_by_status(ScenarioStatus.ACTIVE)
    pending_simulations = uow.scenarios.count_by_status(ScenarioStatus.DRAFT)
    last_import_at = uow.financial_inputs.latest_created_at()
    return {
        "total_projects": total_projects,
        "active_scenarios": active_scenarios,
        "pending_simulations": pending_simulations,
        "last_import": _format_timestamp(last_import_at),
    }


def _load_recent_projects(uow: UnitOfWork) -> list:
    if not uow.projects:
        raise RuntimeError("Project repository not initialised")
    return list(uow.projects.recent(limit=5))


def _load_simulation_updates(uow: UnitOfWork) -> list[dict[str, object]]:
    updates: list[dict[str, object]] = []
    if not uow.scenarios:
        raise RuntimeError("Scenario repository not initialised")
    scenarios = uow.scenarios.recent(limit=5, with_project=True)
    for scenario in scenarios:
        project_name = scenario.project.name if scenario.project else f"Project #{scenario.project_id}"
        timestamp_label = _format_timestamp_with_time(scenario.updated_at)
        updates.append(
            {
                "title": f"{scenario.name} · {scenario.status.value.title()}",
                "description": f"Latest update recorded for {project_name}.",
                "timestamp": scenario.updated_at,
                "timestamp_label": timestamp_label,
            }
        )
    return updates


def _load_scenario_alerts(
    request: Request, uow: UnitOfWork
) -> list[dict[str, object]]:
    alerts: list[dict[str, object]] = []

    if not uow.scenarios:
        raise RuntimeError("Scenario repository not initialised")

    drafts = uow.scenarios.list_by_status(
        ScenarioStatus.DRAFT, limit=3, with_project=True
    )
    for scenario in drafts:
        project_name = scenario.project.name if scenario.project else f"Project #{scenario.project_id}"
        alerts.append(
            {
                "title": f"Draft scenario: {scenario.name}",
                "message": f"{project_name} has a scenario awaiting validation.",
                "link": request.url_for(
                    "projects.view_project", project_id=scenario.project_id
                ),
            }
        )

    if not alerts:
        archived = uow.scenarios.list_by_status(
            ScenarioStatus.ARCHIVED, limit=3, with_project=True
        )
        for scenario in archived:
            project_name = scenario.project.name if scenario.project else f"Project #{scenario.project_id}"
            alerts.append(
                {
                    "title": f"Archived scenario: {scenario.name}",
                    "message": f"Review archived scenario insights for {project_name}.",
                    "link": request.url_for(
                        "scenarios.view_scenario", scenario_id=scenario.id
                    ),
                }
            )

    return alerts


@router.get("/", include_in_schema=False, name="dashboard.home", response_model=None)
def dashboard_home(
    request: Request,
    user: User | None = Depends(get_current_user),
    uow: UnitOfWork = Depends(get_unit_of_work),
) -> HTMLResponse | RedirectResponse:
    if user is None:
        return RedirectResponse(request.url_for("auth.login_form"), status_code=303)

    context = {
        "metrics": _load_metrics(uow),
        "recent_projects": _load_recent_projects(uow),
        "simulation_updates": _load_simulation_updates(uow),
        "scenario_alerts": _load_scenario_alerts(request, uow),
        "export_modals": {
            "projects": request.url_for("exports.modal", dataset="projects"),
            "scenarios": request.url_for("exports.modal", dataset="scenarios"),
        },
    }
    return templates.TemplateResponse(request, "dashboard.html", context)
