"""hosts command — list hosts that have synced, with last sync time and counts."""

from __future__ import annotations

import asyncio
from datetime import UTC, datetime
from typing import Literal

import typer
from rich.console import Console
from rich.table import Table
from sqlalchemy.exc import OperationalError

from cli_framework import get_context
from session_hub_cli.cli import app
from session_hub_cli.commands._helpers import fmt_datetime, get_query_api, print_json
from session_hub_cli.context import SessionHubContext
from session_hub_core import HostInfo

STALE_AFTER_SECONDS = 24 * 3600


@app.command("hosts")
def hosts(
    ctx: typer.Context,
    format: Literal["table", "json"] = typer.Option(
        "table", "--format", help="Output format: table, json"
    ),
) -> None:
    """List all hosts that have synced, with last sync time and counts."""
    app_ctx = get_context(ctx)
    assert isinstance(app_ctx, SessionHubContext)
    console = app_ctx.console
    try:
        rows = asyncio.run(_get_hosts(console))
    except OperationalError as exc:
        console.print(f"[red]Error:[/red] Cannot connect to PostgreSQL: {exc}")
        raise typer.Exit(1) from None
    if format == "json":
        print_json(console, [row.model_dump(mode="json") for row in rows])
        return
    table = Table(title="Hosts")
    table.add_column("Host", style="cyan")
    table.add_column("Last Sync", style="dim")
    table.add_column("Sessions", justify="right")
    table.add_column("Messages", justify="right")
    table.add_column("Status")
    for row in rows:
        table.add_row(
            row.host,
            fmt_datetime(row.last_sync),
            str(row.session_count),
            str(row.message_count),
            _status(row.last_sync),
        )
    console.print(table)


async def _get_hosts(console: Console) -> list[HostInfo]:
    api = get_query_api(console)
    try:
        return await api.get_hosts()
    finally:
        await api.close()


def _status(last_sync: datetime | None) -> str:
    if last_sync is None:
        return "[red]NEVER[/red]"
    if last_sync.tzinfo is None:
        last_sync = last_sync.replace(tzinfo=UTC)
    age_seconds = (datetime.now(UTC) - last_sync).total_seconds()
    if age_seconds < STALE_AFTER_SECONDS:
        return "[green]OK[/green]"
    hours = int(age_seconds // 3600)
    return f"[yellow]STALE ({hours}h ago)[/yellow]"
