from __future__ import annotations

import argparse
import datetime as dt
import json
import sys
import urllib.error
import urllib.request
from pathlib import Path
from typing import Any


ROOT = Path(__file__).resolve().parents[1]
DEFAULT_HEALTH_URL = "http://192.168.220.91:8765/api/health"
DEFAULT_OUTPUT = ROOT / "reports" / "model-chat" / "status.md"


def fetch_json(url: str, timeout: int) -> dict[str, Any]:
    request = urllib.request.Request(url, headers={"Accept": "application/json"})
    try:
        with urllib.request.urlopen(request, timeout=timeout) as response:
            payload = response.read().decode("utf-8")
    except urllib.error.URLError as exc:
        raise RuntimeError(f"failed to fetch {url}: {exc}") from exc
    data = json.loads(payload)
    if not isinstance(data, dict):
        raise RuntimeError(f"health endpoint returned {type(data).__name__}, expected object")
    return data


def table(headers: list[str], rows: list[list[Any]]) -> list[str]:
    lines = [
        "| " + " | ".join(headers) + " |",
        "| " + " | ".join("---" for _ in headers) + " |",
    ]
    for row in rows:
        lines.append("| " + " | ".join(str(value) if value is not None else "" for value in row) + " |")
    return lines


def summarize_routes(health: dict[str, Any]) -> list[list[Any]]:
    rows = []
    for route in health.get("routes") or []:
        model = route.get("model") or {}
        readiness = route.get("readiness") or {}
        rows.append(
            [
                route.get("plugin"),
                model.get("id"),
                route.get("served_model_name"),
                readiness.get("status") or ("online" if route.get("available") else "offline"),
                route.get("base_url"),
            ]
        )
    return rows


def summarize_endpoints(health: dict[str, Any]) -> list[list[Any]]:
    rows = []
    for endpoint in health.get("endpoints") or []:
        models = ", ".join(endpoint.get("models") or [])
        rows.append(
            [
                endpoint.get("id"),
                endpoint.get("status"),
                endpoint.get("base_url"),
                models,
                endpoint.get("latency_ms"),
            ]
        )
    return rows


def summarize_profiles(health: dict[str, Any]) -> list[list[Any]]:
    rows = []
    for profile_id, profile in (health.get("gpu_profile_status") or {}).items():
        rows.append(
            [
                profile_id,
                "yes" if profile.get("ready") else "no",
                ", ".join(profile.get("missing") or []),
                ", ".join(profile.get("conflicts") or []),
            ]
        )
    return rows


def summarize_model_services(health: dict[str, Any]) -> list[list[Any]]:
    rows = []
    for service in health.get("model_services") or []:
        storage = service.get("storage") or {}
        endpoint_models = ", ".join(service.get("endpoint_models") or [])
        rows.append(
            [
                service.get("id"),
                ", ".join(service.get("plugins") or []),
                service.get("runtime"),
                service.get("served_model_name"),
                service.get("status"),
                "yes" if service.get("online") else "no",
                storage.get("status") or ("ok" if storage.get("exists") else "missing"),
                endpoint_models,
            ]
        )
    return rows


def build_markdown(health: dict[str, Any], source_url: str) -> str:
    generated_at = dt.datetime.now(dt.UTC).replace(microsecond=0).isoformat()
    gpu = health.get("gpu") or {}
    lines = [
        "# Model Chat Status",
        "",
        f"- Generated at: `{generated_at}`",
        f"- Source: `{source_url}`",
        f"- Health status: `{health.get('status')}`",
        f"- Host: `{health.get('host')}`",
        f"- Registry models: `{health.get('registry_models')}`",
        f"- GPU: `{gpu.get('summary') or 'unknown'}`",
        "",
        "## Plugin Routes",
        "",
        *table(["plugin", "model", "served model", "status", "base URL"], summarize_routes(health)),
        "",
        "## GPU Profiles",
        "",
        *table(["profile", "ready", "missing", "conflicts"], summarize_profiles(health)),
        "",
        "## Endpoints",
        "",
        *table(["endpoint", "status", "base URL", "models", "latency ms"], summarize_endpoints(health)),
        "",
        "## Model Services",
        "",
        *table(
            ["model", "plugins", "runtime", "served model", "status", "online", "storage", "endpoint models"],
            summarize_model_services(health),
        ),
        "",
    ]
    return "\n".join(lines)


def main() -> int:
    parser = argparse.ArgumentParser(description="Generate a Markdown status report from Model Chat /api/health.")
    parser.add_argument("--url", default=DEFAULT_HEALTH_URL)
    parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT)
    parser.add_argument("--timeout", type=int, default=60)
    parser.add_argument("--print", action="store_true")
    args = parser.parse_args()

    health = fetch_json(args.url, args.timeout)
    markdown = build_markdown(health, args.url)
    args.output.parent.mkdir(parents=True, exist_ok=True)
    args.output.write_text(markdown + "\n", encoding="utf-8")
    if args.print:
        sys.stdout.write(markdown + "\n")
    else:
        print(f"Wrote {args.output}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
