from __future__ import annotations

import json
import os
import sys
import time
from typing import Any
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen


def _json_request(url: str, token: str | None = None, timeout: float = 5.0) -> dict[str, Any]:
    headers = {"Accept": "application/json"}
    if token:
        headers["X-Compute-Token"] = token
    request = Request(url, headers=headers)
    started = time.perf_counter()
    try:
        with urlopen(request, timeout=timeout) as response:
            body = response.read().decode("utf-8", errors="replace")
            data = json.loads(body) if body else {}
            return {
                "ok": 200 <= response.status < 300,
                "status": response.status,
                "duration_ms": int((time.perf_counter() - started) * 1000),
                "data": data,
            }
    except HTTPError as exc:
        body = exc.read().decode("utf-8", errors="replace")
        return {
            "ok": False,
            "status": exc.code,
            "duration_ms": int((time.perf_counter() - started) * 1000),
            "error": body or str(exc),
        }
    except (URLError, TimeoutError, OSError) as exc:
        return {
            "ok": False,
            "duration_ms": int((time.perf_counter() - started) * 1000),
            "error": str(exc),
        }


def _postgres_check(database_url: str | None) -> dict[str, Any]:
    if not database_url:
        return {"ok": False, "skipped": True, "error": "DATABASE_URL is not set"}
    try:
        import psycopg
    except ImportError:
        return {"ok": False, "skipped": True, "error": "psycopg is not installed"}
    started = time.perf_counter()
    try:
        with psycopg.connect(database_url.replace("postgresql+psycopg://", "postgresql://"), connect_timeout=5) as conn:
            with conn.cursor() as cursor:
                cursor.execute(
                    """
                    SELECT table_name
                    FROM information_schema.tables
                    WHERE table_schema='public'
                      AND table_name IN ('users','fine_tune_tasks','compute_nodes','compute_jobs','gpu_allocations')
                    ORDER BY table_name
                    """
                )
                tables = [row[0] for row in cursor.fetchall()]
        return {"ok": len(tables) >= 5, "duration_ms": int((time.perf_counter() - started) * 1000), "tables": tables}
    except Exception as exc:  # noqa: BLE001 - diagnostics should report instead of crashing
        return {"ok": False, "duration_ms": int((time.perf_counter() - started) * 1000), "error": str(exc)}


def main() -> int:
    route_prefix = os.getenv("ROUTE_PREFIX", "/modelTF").rstrip("/")
    app_base_url = os.getenv("APP_BASE_URL", "http://localhost:17861").rstrip("/")
    compute_base_url = os.getenv("COMPUTE_BASE_URL", "").rstrip("/")
    compute_token = os.getenv("COMPUTE_SERVICE_TOKEN")
    checks: list[dict[str, Any]] = [
        {"name": "backend health", **_json_request(f"{app_base_url}{route_prefix}/health")},
        {"name": "postgres schema", **_postgres_check(os.getenv("DATABASE_URL"))},
    ]
    if compute_base_url:
        checks.extend(
            [
                {
                    "name": "compute health",
                    **_json_request(f"{compute_base_url}{route_prefix}/v1/compute/health", compute_token),
                },
                {
                    "name": "compute gpus",
                    **_json_request(f"{compute_base_url}{route_prefix}/compute/resources/gpus", compute_token),
                },
                {
                    "name": "compute jobs",
                    **_json_request(f"{compute_base_url}{route_prefix}/compute/jobs", compute_token),
                },
            ]
        )
    else:
        checks.append({"name": "compute health", "ok": False, "skipped": True, "error": "COMPUTE_BASE_URL is not set"})
    report = {"ok": all(item.get("ok") or item.get("skipped") for item in checks), "checks": checks}
    print(json.dumps(report, ensure_ascii=False, indent=2))
    return 0 if report["ok"] else 1


if __name__ == "__main__":
    sys.exit(main())
