#!/usr/bin/env python3
"""Capture live reef-railiance deployables for the family-declaration validator.

The validator in railiance-master consumes this file via
`--inventory` and must not grow a cluster dependency of its own.
Substrate namespaces and Knative revision Deployments are omitted so
the coverage check sees workload units, not rail machinery.
"""
from __future__ import annotations

import argparse
import json
import re
import subprocess
import sys
from datetime import datetime, timezone
from typing import Any

DEFAULT_REMOTE = "railiance01"
DEFAULT_REEF = "reef-railiance"
SOURCE = "railiance-platform"

SUBSTRATE_NAMESPACES = {
    "cert-manager",
    "cert-manager-test",
    "cnpg-system",
    "default",
    "external-secrets",
    "knative-serving",
    "kube-node-lease",
    "kube-public",
    "kube-system",
    "kourier-system",
    "local-path-storage",
}

EPHEMERAL_NAMESPACE_SUFFIXES = ("-drill", "-test")
KNATIVE_REVISION_DEPLOY = re.compile(r".*-\d{5}-deployment$")

RESOURCE_SPECS = (
    ("Deployment", "deploy"),
    ("StatefulSet", "sts"),
    ("Cluster", "cluster.postgresql.cnpg.io"),
    ("KnativeService", "service.serving.knative.dev"),
)


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(description=__doc__.split("\n\n", 1)[0])
    parser.add_argument(
        "--remote",
        default=DEFAULT_REMOTE,
        help=f"SSH host that can reach the reef API (default: {DEFAULT_REMOTE})",
    )
    parser.add_argument(
        "--reef",
        default=DEFAULT_REEF,
        help=f"Reef identifier recorded in the inventory (default: {DEFAULT_REEF})",
    )
    parser.add_argument(
        "-o",
        "--output",
        help="Write JSON to this path instead of stdout",
    )
    return parser.parse_args()


def remote_get(remote: str, resource: str) -> dict[str, Any]:
    cmd = [
        "ssh",
        "-o",
        "BatchMode=yes",
        remote,
        "kubectl",
        "get",
        resource,
        "-A",
        "-o",
        "json",
    ]
    result = subprocess.run(cmd, check=False, capture_output=True, text=True)
    if result.returncode != 0:
        stderr = (result.stderr or "").strip()
        if "the server doesn't have a resource type" in stderr:
            return {"items": []}
        raise RuntimeError(f"{' '.join(cmd)} failed ({result.returncode}): {stderr}")
    return json.loads(result.stdout)


def skip_namespace(name: str) -> bool:
    if name in SUBSTRATE_NAMESPACES:
        return True
    return any(name.endswith(suffix) for suffix in EPHEMERAL_NAMESPACE_SUFFIXES)


def collect(remote: str) -> list[dict[str, str]]:
    seen: set[tuple[str, str, str]] = set()
    deployables: list[dict[str, str]] = []
    for kind, resource in RESOURCE_SPECS:
        payload = remote_get(remote, resource)
        for item in payload.get("items") or []:
            meta = item.get("metadata") or {}
            name = meta.get("name")
            namespace = meta.get("namespace") or ""
            if not isinstance(name, str) or not name:
                continue
            if skip_namespace(namespace):
                continue
            if kind == "Deployment" and KNATIVE_REVISION_DEPLOY.fullmatch(name):
                continue
            key = (name, namespace, kind)
            if key in seen:
                continue
            seen.add(key)
            deployables.append({"name": name, "namespace": namespace, "kind": kind})
    deployables.sort(key=lambda row: (row["namespace"], row["name"], row["kind"]))
    return deployables


def main() -> int:
    args = parse_args()
    try:
        deployables = collect(args.remote)
    except (RuntimeError, json.JSONDecodeError) as exc:
        print(f"capture failed: {exc}", file=sys.stderr)
        return 1
    inventory = {
        "source": SOURCE,
        "captured_at": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
        "reef": args.reef,
        "deployables": deployables,
    }
    text = json.dumps(inventory, indent=2) + "\n"
    if args.output:
        with open(args.output, "w", encoding="utf-8") as fh:
            fh.write(text)
    else:
        sys.stdout.write(text)
    return 0


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