#!/usr/bin/env python3
"""Claim-loop launcher: load claim-loop.env and resolve k8s:// Service URLs.

Used as ~/bin/rein-aharness-claim on railiance01 so shell never sources JSON
values (AGENT_HARNESS_REPO_MAP). Supports durable ClusterIP access without
kubectl port-forward (ACTIVITY-WP-0027 / docs in activity-core).

Env file keys may use:
  LLM_CONNECT_URL=k8s://activity-core/llm-connect:8080
  ACTIVITY_CORE_URL=k8s://activity-core/actcore-api:8010
  STATE_HUB_URL=k8s://activity-core/actcore-statehub-edge-relay:8000

Resolution uses: kubectl -n <ns> get svc <name> -o jsonpath={.spec.clusterIP}
"""

from __future__ import annotations

import os
import re
import subprocess
import sys
from pathlib import Path

_K8S_URL = re.compile(
    r"^k8s://(?P<ns>[a-z0-9-]+)/(?P<svc>[a-z0-9-]+)(?::(?P<port>\d+))?/?$"
)


def _load_env_file(path: Path) -> dict[str, str]:
    out: dict[str, str] = {}
    if not path.is_file():
        return out
    for line in path.read_text(encoding="utf-8").splitlines():
        line = line.strip()
        if not line or line.startswith("#") or "=" not in line:
            continue
        key, value = line.split("=", 1)
        out[key.strip()] = value.strip()
    return out


def _resolve_k8s_url(value: str) -> str:
    m = _K8S_URL.match(value.strip())
    if not m:
        return value
    ns = m.group("ns")
    svc = m.group("svc")
    port = m.group("port") or "80"
    kubeconfig = os.environ.get("KUBECONFIG", "/etc/rancher/k3s/k3s.yaml")
    cmd = [
        "kubectl",
        f"--kubeconfig={kubeconfig}",
        "-n",
        ns,
        "get",
        "svc",
        svc,
        "-o",
        "jsonpath={.spec.clusterIP}",
    ]
    try:
        ip = subprocess.check_output(cmd, text=True, timeout=30).strip()
    except (subprocess.CalledProcessError, FileNotFoundError, subprocess.TimeoutExpired) as exc:
        print(
            f"rein-aharness-claim: failed to resolve {value!r}: {exc}",
            file=sys.stderr,
        )
        raise SystemExit(2) from exc
    if not ip or ip == "None":
        print(
            f"rein-aharness-claim: empty ClusterIP for {ns}/{svc}",
            file=sys.stderr,
        )
        raise SystemExit(2)
    return f"http://{ip}:{port}"


def _resolve_env(env: dict[str, str]) -> dict[str, str]:
    keys = (
        "LLM_CONNECT_URL",
        "ACTIVITY_CORE_URL",
        "STATE_HUB_URL",
        "STATEHUB_URL",
    )
    for key in keys:
        if key in env and env[key].startswith("k8s://"):
            env[key] = _resolve_k8s_url(env[key])
    return env


def main() -> None:
    home = Path.home()
    env = os.environ.copy()
    # Default kubeconfig for k3s host users
    env.setdefault("KUBECONFIG", "/etc/rancher/k3s/k3s.yaml")
    file_env = _load_env_file(home / ".config/rein-aharness/claim-loop.env")
    env.update(file_env)
    env = _resolve_env(env)

    rein = home / "rein-aharness" / ".venv" / "bin" / "rein-aharness"
    if not rein.is_file():
        # Fall back to PATH
        cmd = ["rein-aharness", *sys.argv[1:]]
    else:
        cmd = [str(rein), *sys.argv[1:]]
    raise SystemExit(subprocess.call(cmd, env=env))


if __name__ == "__main__":
    main()
