"""Handler for GET /v1/stats endpoint.

Exposes routing outcome statistics from OutcomeDB via HTTP.
The MCP server (and any other consumer) calls this endpoint
instead of accessing the SQLite database directly.
"""

from __future__ import annotations

from datetime import datetime, timedelta, timezone
from enum import Enum
from typing import Any

import structlog
from fastapi import APIRouter, HTTPException, Query

from robot_resources.tracking.db import OutcomeDB

router = APIRouter()
logger = structlog.get_logger()

# ------------------------------------------------------------------
# DB access (lazy-initialized singleton, same pattern as completions)
# ------------------------------------------------------------------

_outcome_db: OutcomeDB | None = None


def _get_outcome_db() -> OutcomeDB | None:
    """Get or initialize the OutcomeDB singleton.

    Returns None if initialization fails — stats are optional
    and should degrade gracefully.
    """
    global _outcome_db  # noqa: PLW0603
    if _outcome_db is not None:
        return _outcome_db
    try:
        _outcome_db = OutcomeDB()
        _outcome_db.connect()
        logger.info("stats_db_connected")
        return _outcome_db
    except Exception:  # defensive-catch: stats degradation — return None if DB unavailable
        logger.warning("stats_db_init_failed", exc_info=True)
        return None


# ------------------------------------------------------------------
# Period enum
# ------------------------------------------------------------------


class StatsPeriod(str, Enum):
    weekly = "weekly"
    monthly = "monthly"
    all = "all"


# ------------------------------------------------------------------
# Endpoint
# ------------------------------------------------------------------

_PERIOD_DAYS = {"weekly": 7, "monthly": 30}


@router.get("/v1/stats")
async def get_stats(
    period: StatsPeriod = Query(StatsPeriod.weekly, description="Time period for stats"),
    task_type: str | None = Query(None, description="Filter by task type"),
    provider: str | None = Query(None, description="Filter by provider"),
) -> dict[str, Any]:
    """Get routing cost savings statistics.

    Returns aggregated stats from the outcome tracking database,
    filtered by period, task type, and/or provider.
    """
    db = _get_outcome_db()
    if db is None:
        raise HTTPException(
            status_code=503,
            detail={"error": "Tracking database unavailable"},
        )

    # Compute time window
    now = datetime.now(timezone.utc)
    since: datetime | None = None
    if period != StatsPeriod.all:
        days = _PERIOD_DAYS[period.value]
        since = now - timedelta(days=days)

    # Query summary from DB
    summary = db.get_summary(since=since, until=now)

    # If filtering by task_type or provider, we need a filtered query
    if task_type or provider:
        records = db.query(
            since=since,
            until=now,
            task_type=task_type,
            provider=provider,
            limit=100_000,
        )
        total_requests = len(records)
        total_cost_saved = sum(r.cost_saved for r in records)
        total_cost_actual = sum(r.cost_actual for r in records)
        total_cost_baseline = sum(r.cost_baseline for r in records)
        avg_savings = total_cost_saved / total_requests if total_requests > 0 else 0.0

        # Build breakdowns from filtered records
        by_task: dict[str, dict[str, float | int]] = {}
        by_provider: dict[str, dict[str, float | int]] = {}
        for r in records:
            if r.task_type not in by_task:
                by_task[r.task_type] = {"count": 0, "cost_saved": 0.0}
            by_task[r.task_type]["count"] += 1
            by_task[r.task_type]["cost_saved"] = round(
                by_task[r.task_type]["cost_saved"] + r.cost_saved, 6
            )

            if r.provider not in by_provider:
                by_provider[r.provider] = {"count": 0, "cost_saved": 0.0}
            by_provider[r.provider]["count"] += 1
            by_provider[r.provider]["cost_saved"] = round(
                by_provider[r.provider]["cost_saved"] + r.cost_saved, 6
            )

        return {
            "period": period.value,
            "total_requests": total_requests,
            "total_cost_saved": round(total_cost_saved, 6),
            "total_cost_actual": round(total_cost_actual, 6),
            "total_cost_baseline": round(total_cost_baseline, 6),
            "average_savings_per_request": round(avg_savings, 6),
            "breakdown_by_task_type": by_task,
            "breakdown_by_provider": by_provider,
        }

    # Unfiltered path — use summary directly
    cost_by_task = db.get_cost_by_task_type(since=since, until=now)

    # Build provider breakdown from summary
    by_provider_summary: dict[str, dict[str, float | int]] = {}
    if summary.by_provider:
        provider_costs = db.get_cost_by_provider(since=since, until=now)
        for prov, count in summary.by_provider.items():
            by_provider_summary[prov] = {
                "count": count,
                "cost_saved": provider_costs.get(prov, 0.0),
            }

    avg_savings = (
        summary.total_cost_saved / summary.total_requests
        if summary.total_requests > 0
        else 0.0
    )

    return {
        "period": period.value,
        "total_requests": summary.total_requests,
        "total_cost_saved": round(summary.total_cost_saved, 6),
        "total_cost_actual": round(summary.total_cost_actual, 6),
        "total_cost_baseline": round(summary.total_cost_baseline, 6),
        "average_savings_per_request": round(avg_savings, 6),
        "breakdown_by_task_type": cost_by_task,
        "breakdown_by_provider": by_provider_summary,
    }


