"""W21B-wave-2: background_prompt v9 opt-in contract guards."""
from __future__ import annotations

import pytest

from app.modules.pipeline.background_prompt import (
    PROMPT_VERSION_MAP,
    BackgroundPromptOverlayError,
    build_bg_user_prompt,
    resolve_prompt_version,
)
from app.modules.prompt_loader import load_prompt, load_schema


_V9_PACK_NAME = "9.202605290248"


def _bg_spec(surface_role: str = "exterior_plate"):
    return {
        "bg_id": "L04B01",
        "loc_id": "L04",
        "sub_location": "roof exterior",
        "state_label_raw": "day quiet exterior plate",
        "surface_role": surface_role,
        "applies_to_shots": ["S4_Shot1"],
    }


_OVERLAY = {
    "bg_id": "L04B01",
    "fp_id": "fp_roof",
    "use_numbered_elements": [1],
    "ignore_numbered_elements": [2],
    "base_markers_to_reference": [
        {
            "number": 1,
            "label": "roof parapet",
            "category": "fixture",
            "position_hint": "north edge",
            "base_layer_decision": "base_structural_unit",
        }
    ],
    "transient_markers_to_describe": [
        {
            "number": 2,
            "label": "news broadcast on TV",
            "category": "screen_content",
            "position_hint": "center screen",
            "base_layer_decision": "state_overlay_plot_cue",
        }
    ],
    "ignored_state_overlay_markers": [],
    "target_unit_marker_numbers": [1],
    "dominant_target_unit_marker_number": 1,
    "clean_background_expected": False,
    "diagnostics": [],
}


def test_v9_selector_resolves_pack_name():
    assert PROMPT_VERSION_MAP["9"] == _V9_PACK_NAME
    assert resolve_prompt_version("9") == _V9_PACK_NAME


def test_v9_config_literal_accepts_nine(monkeypatch):
    monkeypatch.delenv("BACKGROUND_PROMPT_VERSION", raising=False)
    from app.core.config import Settings

    assert Settings(_env_file=None, background_prompt_version="9").background_prompt_version == "9"


def test_v10_config_literal_accepts_ten(monkeypatch):
    monkeypatch.delenv("BACKGROUND_PROMPT_VERSION", raising=False)
    from app.core.config import Settings

    assert Settings(_env_file=None, background_prompt_version="10").background_prompt_version == "10"


def test_v9_pack_loads_and_adds_screen_guard():
    system = load_prompt("background_prompt", "system", version=_V9_PACK_NAME)
    user_template = load_prompt(
        "background_prompt", "user_template", version=_V9_PACK_NAME,
    )
    schema = load_schema("background_prompt", "schema", version=_V9_PACK_NAME)

    assert "story-content surfaces" in system
    assert "non-semantic" in system
    assert "{surface_role}" in user_template
    assert "{transient_markers_block}" not in user_template
    assert set(schema["required"]) == {
        "bg_id",
        "t2i_prompt",
        "ref_guide",
        "shot_guides",
        "objects_owned_by_background",
    }


def test_v9_build_includes_surface_role_but_withholds_transient_screen_label():
    rendered = build_bg_user_prompt(
        bg_spec=_bg_spec("exterior_plate"),
        floor_plan_path="",
        prior_bg_paths=[],
        scene_segments=[
            {
                "scene_index": 4,
                "heading": "probe",
                "text": "VERBATIM_SCENE_PROBE_LINE",
            }
        ],
        visual_world_rules="regional world rule body",
        source_language="ko",
        prompt_version="9",
        overlay_payload=_OVERLAY,
    )

    assert "surface_role: exterior_plate" in rendered
    assert "1. roof parapet [fixture] — north edge" in rendered
    assert "news broadcast on TV" not in rendered
    assert "center screen" not in rendered
    assert "VERBATIM_SCENE_PROBE_LINE" not in rendered


def test_v9_fp_less_exterior_allows_missing_overlay():
    rendered = build_bg_user_prompt(
        bg_spec=_bg_spec("exterior_plate"),
        floor_plan_path="",
        prior_bg_paths=[],
        scene_segments=[],
        visual_world_rules="regional exterior rule",
        source_language="ko",
        prompt_version="9",
        overlay_payload=None,
    )

    assert "surface_role: exterior_plate" in rendered
    assert "fp-less surface plate" in rendered
    assert "regional exterior rule" in rendered


def test_v9_interior_missing_overlay_still_raises():
    with pytest.raises(BackgroundPromptOverlayError):
        build_bg_user_prompt(
            bg_spec=_bg_spec("interior_room"),
            floor_plan_path="",
            prior_bg_paths=[],
            scene_segments=[],
            visual_world_rules="",
            source_language="ko",
            prompt_version="9",
            overlay_payload=None,
        )


def test_v9_fp_backed_non_interior_missing_overlay_still_raises():
    with pytest.raises(BackgroundPromptOverlayError):
        build_bg_user_prompt(
            bg_spec=_bg_spec("transition_zone"),
            floor_plan_path="/tmp/fp_transition.png",
            prior_bg_paths=[],
            scene_segments=[],
            visual_world_rules="",
            source_language="ko",
            prompt_version="9",
            overlay_payload=None,
        )
