"""LLMHosts TUI dashboard -- color theme and formatting utilities.

Centralises all visual constants so widgets stay clean and consistent.
"""

from __future__ import annotations

# ---------------------------------------------------------------------------
# Color palette (Rich markup / Textual CSS color names)
# ---------------------------------------------------------------------------

COLORS: dict[str, str] = {
    # Savings & cost
    "savings": "green",
    "cost": "red",
    # Backend routing types
    "local": "cyan",
    "cloud": "yellow",
    "cache": "magenta",
    # Health
    "healthy": "green",
    "unhealthy": "red",
    "degraded": "yellow",
    # UI chrome
    "header": "bold bright_blue",
    "header_bg": "rgb(20,20,40)",
    "muted": "dim white",
    "accent": "bright_blue",
    "border": "rgb(80,80,120)",
    "label": "bold white",
    "value": "white",
    "separator": "rgb(60,60,100)",
}

# Rich markup convenience aliases
_S = COLORS  # shorthand for inline use

# Backend → display colour mapping
BACKEND_COLORS: dict[str, str] = {
    "ollama": "cyan",
    "openai": "green",
    "anthropic": "dark_orange",
    "openrouter": "yellow",
    "cache": "magenta",
}

# Route type → display colour mapping
ROUTE_COLORS: dict[str, str] = {
    "local": "cyan",
    "cloud": "yellow",
    "cache": "magenta",
}

# Health indicator symbols
HEALTH_ICONS: dict[bool, str] = {
    True: "[green]●[/green]",
    False: "[red]●[/red]",
}


# ---------------------------------------------------------------------------
# Formatting helpers
# ---------------------------------------------------------------------------


def format_cost(amount: float) -> str:
    """Format a USD cost for display.

    Examples: ``$0.00``, ``$0.04``, ``$12.50``, ``$1,234.56``.
    """
    if amount < 0.005:
        return "$0.00"
    if amount < 1.0:
        return f"${amount:.2f}"
    if amount < 1_000.0:
        return f"${amount:,.2f}"
    return f"${amount:,.0f}"


def format_latency(ms: float) -> str:
    """Format latency in milliseconds.

    Below 1000ms shows ms; above shows seconds.
    Examples: ``12ms``, ``145ms``, ``1.2s``.
    """
    if ms < 1.0:
        return "<1ms"
    if ms < 1_000.0:
        return f"{ms:.0f}ms"
    return f"{ms / 1_000.0:.1f}s"


def format_savings_percent(pct: float) -> str:
    """Format a savings percentage.

    Examples: ``0%``, ``64%``, ``99.5%``.
    """
    if pct <= 0.0:
        return "0%"
    if pct >= 99.95:
        return "100%"
    if pct < 10.0:
        return f"{pct:.1f}%"
    return f"{pct:.0f}%"


def format_uptime(seconds: float) -> str:
    """Format an uptime duration into a human-readable string.

    Examples: ``0s``, ``45s``, ``12m 30s``, ``2h 15m``, ``1d 3h``.
    """
    if seconds < 0:
        return "0s"

    total = int(seconds)
    days, remainder = divmod(total, 86400)
    hours, remainder = divmod(remainder, 3600)
    minutes, secs = divmod(remainder, 60)

    if days > 0:
        return f"{days}d {hours}h" if hours else f"{days}d"
    if hours > 0:
        return f"{hours}h {minutes}m" if minutes else f"{hours}h"
    if minutes > 0:
        return f"{minutes}m {secs}s" if secs else f"{minutes}m"
    return f"{secs}s"


def format_tokens(count: int) -> str:
    """Format a token count with SI suffix.

    Examples: ``0``, ``450``, ``12.3K``, ``1.5M``.
    """
    if count < 1_000:
        return str(count)
    if count < 1_000_000:
        return f"{count / 1_000:.1f}K"
    if count < 1_000_000_000:
        return f"{count / 1_000_000:.1f}M"
    return f"{count / 1_000_000_000:.1f}B"


def format_rpm(rpm: float) -> str:
    """Format requests-per-minute.

    Examples: ``0.0``, ``1.5``, ``12.3``.
    """
    if rpm < 0.05:
        return "0.0"
    return f"{rpm:.1f}"


def format_percent(value: float) -> str:
    """Format a 0-1 ratio as a percentage string.

    Examples: ``0%``, ``72%``, ``100%``.
    """
    pct = value * 100.0
    if pct <= 0.0:
        return "0%"
    if pct >= 99.95:
        return "100%"
    return f"{pct:.0f}%"


def backend_color(backend: str) -> str:
    """Return the Rich colour name for a backend type."""
    return BACKEND_COLORS.get(backend.lower(), "white")


def route_label(backend: str, cached: bool) -> tuple[str, str]:
    """Return (label, colour) for a routing decision.

    Returns
    -------
    tuple[str, str]
        A ``(label, rich_colour)`` pair such as ``("local", "cyan")``.
    """
    if cached:
        return "cache", ROUTE_COLORS["cache"]
    if backend.lower() == "ollama":
        return "local", ROUTE_COLORS["local"]
    return "cloud", ROUTE_COLORS["cloud"]


def sparkline(values: list[float], width: int = 8) -> str:
    """Render a tiny Unicode sparkline from a list of values.

    Uses the block characters U+2581..U+2588.
    """
    if not values:
        return " " * width
    # Take the last ``width`` values
    sample = values[-width:]
    lo = min(sample)
    hi = max(sample)
    span = hi - lo if hi != lo else 1.0
    blocks = " ▁▂▃▄▅▆▇█"
    out: list[str] = []
    for v in sample:
        idx = int((v - lo) / span * 8)
        idx = max(0, min(idx, 8))
        out.append(blocks[idx])
    # Pad left if shorter than width
    return "".join(out).rjust(width)
