#!/usr/bin/env python3
"""promptc — compile shot spec + look into a ready-to-paste Flow/Veo prompt.

  tools/promptc.py shots/t2_s3_sharkrun.json                 # canonical look (cel80s)
  tools/promptc.py shots/t2_s3_sharkrun.json --look scannerdarkly
  tools/promptc.py shots/t2_s3_sharkrun.json --all           # every look, labeled
  tools/promptc.py --flux hero --look scannerdarkly          # ingredient still prompt
                                                             # (hero_face for that look)
Paths resolve relative to production/prompts/. Zero deps, stdlib only.
"""
import argparse
import json
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent / "production" / "prompts"
CANONICAL = "cel80s"


def load(p):
    return json.loads(Path(p).read_text())


def looks():
    return {f.stem: load(f) for f in (ROOT / "looks").glob("*.json")}


def compile_prompt(shot, look, blocks):
    parts = [look["style"]]
    parts += [blocks["characters"][c] for c in shot.get("characters", [])]
    if shot.get("set"):
        parts.append(blocks["sets"][shot["set"]])
    parts.append(shot["action"])
    if shot.get("camera"):
        parts.append(shot["camera"])
    neg = ", ".join(x for x in [blocks["negative_base"], look.get("negative", "")] if x)
    return ". ".join(p.strip().rstrip(".") for p in parts) + ". Avoid: " + neg + "."


def flux_ingredient(char, look, blocks):
    """Prompt for the character ingredient still in a given look (FLUX, free)."""
    return (f"{look['style']}. {blocks['characters'][char]}. close-up head and "
            f"shoulders portrait, three-quarter view, confident smirk, plain warm "
            f"gray background. Avoid: {blocks['negative_base']}, {look.get('negative','')}.")


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("shot", nargs="?", help="path to shot json (rel to production/prompts/)")
    ap.add_argument("--look", default=CANONICAL)
    ap.add_argument("--all", action="store_true", help="compile shot in every look")
    ap.add_argument("--flux", metavar="CHAR", help="emit FLUX ingredient-still prompt for a character")
    args = ap.parse_args()

    blocks = load(ROOT / "blocks.json")
    lks = looks()
    if args.look not in lks:
        sys.exit(f"unknown look {args.look!r}; have: {', '.join(sorted(lks))}")

    if args.flux:
        print(flux_ingredient(args.flux, lks[args.look], blocks))
        return

    if not args.shot:
        ap.error("need a shot json (or --flux CHAR)")
    p = Path(args.shot)
    shot = load(p if p.exists() else ROOT / args.shot)

    chosen = sorted(lks) if args.all else [args.look]
    for name in chosen:
        if args.all:
            print(f"\n=== {name} — {lks[name]['label']} ===")
        print(compile_prompt(shot, lks[name], blocks))


if __name__ == "__main__":
    main()
