"""Phase 2 tests for the gpt-image-2 photoreal storyboard finish prompt."""

from __future__ import annotations

import inspect
import re
import sys
from pathlib import Path

_REPO_ROOT = Path(__file__).resolve().parents[4]
if str(_REPO_ROOT) not in sys.path:
    sys.path.insert(0, str(_REPO_ROOT))

from recoil.pipeline._lib import prompt_engine  # noqa: E402
from recoil.pipeline._lib.prompt_engine import get_builder  # noqa: E402


def _segments() -> list[dict]:
    return [
        {
            "setting": "Cryo pod platform",
            "intent": "Jade studies the frost-cracked pod seal",
        },
        {
            "setting": "Anchor cable gantry",
            "intent": "Wren signals Jade to hold position",
        },
        {
            "setting": "Cryo pod platform",
            "intent": "The pod warning light catches both faces",
        },
    ]


def _char_descs() -> dict[str, str]:
    return {
        "jade": "salvage pilot in a patched pressure jacket",
        "wren": "armored tactical partner with a compact helmet",
    }


def _ref_layout() -> dict:
    return {
        "identity_refs": {
            "jade": (1, 2),
            "wren": (3, 4),
        },
        "sublocation_refs": [
            {"slug": "cryo_pod_platform", "index": 5},
            {"slug": "anchor_cable_gantry", "index": 6},
        ],
        "prop_refs": [
            {"slug": "cryo_pod", "index": 7},
        ],
    }


def test_finish_builder_is_registered_with_signature_parity():
    pencil = get_builder("gpt-image-2", "storyboard")
    finish = get_builder("gpt-image-2", "storyboard_finish")

    assert pencil is prompt_engine.build_storyboard_strip_prompt
    assert finish is prompt_engine.build_gpt_image_2_storyboard_finish_prompt
    assert list(inspect.signature(finish).parameters) == [
        "segments",
        "slots",
        "char_descs",
        "ref_layout",
        "sublocation_locked",
        "grid",
        "scene_context",
        "carrier_facts",
    ]


def test_finish_prompt_contains_proven_photoreal_contract():
    prompt = prompt_engine.build_gpt_image_2_storyboard_finish_prompt(
        _segments(),
        4,
        _char_descs(),
        _ref_layout(),
        False,
        grid=(2, 2),
        scene_context="Jade and Wren have just reached the lower platform.",
    )

    assert (
        "Create a 3-panel storyboard as ONE single vertical image: a grid of "
        "2 columns x 2 rows, panels numbered 1-4 (draw panels 1-3; trailing "
        "cells left blank), each panel a 9:16 vertical film frame."
    ) in prompt
    assert (
        "PHOTOREALISTIC cinematic film frames — moody practical lighting, "
        "filmic color, production-plate quality. No sketch lines, no illustration."
    ) in prompt
    assert prompt_engine.STORYBOARD_FINISH_COMPOSITION_REF in prompt
    assert (
        "Do not write text on the image. No subtitles. No captions. "
        "No panel numbers beyond small corner indices."
    ) in prompt


def test_finish_prompt_renders_reference_descriptions_in_attachment_order():
    prompt = prompt_engine.build_gpt_image_2_storyboard_finish_prompt(
        _segments(),
        4,
        _char_descs(),
        _ref_layout(),
        False,
        grid=(2, 2),
    )

    reference_block = prompt.split("REFERENCE MAPPING:\n", 1)[1].split("\n\n", 1)[0]
    expected_order = [
        prompt_engine.STORYBOARD_FINISH_COMPOSITION_REF,
        "@Image1-@Image2 are identity references for jade",
        "@Image3-@Image4 are identity references for wren",
        "@Image5 is the cryo_pod_platform sublocation geography reference.",
        "@Image6 is the anchor_cable_gantry sublocation geography reference.",
        "@Image7 is the cryo_pod prop identity reference.",
    ]
    positions = [reference_block.index(text) for text in expected_order]

    assert positions == sorted(positions)


def test_finish_prompt_beat_count_matches_segments():
    prompt = prompt_engine.build_gpt_image_2_storyboard_finish_prompt(
        _segments(),
        4,
        _char_descs(),
        _ref_layout(),
        False,
        grid=(2, 2),
    )
    story_beats = prompt.split("STORY BEATS:\n", 1)[1].split(
        "\n\n" + prompt_engine.STORYBOARD_FINISH_NO_TEXT_FOOTER,
        1,
    )[0]

    assert len(re.findall(r"(?m)^\d+\.$", story_beats)) == len(_segments())
    for segment in _segments():
        assert segment["setting"] in story_beats
        assert segment["intent"] in story_beats


def test_registered_pencil_builder_output_is_byte_stable():
    expected = (
        "Create a storyboard as ONE single image: a grid of 2 columns x 2 rows, "
        "panels numbered 1-4 reading left to right, top to bottom. Each panel is "
        "a 9:16 vertical film frame. Draw only the first 3 panel(s); leave the "
        "trailing 1 cell completely blank — white paper.\n\n"
        "STYLE:\n"
        f"{prompt_engine.STORYBOARD_STYLE_LOCK}\n\n"
        "REFERENCE MAPPING:\n"
        "Attached images 1-2 are identity references (front, profile) for jade — "
        "salvage pilot in a patched pressure jacket\n"
        "Attached images 3-4 are identity references (front, profile) for wren — "
        "armored tactical partner with a compact helmet\n\n"
        "SCENE CONTEXT (read-only — for causality, blocking, and continuity; "
        "do NOT draw panels for this text, only for the numbered beats):\n"
        "Jade and Wren have just reached the lower platform.\n\n"
        "AUTHORING:\n"
        f"{prompt_engine.STORYBOARD_DIRECTOR_PREAMBLE}\n"
        "Draw EXACTLY 3 panels, one per numbered beat below, in order. "
        "No invented panels, no filler.\n\n"
        "STORY BEATS:\n"
        "1.\n"
        "Setting: Cryo pod platform\n"
        "Jade studies the frost-cracked pod seal\n\n"
        "2.\n"
        "Setting: Anchor cable gantry\n"
        "Wren signals Jade to hold position\n\n"
        "3.\n"
        "Setting: Cryo pod platform\n"
        "The pod warning light catches both faces"
    )

    prompt = get_builder("gpt-image-2", "storyboard")(
        _segments(),
        4,
        _char_descs(),
        {"identity_refs": {"jade": (1, 2), "wren": (3, 4)}},
        False,
        grid=(2, 2),
        scene_context="Jade and Wren have just reached the lower platform.",
    )

    assert prompt == expected
