#!/usr/bin/env python3
"""Dump key frames as stills BEFORE rendering — the cheap smoke test that
catches layout problems for a fraction of a render's cost.

Env: BRAND_PACK, BRAND_PROJECT.
Usage: python3 make_stills.py [16x9]
Writes <project>/smoke/<beat>-<t>.png + smoke/contact-sheet.png
"""
import importlib.util
import os
import sys

from PIL import Image, ImageDraw

PROJ = os.environ.get("BRAND_PROJECT", "")
if not PROJ:
    sys.exit("make_stills: set BRAND_PROJECT")
aspect = sys.argv[1] if len(sys.argv) > 1 else "16x9"

_here = os.path.dirname(os.path.abspath(__file__))
sys.argv = ["make_stills", aspect]
_spec = importlib.util.spec_from_file_location("_engine", os.path.join(_here, "engine.py"))
E = importlib.util.module_from_spec(_spec)
sys.modules[_spec.name] = E
_spec.loader.exec_module(E)

OUTDIR = os.path.join(PROJ, "smoke")
os.makedirs(OUTDIR, exist_ok=True)


def frame_at(T):
    """Delegates to the engine — never a second copy of the frame body. A
    duplicate here drifted from render() and put the outro wordmark band in the
    wrong place on the very contact sheet the operator approves."""
    return E.compose_frame(T)


shots = []
for i, st in enumerate(E.BEAT_STARTS):
    d = E.BEAT_DURS[i]
    for frac in (0.35, 0.72, 0.95):
        shots.append((f"B{i + 1:03d}", st + d * frac))
for frac in (0.45, 0.95):
    shots.append(("OUTRO", (E.TOTAL - E.OUTRO_D) + E.OUTRO_D * frac))

imgs = []
for name, T in shots:
    im = frame_at(T)
    im.save(os.path.join(OUTDIR, f"{name}-{T:05.1f}.png"))
    imgs.append(im)

cols = 4
tw = 480
th = int(tw * E.Hd / E.Wd)
rows = (len(imgs) + cols - 1) // cols
sheet = Image.new("RGB", (cols * tw, rows * th), (255, 255, 255))
for i, im in enumerate(imgs):
    sheet.paste(im.resize((tw, th), Image.LANCZOS), ((i % cols) * tw, (i // cols) * th))
sp = os.path.join(OUTDIR, "contact-sheet.png")
sheet.save(sp)
print("contact sheet:", sp, sheet.size, f"({len(imgs)} frames)")
