from __future__ import annotations

import statistics

from rich.console import Console

from ..checks import gateway, internet
from ..models import CheckResult, MetricAlert, Severity

LINE_WIDTH = 64

console = Console(highlight=False)

# Generated with: toilet -f future "yslow?"
BANNER = (
    "[cyan]╻ ╻┏━┓╻  ┏━┓╻ ╻┏━┓[/cyan]\n"
    "[blue]┗┳┛┗━┓┃  ┃ ┃┃╻┃ ╺┛[/blue]\n"
    "[magenta] ╹ ┗━┛┗━╸┗━┛┗┻┛ ╹[/magenta]"
)


def format_ago(seconds: float) -> str:
    """Format a duration for 'ago' display: seconds if <1m, just minutes after."""
    seconds = int(seconds)
    if seconds < 60:
        return f"{seconds}s ago"
    minutes = (seconds + 30) // 60  # round to nearest minute
    if minutes < 60:
        return f"{minutes}m ago"
    hours = minutes // 60
    mins = minutes % 60
    return f"{hours}h {mins}m ago"


def _alert_lookup(alerts: list[MetricAlert]) -> dict[tuple[str, str], Severity]:
    """Build a lookup from (host, metric) to worst severity."""
    lookup: dict[tuple[str, str], Severity] = {}
    for a in alerts:
        key = (a.host, a.metric)
        if key not in lookup or a.severity == Severity.ERROR:
            lookup[key] = a.severity
    return lookup


def _fmt_metric(
    value: str,
    host: str,
    metric: str,
    lookup: dict[tuple[str, str], Severity],
) -> str:
    """Format a metric value, highlighting if flagged."""
    key = (host, metric)
    if key in lookup:
        color = "red" if lookup[key] == Severity.ERROR else "yellow"
        return f"[{color}]{value}[/{color}]"
    return f"[dim]{value}[/dim]"


def _fmt_metric_for_hosts(
    value: str,
    hosts: set[str],
    metric: str,
    lookup: dict[tuple[str, str], Severity],
) -> str:
    """Format a metric value, highlighting by worst severity across multiple hosts."""
    worst: Severity | None = None
    for h in hosts:
        sev = lookup.get((h, metric))
        if sev == Severity.ERROR:
            worst = sev
            break
        if sev is not None:
            worst = sev
    if worst is not None:
        color = "red" if worst == Severity.ERROR else "yellow"
        return f"[{color}]{value}[/{color}]"
    return f"[dim]{value}[/dim]"


def render_probes(result: CheckResult) -> str:
    lookup = _alert_lookup(result.alerts)
    lines: list[str] = []

    gw = result.gateway
    if gw is None:
        lines.append(f"  [dim]{gateway.LABEL:14s}no gateway detected[/dim]")
    elif not gw.reachable:
        lines.append(f"  [dim]{gateway.LABEL:14s}gateway {gw.host} unreachable[/dim]")
    else:
        rtt = _fmt_metric(f"{gw.avg:5.1f} ms rtt", gw.host, "rtt", lookup)
        loss = _fmt_metric(f"{gw.loss_pct:.0f}% loss", gw.host, "loss", lookup)
        jitter = _fmt_metric(f"{gw.jitter:4.1f} ms jitter", gw.host, "jitter", lookup)
        lines.append(
            f"  [dim]{gateway.LABEL:14s}[/dim]{rtt}[dim],[/dim] {loss}[dim],[/dim] {jitter}"
        )

    reachable_inet = [r for r in result.internet if r.reachable]
    if not reachable_inet:
        lines.append(f"  [dim]{internet.LABEL:14s}all targets unreachable[/dim]")
    else:
        avg_rtt = statistics.mean(r.avg for r in reachable_inet)
        max_loss = max(r.loss_pct for r in reachable_inet)
        max_jitter = max(r.jitter for r in reachable_inet)
        inet_hosts = {r.host for r in reachable_inet}
        lbl = f"{internet.LABEL:14s}"
        rtt = _fmt_metric_for_hosts(f"{avg_rtt:5.1f} ms rtt", inet_hosts, "rtt", lookup)
        loss = _fmt_metric_for_hosts(
            f"{max_loss:.0f}% loss", inet_hosts, "loss", lookup
        )
        jitter = _fmt_metric_for_hosts(
            f"{max_jitter:4.1f} ms jitter", inet_hosts, "jitter", lookup
        )
        lines.append(f"  [dim]{lbl}[/dim]{rtt}[dim],[/dim] {loss}[dim],[/dim] {jitter}")

    # DNS results — one line per resolver
    for r in result.dns:
        suffix = " ✱" if r.is_configured else ""
        lbl = f"{r.label + ':':14s}"
        if r.cached_ms is None and r.uncached_ms is None:
            lines.append(f"  [dim]{lbl}unreachable{suffix}[/dim]")
            continue
        parts = []
        if r.cached_ms is not None:
            cached = _fmt_metric(
                f"{r.cached_ms:5.1f} ms cached", r.server, "dns-cached", lookup
            )
            parts.append(cached)
        if r.uncached_ms is not None:
            uncached = _fmt_metric(
                f"{r.uncached_ms:5.1f} ms uncached", r.server, "dns-uncached", lookup
            )
            parts.append(uncached)
        lines.append(
            f"  [dim]{lbl}[/dim]{'[dim],[/dim] '.join(parts)}[dim]{suffix}[/dim]"
        )

    return "\n".join(lines)
