#!/usr/bin/env python3
"""Render the SDK conformance matrix (GL #395).

Reads the per-SDK scorecards written by the conformance suites
(``conformance-{python,typescript,rust}.json``) and renders the publishable
matrix ``docs/reference/sdk-conformance-matrix.md``: SDK version x engine
version x per-check status. Run by ``scripts/sdk-conformance.sh`` and the
``sdk-conformance`` CI job on every release candidate.
"""

from __future__ import annotations

import argparse
import datetime as dt
import json
import pathlib
import re
import sys

SDK_VERSIONS = {
    "python": ("clients/python/leanctx/__init__.py", r'__version__ = "([^"]+)"'),
    "typescript": ("cookbook/sdk/package.json", r'"version":\s*"([^"]+)"'),
    "rust": ("clients/rust/lean-ctx-client/Cargo.toml", r'^version = "([^"]+)"'),
}


def sdk_version(root: pathlib.Path, sdk: str) -> str:
    rel, pattern = SDK_VERSIONS[sdk]
    text = (root / rel).read_text(encoding="utf-8")
    m = re.search(pattern, text, re.MULTILINE)
    return m.group(1) if m else "unknown"


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("matrix_dir", type=pathlib.Path)
    parser.add_argument("--engine-version", required=True)
    parser.add_argument("--out", type=pathlib.Path, required=True)
    args = parser.parse_args()

    root = pathlib.Path(__file__).resolve().parent.parent
    cards = {}
    for sdk in ("python", "typescript", "rust"):
        path = args.matrix_dir / f"conformance-{sdk}.json"
        if path.is_file():
            cards[sdk] = json.loads(path.read_text(encoding="utf-8"))

    if not cards:
        print("no scorecards found — did the suites run?", file=sys.stderr)
        return 1

    check_names: list[str] = []
    for card in cards.values():
        for check in card["checks"]:
            if check["name"] not in check_names:
                check_names.append(check["name"])

    lines = [
        "# SDK Conformance Matrix",
        "",
        "Status of every first-party SDK against the frozen `/v1` contract",
        "(`run_conformance`, GL #395). Generated by `scripts/sdk-conformance.sh`",
        "against a real `lean-ctx serve` instance — regenerate, never edit.",
        "",
        f"- **Engine:** `{args.engine_version}`",
        f"- **Generated:** {dt.datetime.now(dt.timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}",
        "",
        "| SDK | Package | Version | Conformance |",
        "|---|---|---|---|",
    ]
    packages = {
        "python": "`lean-ctx-client` (PyPI)",
        "typescript": "`lean-ctx-client` (npm)",
        "rust": "`lean-ctx-client` (crates.io)",
    }
    for sdk, card in cards.items():
        verdict = "PASS" if card["all_passed"] else "FAIL"
        lines.append(
            f"| {sdk} | {packages[sdk]} | {sdk_version(root, sdk)} "
            f"| {verdict} ({card['passed']}/{card['total']}) |"
        )

    lines += ["", "## Checks", "", "| Check | " + " | ".join(cards) + " |"]
    lines.append("|---|" + "---|" * len(cards))
    for name in check_names:
        row = [name]
        for card in cards.values():
            check = next((c for c in card["checks"] if c["name"] == name), None)
            if check is None:
                row.append("—")
            elif check["passed"]:
                row.append("pass")
            else:
                detail = check.get("detail", "")
                row.append(f"FAIL {detail}".strip())
        lines.append("| " + " | ".join(row) + " |")

    lines += [
        "",
        "## SemVer coupling",
        "",
        "Every SDK declares the `http_mcp` contract versions it speaks",
        "(`SUPPORTED_HTTP_CONTRACT_VERSIONS`); the `engine_compat` check fails when",
        "a server speaks a contract the SDK release does not support. SDK majors",
        "follow the engine contract major (CONTRACTS.md § Versioning rules).",
        "",
    ]

    args.out.parent.mkdir(parents=True, exist_ok=True)
    args.out.write_text("\n".join(lines), encoding="utf-8")
    print(f"wrote {args.out}")
    return 0 if all(c["all_passed"] for c in cards.values()) else 1


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