r"""
Render a broadcast demo MP4 for EVERY race in the GSYS manifest (the 12 May-23/24 flights), one file
per race, in one language. Thin orchestrator over `record_demo.py --race <id>`.

  ..\..\..\.venv-demo\Scripts\python.exe demo/record/record_all_gsys.py --lang en

Output: <out-dir>/<raceId>_<lang>.mp4  (default demo/_cap/gsys_<lang>/). RESUMABLE — a race whose
output already exists is skipped, so a crash mid-batch just continues. Pre-synthesize the commentary
once first (export/synth_races.py --lang <lang>); each race still self-checks its clips before
recording. Each race is ~8 min real-time, captured headless frame-by-frame, so the full set is a long,
GPU-heavy run — leave it going.
"""
from __future__ import annotations

import argparse
import json
import subprocess
import sys
import time
from pathlib import Path

HERE = Path(__file__).resolve().parent
ROOT = HERE.parent.parent                                  # v3/broadcast
MANIFEST = ROOT / "demo" / "data" / "races" / "manifest.json"


def races() -> list[tuple[str, str]]:
    """(raceId, title) for every manifest race. The title is the race name (date + local start time)."""
    return [(r["id"], r.get("title") or r["id"])
            for r in json.loads(MANIFEST.read_text(encoding="utf-8")).get("races", [])]


def _safe(title: str) -> str:
    """Filesystem-safe filename from a race title — Windows forbids : \\ / * ? \" < > | so the time's
    colon becomes a hyphen ('2026-05-22 15:08' → '2026-05-22 15-08')."""
    for ch in ':\\/*?"<>|':
        title = title.replace(ch, "-")
    return title.strip()


def main() -> int:
    ap = argparse.ArgumentParser(description=__doc__,
                                 formatter_class=argparse.RawDescriptionHelpFormatter)
    ap.add_argument("--lang", default="en")
    ap.add_argument("--out", default=None, help="output dir (default demo/_cap/gsys_<lang>/)")
    ap.add_argument("--only", default=None, help="comma list of race ids to (re)render, e.g. gsys01,gsys02")
    ap.add_argument("--force", action="store_true", help="re-render even if the output already exists")
    ap.add_argument("--res", default="1920x1080")
    ap.add_argument("--fps", type=int, default=30)
    args, passthrough = ap.parse_known_args()

    out_dir = Path(args.out) if args.out else ROOT / "demo" / "_cap" / f"gsys_{args.lang}"
    out_dir.mkdir(parents=True, exist_ok=True)
    want = {x.strip() for x in args.only.split(",")} if args.only else None
    picks = [(rid, title) for rid, title in races() if want is None or rid in want]

    print(f"rendering {len(picks)} race(s) in '{args.lang}' -> {out_dir}")
    done, skipped, failed = [], [], []
    for i, (rid, title) in enumerate(picks, 1):
        out = out_dir / f"{_safe(title)}.mp4"        # filename = the race (date + local start time)
        if out.exists() and not args.force:
            print(f"[{i}/{len(picks)}] {rid}: exists, skipping ({out.name})")
            skipped.append(rid)
            continue
        print(f"\n[{i}/{len(picks)}] {rid}: recording -> {out.name}")
        t0 = time.time()
        rc = subprocess.run([sys.executable, str(HERE / "record_demo.py"),
                             "--race", rid, "--lang", args.lang,
                             "--res", args.res, "--fps", str(args.fps),
                             "--out", str(out), *passthrough]).returncode
        if rc == 0 and out.exists():
            print(f"      done in {time.time() - t0:.0f}s")
            done.append(rid)
        else:
            print(f"      FAILED (rc={rc}) — continuing")
            failed.append(rid)

    print(f"\nrendered {len(done)}  skipped {len(skipped)}  failed {len(failed)}")
    if failed:
        print("  failed:", ", ".join(failed))
    return 1 if failed else 0


if __name__ == "__main__":
    sys.exit(main())
