"""API key validation and quota checking."""

from __future__ import annotations

import hashlib
import json
import logging
from dataclasses import dataclass

from aiohttp import web

from backend.db.connection import get_db

logger = logging.getLogger("ecate.proxy.auth")


@dataclass
class AuthContext:
    """Resolved API key context attached to each request."""
    key_id: str
    name: str
    strategy: str
    allowed_models: list[str] | None  # None = all allowed
    daily_budget_usd: float | None
    monthly_budget_usd: float | None


async def authenticate(request: web.Request) -> AuthContext:
    """Validate the Bearer token and return the auth context.

    Raises web.HTTPUnauthorized on invalid/missing key.
    Raises web.HTTPTooManyRequests on budget exceeded.
    """
    auth_header = request.headers.get("Authorization", "")
    if not auth_header.startswith("Bearer "):
        raise web.HTTPUnauthorized(text="Missing or invalid Authorization header")

    token = auth_header[7:].strip()
    if not token:
        raise web.HTTPUnauthorized(text="Empty API key")

    key_hash = hashlib.sha256(token.encode()).hexdigest()

    db = await get_db()
    rows = await db.execute_fetchall(
        "SELECT id, name, default_strategy, allowed_models, daily_budget_usd, monthly_budget_usd "
        "FROM api_keys WHERE key_hash = ? AND is_active = TRUE",
        (key_hash,),
    )

    if not rows:
        raise web.HTTPUnauthorized(text="Invalid API key")

    row = rows[0]
    allowed_models = json.loads(row["allowed_models"]) if row["allowed_models"] else None

    ctx = AuthContext(
        key_id=row["id"],
        name=row["name"],
        strategy=row["default_strategy"],
        allowed_models=allowed_models,
        daily_budget_usd=row["daily_budget_usd"],
        monthly_budget_usd=row["monthly_budget_usd"],
    )

    # Check daily budget
    if ctx.daily_budget_usd is not None:
        spent = await db.execute_fetchall(
            "SELECT COALESCE(SUM(cost_usd), 0) as spent FROM usage_logs "
            "WHERE api_key_id = ? AND timestamp >= datetime('now', '-1 day')",
            (ctx.key_id,),
        )
        if spent and spent[0]["spent"] >= ctx.daily_budget_usd:
            raise web.HTTPTooManyRequests(text="Daily budget exceeded")

    # Check monthly budget
    if ctx.monthly_budget_usd is not None:
        spent = await db.execute_fetchall(
            "SELECT COALESCE(SUM(cost_usd), 0) as spent FROM usage_logs "
            "WHERE api_key_id = ? AND timestamp >= datetime('now', '-30 day')",
            (ctx.key_id,),
        )
        if spent and spent[0]["spent"] >= ctx.monthly_budget_usd:
            raise web.HTTPTooManyRequests(text="Monthly budget exceeded")

    return ctx
