#!/usr/bin/env python3
import argparse
import json
import sys
import time
import urllib.request
import urllib.error
from datetime import datetime, timezone


def utc_now():
    return datetime.now(timezone.utc).isoformat(timespec="seconds")


def fetch_json(base_url, path, timeout):
    url = base_url.rstrip("/") + path
    try:
        with urllib.request.urlopen(url, timeout=timeout) as r:
            body = r.read().decode("utf-8", errors="replace")
            return {
                "ok": 200 <= r.status < 300,
                "status": r.status,
                "body": body,
                "json": json.loads(body),
                "error": None,
            }
    except Exception as e:
        return {
            "ok": False,
            "status": None,
            "body": "",
            "json": None,
            "error": str(e),
        }


def fetch_text(base_url, path, timeout):
    url = base_url.rstrip("/") + path
    try:
        with urllib.request.urlopen(url, timeout=timeout) as r:
            body = r.read().decode("utf-8", errors="replace")
            return {
                "ok": 200 <= r.status < 300,
                "status": r.status,
                "body": body,
                "error": None,
            }
    except Exception as e:
        return {
            "ok": False,
            "status": None,
            "body": "",
            "error": str(e),
        }


def metric_label_value(metrics_body, metric_name, label):
    prefix = metric_name + "{"
    for line in metrics_body.splitlines():
        if line.startswith(prefix):
            inside = line.split("{", 1)[1].split("}", 1)[0]
            for part in inside.split(","):
                if "=" not in part:
                    continue
                k, v = part.split("=", 1)
                if k.strip() == label:
                    return v.strip().strip('"')
    return None


def add_check(checks, name, status, detail):
    checks.append({
        "name": name,
        "status": status,
        "detail": detail,
    })


def main():
    parser = argparse.ArgumentParser(description="GAL-2 Time Contract diagnostic tool")
    parser.add_argument("--base-url", default="http://127.0.0.1:9095")
    parser.add_argument("--timeout", type=float, default=5.0)
    parser.add_argument("--json", action="store_true")
    args = parser.parse_args()

    checks = []
    base_url = args.base_url.rstrip("/")

    status = fetch_json(base_url, "/status", args.timeout)
    health = fetch_json(base_url, "/health", args.timeout)
    contract = fetch_json(base_url, "/contract", args.timeout)
    metrics = fetch_text(base_url, "/metrics", args.timeout)

    add_check(checks, "/status", "PASS" if status["ok"] else "FAIL", f'HTTP {status["status"]} {status["error"] or ""}'.strip())
    add_check(checks, "/health", "PASS" if health["ok"] else "FAIL", f'HTTP {health["status"]} {health["error"] or ""}'.strip())
    add_check(checks, "/contract", "PASS" if contract["ok"] else "FAIL", f'HTTP {contract["status"]} {contract["error"] or ""}'.strip())
    add_check(checks, "/metrics", "PASS" if metrics["ok"] else "FAIL", f'HTTP {metrics["status"]} {metrics["error"] or ""}'.strip())

    status_json = status["json"] or {}
    health_json = health["json"] or {}
    contract_json = contract["json"] or {}
    metrics_body = metrics["body"] or ""

    status_version = status_json.get("version")
    contract_version = contract_json.get("version")
    metrics_daemon_version = metric_label_value(metrics_body, "gal2_build_info", "daemon_version")
    metrics_contract_version = metric_label_value(metrics_body, "gal2_build_info", "contract_version")

    if status_version and contract_version and metrics_daemon_version and metrics_contract_version:
        version_ok = (status_version == metrics_daemon_version and contract_version == metrics_contract_version)
        add_check(
            checks,
            "version_consistency",
            "PASS" if version_ok else "FAIL",
            f"status={status_version}, contract={contract_version}, metrics_daemon={metrics_daemon_version}, metrics_contract={metrics_contract_version}",
        )
    else:
        add_check(checks, "version_consistency", "WARN", "Could not fully verify version consistency")

    config_present = status_json.get("config_present", health_json.get("config_present"))
    api_key_present = status_json.get("api_key_present", health_json.get("api_key_present"))

    add_check(
        checks,
        "config_present",
        "PASS" if config_present is True else "WARN",
        f"config_present={config_present}",
    )

    add_check(
        checks,
        "api_key_present",
        "PASS" if api_key_present is True else "WARN",
        f"api_key_present={api_key_present}",
    )

    safe = contract_json.get("safe_to_consume")
    mode = contract_json.get("mode")
    reason = contract_json.get("reason")

    add_check(
        checks,
        "safe_to_consume",
        "PASS" if safe is True else "WARN",
        f"safe_to_consume={safe}, mode={mode}, reason={reason}",
    )

    add_check(
        checks,
        "secret_safe",
        "PASS",
        "Doctor reports presence booleans only. It does not print API keys or secret values.",
    )

    report = {
        "schema": "gal2-doctor-report-v1",
        "generated_at_utc": utc_now(),
        "base_url": base_url,
        "summary": {
            "status_version": status_version,
            "contract_version": contract_version,
            "mode": mode,
            "safe_to_consume": safe,
            "reason": reason,
            "config_present": config_present,
            "api_key_present": api_key_present,
        },
        "checks": checks,
    }

    has_fail = any(c["status"] == "FAIL" for c in checks)

    if args.json:
        print(json.dumps(report, indent=2, sort_keys=True))
    else:
        print("GAL-2 Doctor Report")
        print("===================")
        print(f"Generated UTC: {report['generated_at_utc']}")
        print(f"Base URL: {base_url}")
        print("")
        print("Summary")
        print(f"  status_version: {status_version}")
        print(f"  contract_version: {contract_version}")
        print(f"  mode: {mode}")
        print(f"  safe_to_consume: {safe}")
        print(f"  reason: {reason}")
        print(f"  config_present: {config_present}")
        print(f"  api_key_present: {api_key_present}")
        print("")
        print("Checks")
        for c in checks:
            print(f"  [{c['status']}] {c['name']}: {c['detail']}")

    return 2 if has_fail else 0


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