"""Codegen Pydantic engine schemas → @recoil/contracts/src/generated.ts.

Run:
    python -m recoil.api.codegen.pydantic_to_ts

The output replaces recoil/console-v2/packages/contracts/src/generated.ts in
place. Phase 17 swaps the desktop/mobile data import sites from
@recoil/fixtures to @recoil/http-adapter, which uses these generated types
as the wire contract.

Requires `json2ts` on PATH (or in console-v2/node_modules/.bin/) — provided
by the json-schema-to-typescript pnpm package.

Phase 16 CI gate: re-run codegen and `git diff --exit-code` the output. Drift
means a Pydantic shape changed without re-running codegen — the gate fails
loudly per Law 4.
"""
from __future__ import annotations

import os
import shutil
import sys
from pathlib import Path

REPO = Path(__file__).resolve().parents[3]  # recoil/.. → CLAUDE_PROJECTS
OUT = REPO / "recoil" / "console-v2" / "packages" / "contracts" / "src" / "generated.ts"


def _resolve_json2ts() -> str:
    """Find json2ts CLI. Prefer the console-v2 node_modules bin."""
    bundled = (
        REPO / "recoil" / "console-v2" / "node_modules" / ".bin" / "json2ts"
    )
    if bundled.exists():
        return str(bundled)
    on_path = shutil.which("json2ts")
    if on_path:
        return on_path
    raise SystemExit(
        "json2ts not found. Install via:\n"
        "  cd recoil/console-v2 && pnpm add -D -w json-schema-to-typescript"
    )


def main() -> int:
    from pydantic2ts import generate_typescript_defs  # type: ignore

    json2ts = _resolve_json2ts()
    OUT.parent.mkdir(parents=True, exist_ok=True)
    generate_typescript_defs(
        "recoil.api.schemas.engine",
        str(OUT),
        exclude=(),
        json2ts_cmd=json2ts,
    )
    # Prepend a "do-not-edit" banner — pydantic2ts writes its own header but
    # we want our explicit Phase-16 marker so reviewers see the source.
    text = OUT.read_text(encoding="utf-8")
    banner = (
        "/* eslint-disable */\n"
        "/**\n"
        " * GENERATED — recoil/api/codegen/pydantic_to_ts.py\n"
        " * Source of truth: recoil/api/schemas/engine.py (Pydantic)\n"
        " * DO NOT HAND-EDIT. Re-run `pnpm codegen` to regenerate.\n"
        " */\n"
    )
    if not text.startswith("/* eslint-disable */"):
        OUT.write_text(banner + text, encoding="utf-8")
    print(f"wrote {OUT.relative_to(REPO)}", file=sys.stderr)
    return 0


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