"""API routes for statistics and dashboard data."""

from collections import defaultdict
from datetime import datetime, timezone

from fastapi import APIRouter, Depends
from sqlmodel import Session

from agenteval.storage.model_config_repository import ModelConfigRepository
from agenteval.storage.repository import RunRepository, ScenarioRepository, TargetRepository
from agenteval.web.deps import get_db

router = APIRouter()


def _ts(dt: datetime | None) -> float:
    """Sortable timestamp tolerant of naive/aware mixes in legacy rows."""
    if dt is None:
        return 0.0
    if dt.tzinfo is None:
        dt = dt.replace(tzinfo=timezone.utc)
    return dt.timestamp()


@router.get("/dashboard")
def dashboard(session: Session = Depends(get_db)) -> dict:
    targets = TargetRepository(session).list_all()
    scenarios = ScenarioRepository(session).list_all()
    runs = RunRepository(session).list_all()
    model_configs = ModelConfigRepository(session).list_all()

    scenario_names = {s.id: s.name for s in scenarios}
    target_names = {t.id: t.name for t in targets}

    completed_runs = [r for r in runs if r.status == "completed" and r.summary]
    pass_rates = [r.summary.get("pass_rate", 0) for r in completed_runs if isinstance(r.summary, dict)]
    overall_pass_rate = sum(pass_rates) / len(pass_rates) if pass_rates else None

    today = datetime.now(timezone.utc).date()
    today_runs = 0
    running_count = 0
    trigger_breakdown: dict[str, int] = defaultdict(int)
    for r in runs:
        if r.started_at:
            started = r.started_at
            if started.tzinfo is None:
                started = started.replace(tzinfo=timezone.utc)
            if started.date() == today:
                today_runs += 1
        if r.status in ("running", "pending"):
            running_count += 1
        trigger_breakdown[r.triggered_by.value] += 1

    # Per-scenario aggregation over completed runs.
    by_scenario: dict[str, list] = defaultdict(list)
    for r in completed_runs:
        by_scenario[r.scenario_id].append(r)
    scenario_stats = []
    for sid, sruns in by_scenario.items():
        rates = [r.summary.get("pass_rate", 0) for r in sruns if isinstance(r.summary, dict)]
        last_run = max(sruns, key=lambda r: _ts(r.started_at))
        scenario_stats.append({
            "scenario_id": sid,
            "scenario_name": scenario_names.get(sid, sid[:8]),
            "run_count": len(sruns),
            "avg_pass_rate": round(sum(rates) / len(rates), 4) if rates else None,
            "last_run_at": last_run.started_at.isoformat() if last_run.started_at else None,
        })
    scenario_stats.sort(key=lambda s: s["run_count"], reverse=True)

    recent_runs = sorted(runs, key=lambda r: _ts(r.started_at), reverse=True)[:10]

    return {
        "targets_count": len(targets),
        "scenarios_count": len(scenarios),
        "runs_count": len(runs),
        "model_configs_count": len(model_configs),
        "today_runs": today_runs,
        "running_count": running_count,
        "overall_pass_rate": overall_pass_rate,
        "trigger_breakdown": dict(trigger_breakdown),
        "scenario_stats": scenario_stats,
        "recent_runs": [
            {
                **r.model_dump(),
                "scenario_name": scenario_names.get(r.scenario_id),
                "target_name": target_names.get(r.target_id),
            }
            for r in recent_runs
        ],
    }


@router.get("/trend")
def trend(days: int = 30, session: Session = Depends(get_db)) -> list[dict]:
    runs = RunRepository(session).list_all()
    completed = [r for r in runs if r.status == "completed" and r.summary and r.started_at]

    daily: dict[str, list[float]] = defaultdict(list)
    for run in completed:
        date_str = run.started_at.strftime("%Y-%m-%d") if run.started_at else ""
        if date_str and isinstance(run.summary, dict):
            daily[date_str].append(run.summary.get("pass_rate", 0))

    sorted_dates = sorted(daily.keys())[-days:]
    return [
        {
            "date": d,
            "pass_rate": round(sum(daily[d]) / len(daily[d]) * 100, 1),
            "run_count": len(daily[d]),
        }
        for d in sorted_dates
    ]
