"""Unit tests for _extract_key_bg_elements_or_raise helper (Area C migration).

helper 가 staging / shot_info 의 4 시나리오를 fail-fast 정합으로 처리하는지
검증. Gate 4 (no silent fallback) 정합 — 모든 contract 위반은 AppError raise.
"""
import pytest

from app.core.errors import AppError
from app.core.steps.render_prompt_card import _extract_key_bg_elements_or_raise


def test_staging_not_applicable_returns_empty_list():
    """shot_info.staging_not_applicable=True → []."""
    result = _extract_key_bg_elements_or_raise(
        staging=None,
        shot_info={"staging_not_applicable": True},
    )
    assert result == []


def test_staging_none_without_flag_raises():
    """staging=None + staging_not_applicable 미설정 → AppError(staging_required)."""
    with pytest.raises(AppError) as exc_info:
        _extract_key_bg_elements_or_raise(staging=None, shot_info={})
    assert exc_info.value.code == "render_prompt_card.staging_required"


def test_staging_with_empty_key_bg_elements_returns_empty():
    """staging.key_bg_elements=[] → [] (정상 absence)."""
    result = _extract_key_bg_elements_or_raise(
        staging={"key_bg_elements": []},
        shot_info={},
    )
    assert result == []


def test_staging_with_populated_key_bg_elements_passes_through():
    """staging.key_bg_elements=[{...}] → list 그대로."""
    element = {"element": "photograph on the wall",
               "directionality_class": "content_surface",
               "orientation": "front face visible"}
    result = _extract_key_bg_elements_or_raise(
        staging={"key_bg_elements": [element]},
        shot_info={},
    )
    assert result == [element]


def test_staging_with_non_list_key_bg_elements_raises():
    """staging.key_bg_elements 가 list 아님 → AppError(invalid)."""
    with pytest.raises(AppError) as exc_info:
        _extract_key_bg_elements_or_raise(
            staging={"key_bg_elements": "not-a-list"},
            shot_info={},
        )
    assert exc_info.value.code == "render_prompt_card.staging_key_bg_elements_invalid"


def test_staging_empty_dict_raises_invalid():
    """staging={} (no key_bg_elements key) → AppError(invalid).

    staging.get('key_bg_elements') 가 None → isinstance(None, list)==False →
    같은 invalid AppError. missing-key 와 wrong-type 모두 fail-fast 등가.
    """
    with pytest.raises(AppError) as exc_info:
        _extract_key_bg_elements_or_raise(staging={}, shot_info={})
    assert exc_info.value.code == "render_prompt_card.staging_key_bg_elements_invalid"


def test_render_prompt_card_no_phantom_phrase_closed_list():
    """Area #5 v1: close framing constraints + non-close owned constraints 안
    closed-list phantom phrase literal 0 (W3 Task 3.6).

    classifier 폐기 + sidecar SOT 후, render_prompt_card 가 emit 하는 constraint
    문자열에서 legacy closed-list literal 모두 폐기. principle-only.
    """
    import inspect
    from app.core.steps import render_prompt_card
    src = inspect.getsource(render_prompt_card)
    forbidden = [
        "the existing X",
        "use the X from the reference",
        "matching the reference camera",
        "the door from the reference",
        "preserving the same room perspective",
        "maintaining the reference's framing",
    ]
    for lit in forbidden:
        assert lit not in src, (
            f"closed-list literal {lit!r} present in render_prompt_card.py — "
            f"Area #5 W3 Task 3.6 wording cleanup violated"
        )
