"""Quota usage attribution: a user's own consumption + an admin breakdown across users.

The aggregate daily budget lives in ApiQuotaUsage; here we read the per-spend audit log
(QuotaEvent) to attribute units to the user who triggered them (NULL actor = system).
"""
from datetime import datetime, timedelta, timezone

from fastapi import APIRouter, Depends
from sqlalchemy import func, select
from sqlalchemy.orm import Session

from app import quota
from app.auth import current_user
from app.db import get_db
from app.models import QuotaEvent, User
from app.routes.admin import admin_user

router = APIRouter(prefix="/api/quota", tags=["quota"])


def _sum(db: Session, *conds) -> int:
    return int(
        db.scalar(
            select(func.coalesce(func.sum(QuotaEvent.units), 0)).where(*conds)
        )
        or 0
    )


@router.get("/my-usage")
def my_usage(
    user: User = Depends(current_user), db: Session = Depends(get_db)
) -> dict:
    now = datetime.now(timezone.utc)
    mine = QuotaEvent.user_id == user.id
    by_action = {
        action: int(units)
        for action, units in db.execute(
            select(QuotaEvent.action, func.sum(QuotaEvent.units))
            .where(mine, QuotaEvent.created_at >= now - timedelta(days=30))
            .group_by(QuotaEvent.action)
        ).all()
    }
    return {
        "today": _sum(db, mine, QuotaEvent.created_at >= quota.pacific_day_start_utc()),
        "last_7d": _sum(db, mine, QuotaEvent.created_at >= now - timedelta(days=7)),
        "last_30d": _sum(db, mine, QuotaEvent.created_at >= now - timedelta(days=30)),
        "all_time": _sum(db, mine),
        "by_action": by_action,
    }


@router.get("/admin")
def admin_usage(
    days: int = 30,
    _: User = Depends(admin_user),
    db: Session = Depends(get_db),
) -> dict:
    days = max(1, min(days, 365))
    since = datetime.now(timezone.utc) - timedelta(days=days)

    totals = db.execute(
        select(QuotaEvent.user_id, func.sum(QuotaEvent.units))
        .where(QuotaEvent.created_at >= since)
        .group_by(QuotaEvent.user_id)
    ).all()

    per_action: dict[int | None, dict[str, int]] = {}
    for uid, action, units in db.execute(
        select(QuotaEvent.user_id, QuotaEvent.action, func.sum(QuotaEvent.units))
        .where(QuotaEvent.created_at >= since)
        .group_by(QuotaEvent.user_id, QuotaEvent.action)
    ).all():
        per_action.setdefault(uid, {})[action] = int(units)

    uids = [uid for uid, _ in totals if uid is not None]
    emails = (
        {u.id: u.email for u in db.execute(select(User).where(User.id.in_(uids))).scalars()}
        if uids
        else {}
    )

    rows = [
        {
            "user_id": uid,
            "email": emails.get(uid, "(deleted user)") if uid is not None else "System",
            "total": int(total),
            "by_action": per_action.get(uid, {}),
        }
        for uid, total in totals
    ]
    rows.sort(key=lambda r: r["total"], reverse=True)

    # Instance-wide daily series in Pacific days (matches the budget reset).
    day_expr = func.date(func.timezone("America/Los_Angeles", QuotaEvent.created_at))
    daily = [
        {"day": str(day), "total": int(units)}
        for day, units in db.execute(
            select(day_expr, func.sum(QuotaEvent.units))
            .where(QuotaEvent.created_at >= since)
            .group_by(day_expr)
            .order_by(day_expr)
        ).all()
    ]

    return {"range_days": days, "rows": rows, "daily": daily}
