"""Core data models."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any


@dataclass
class BudgetStatus:
    used: float
    limit: float

    @property
    def remaining(self) -> float:
        return max(0.0, self.limit - self.used)

    @property
    def pct_spent(self) -> float:
        if self.limit <= 0:
            return 1.0
        return self.used / self.limit

    @property
    def exceeded(self) -> bool:
        return self.used >= self.limit

    def format_simple(self) -> str:
        pct_left = int((1.0 - self.pct_spent) * 100)
        return f"Budget: ${self.remaining:.3f} remaining of ${self.limit:.2f} ({pct_left}% left)"

    def __str__(self) -> str:
        return self.format_simple()


@dataclass
class EjectDecision:
    should_eject: bool
    reason: str = ""


@dataclass
class CacheStats:
    """Prompt cache performance for a single run."""
    total_prompt_tokens: int = 0
    cached_tokens: int = 0
    cache_creation_tokens: int = 0
    request_count: int = 0
    cache_hit_requests: int = 0

    @property
    def hit_rate(self) -> float:
        if self.total_prompt_tokens == 0:
            return 0.0
        return self.cached_tokens / self.total_prompt_tokens

    def to_dict(self) -> dict:
        return {
            "total_prompt_tokens": self.total_prompt_tokens,
            "cached_tokens": self.cached_tokens,
            "cache_creation_tokens": self.cache_creation_tokens,
            "request_count": self.request_count,
            "cache_hit_requests": self.cache_hit_requests,
            "hit_rate": round(self.hit_rate, 4),
        }


@dataclass
class InfraResult:
    """Result of a single infrastructure readiness check."""

    ok: bool | None  # True=pass, False=fail, None=warn
    detail: str = ""
    hint: str = ""  # actionable remediation suggestion


@dataclass
class RunResult:
    alias: str
    model_id: str
    budget_usd: float
    started_at: str = ""
    finished_at: str = ""
    duration_s: int = 0
    cost_usd: float | None = None
    error: str | None = None
    tool_calls: int = 0
    events_count: int = 0
    output: dict[str, Any] = field(default_factory=dict)
    cache: CacheStats = field(default_factory=CacheStats)

    @property
    def ok(self) -> bool:
        return self.error is None

    def to_dict(self) -> dict:
        return {
            "alias": self.alias,
            "model_id": self.model_id,
            "budget_usd": self.budget_usd,
            "started_at": self.started_at,
            "finished_at": self.finished_at,
            "duration_s": self.duration_s,
            "cost_usd": self.cost_usd,
            "error": self.error,
            "tool_calls": self.tool_calls,
            "events_count": self.events_count,
            "output": self.output,
            "cache": self.cache.to_dict(),
        }
