"""Create detailed, deterministic video prompts and shot lists for all concepts."""

from __future__ import annotations

import csv
import json
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1] / "content" / "speech"
PLAN = json.loads((ROOT / "plan" / "content-plan.json").read_text(encoding="utf-8"))


def concept_path(c: dict) -> Path:
    return ROOT / "concepts" / Path(*c["category"].split(".")) / c["key"]


def beats(kind: str, purpose: str, depiction: str) -> list[dict]:
    if kind in {"action", "routine"}:
        actions = [
            ("0.0-1.5", "Establish actor, relevant objects and safe starting state; hold camera steady."),
            ("1.5-5.5", f"Show the complete target action clearly: {depiction}. Keep hands, face and affected object visible."),
            ("5.5-8.0", "Show the natural completion state and hold it long enough to understand the result."),
        ]
    elif kind in {"social_word", "emotion"}:
        actions = [
            ("0.0-2.0", "Establish the everyday situation and communication partner or meaningful cause."),
            ("2.0-5.5", f"Show the target intent or emotion with congruent facial, body and contextual cues: {depiction}."),
            ("5.5-8.0", "Show an appropriate partner response or stable emotional aftermath; preserve autonomy and natural expression."),
        ]
    elif kind in {"attribute", "preposition", "quantity"}:
        actions = [
            ("0.0-1.5", "Establish a controlled comparison set with matched objects and neutral composition."),
            ("1.5-5.5", f"Perform one slow placement, reveal or comparison that makes the target relation visible: {depiction}."),
            ("5.5-8.0", "Hold the completed contrast without labels, pointing overlays or positional answer cues."),
        ]
    elif kind in {"person", "location"}:
        actions = [
            ("0.0-2.0", "Begin with a wider contextual view that establishes role or place through ordinary activity."),
            ("2.0-5.5", f"Move or cut once to the key identifying evidence: {depiction}."),
            ("5.5-8.0", "Hold a natural stable view; avoid posed gestures, uniforms or symbols as the sole cue."),
        ]
    else:
        actions = [
            ("0.0-1.5", "Begin with the target partly occluded or resting naturally while its context is visible."),
            ("1.5-5.5", f"Reveal or interact with the target slowly and naturally: {depiction}. Keep the whole target readable."),
            ("5.5-8.0", "Hold the target fully visible for recognition and optional pause-frame use."),
        ]
    return [{"timecode": t, "story_beat": a} for t, a in actions]


def camera_plan(kind: str) -> list[dict]:
    focus = "face, hands and communication partner" if kind in {"social_word", "emotion", "person"} else "target, actor hands and relevant reference object"
    return [
        {"shot": 1, "framing": "wide or medium establishing shot", "movement": "locked-off or very slow push-in", "focus": "context plus target", "duration_seconds": 2},
        {"shot": 2, "framing": "medium close shot", "movement": "locked-off", "focus": focus, "duration_seconds": 4},
        {"shot": 3, "framing": "close result or response shot", "movement": "locked-off", "focus": "unambiguous completed meaning", "duration_seconds": 2},
    ]


def prompt(c: dict, video: dict, image: dict) -> str:
    return (
        f"Create one 8-second landscape 16:9 realistic clinical-educational video for the language-independent "
        f"concept '{c['name']}' (key {c['key']}), purpose {video['purpose']}. Use the approved reference image "
        f"{image['filename']} for semantic content and visual continuity, not for identity preservation. Scene: "
        f"{image['depiction']} in {image['context']}; participants: {image['people']}. Begin with a stable establishing "
        f"view, show one slow natural target action or reveal, then hold the completed meaning for at least two seconds. "
        f"Keep the target continuously visible, anatomically and physically plausible, safely framed and naturally lit. "
        f"Use at most one simple camera cut; no fast zoom, montage or dramatic acting. Language-neutral: no necessary speech "
        f"and no embedded writing. Preserve culturally respectful, disability-inclusive representation."
    )


NEGATIVE = [
    "no captions, labels, readable text, letters, numbers, logos, brands or watermark",
    "no jump cuts, time lapse, fast camera movement, flicker, strobe, looping discontinuity or motion smear",
    "no extra fingers, fused limbs, changing identity, changing clothing, morphing objects or disappearing props",
    "no unsafe, frightening, coercive, humiliating or medically distressing behavior",
    "no target hidden by hands, crop, foreground objects or shallow focus at the teaching moment",
    "no music as a meaning cue and no speech required to understand the concept",
]


updated = 0
for c in PLAN["concepts"]:
    base = concept_path(c)
    video_dir = base / "videos"
    briefs = json.loads((video_dir / "production-briefs.json").read_text(encoding="utf-8"))["briefs"]
    with (base / "images" / "assets.csv").open(encoding="utf-8", newline="") as stream:
        images = {row["purpose"]: row for row in csv.DictReader(stream)}
    refs = [images["identification"], images["meaning"], images["generalisation_probe"]]
    semantic = json.loads((base / "semantic-definition.json").read_text(encoding="utf-8"))
    videos = []
    for index, (brief, ref) in enumerate(zip(briefs, refs), 1):
        videos.append({
            "video_key": brief["video_key"],
            "purpose": brief["purpose"],
            "duration_seconds": 8,
            "reference_image": {"asset_key": ref["asset_key"], "filename": f"../images/{ref['filename']}", "usage": "semantic_and_composition_reference"},
            "narrative_intent": brief["brief"],
            "setup": {"setting": ref["context"], "depiction": ref["depiction"], "people": ref["people"], "continuity_lock": ["participant identity", "clothing", "target instance", "background layout", "lighting direction"]},
            "story_beats": beats(c["type"], brief["purpose"], ref["depiction"]),
            "shot_list": camera_plan(c["type"]),
            "generation_prompt": prompt(c, brief, ref),
            "negative_constraints": NEGATIVE,
            "audio_plan": {"production_audio": "quiet natural room tone only", "speech": "none required", "music": "none", "localized_voiceover": "optional separate approved track"},
            "accessibility": {"captions": "required if any speech is added", "audio_description": "author from narrative_intent after picture lock", "photosensitivity": "no flashes or rapid cuts", "silent_comprehension": "required"},
            "safety_and_semantics": semantic["safety_and_cultural_notes"],
            "review_gates": ["technical continuity", "target clarity", "SLP review", "accessibility review", "cultural review", "rights and releases"],
            "status": "prompt_ready_review_required",
        })
    record = {"schema_version": 1, "concept_key": c["key"], "format": "landscape_16_9", "default_duration_seconds": 8, "videos": videos}
    out = video_dir / "video-generation-plan.json"
    text = json.dumps(record, ensure_ascii=False, indent=2) + "\n"
    if not out.exists() or out.read_text(encoding="utf-8") != text:
        out.write_text(text, encoding="utf-8"); updated += 1

    csv_path = video_dir / "videos-list.csv"
    header = ["video_key","filename","purpose","difficulty","setting","people","target_action","target_timecode","duration_seconds","language_scope","captions_or_audio","source_or_creator","licence_or_release","checksum","status","review_notes"]
    rows = []
    for i, v in enumerate(videos, 1):
        rows.append([v["video_key"],f"{v['video_key']}.mp4",v["purpose"],i, v["setup"]["setting"],v["setup"]["people"],v["setup"]["depiction"],"00:00:01.500-00:00:05.500",8,"language_neutral_preferred","captions_if_speech; audio_description_review","TODO","release_required","","prompt_ready","See video-generation-plan.json; SLP accessibility cultural rights and technical review required"])
    with csv_path.open("w", encoding="utf-8", newline="") as stream:
        writer = csv.writer(stream); writer.writerow(header); writer.writerows(rows)

print(f"Video generation plans ready: {len(PLAN['concepts'])} concepts / {len(PLAN['concepts']) * 3} videos; {updated} plan files updated")
