"""EpisodeReferencePolicyStep — visible_shot_count 집계 + fail-fast 검증."""
import pytest

from app.core.errors import AppError
from app.core.steps.episode_reference_policy_step import (
    build_selected_map_or_raise,
    compute_visible_shot_count_from_checkpoints,
)


def test_visible_shot_count_over_selected_shots_only():
    shot_director_data = {"scenes": [
        {"scene_index": 1, "shots": [
            {"shot_index": 0, "visible_entity_ids": ["C01", "C08"]},
            {"shot_index": 1, "visible_entity_ids": ["C01"]},
            {"shot_index": 2, "visible_entity_ids": ["C01", "C99"]},
        ]},
    ]}
    selected = {1: {0, 1}}  # shot 2 미선택
    got = compute_visible_shot_count_from_checkpoints(
        shot_director_data, selected,
    )
    assert got["C01"] == 2
    assert got["C08"] == 1
    assert "C99" not in got


def test_visible_shot_count_composite_id_normalized_to_base():
    shot_director_data = {"scenes": [
        {"scene_index": 1, "shots": [
            {"shot_index": 0, "visible_entity_ids": ["C01O02"]},
        ]},
    ]}
    got = compute_visible_shot_count_from_checkpoints(
        shot_director_data, {1: {0}},
    )
    assert got.get("C01") == 1


def test_visible_shot_count_fails_when_selected_scene_missing():
    """shot_director scene 이 selected_map 에 없으면 AppError fail-fast
    (전체 shot fallback 금지 — Phase 0 와 동일 fail-closed)."""
    shot_director_data = {"scenes": [
        {"scene_index": 1, "shots": [
            {"shot_index": 0, "visible_entity_ids": ["C01"]}]},
        {"scene_index": 2, "shots": [
            {"shot_index": 0, "visible_entity_ids": ["C07"]}]},
    ]}
    with pytest.raises(AppError):
        compute_visible_shot_count_from_checkpoints(shot_director_data, {1: {0}})


def test_build_selected_map_fails_when_shot_selection_missing():
    """shot_selection checkpoint 부재/empty → AppError fail-fast."""
    with pytest.raises(AppError):
        build_selected_map_or_raise(None)
    with pytest.raises(AppError):
        build_selected_map_or_raise({"data": {"scenes": []}})


def test_build_selected_map_ok():
    got = build_selected_map_or_raise(
        {"data": {"scenes": [
            {"scene_index": 1, "selected_shot_indices": [0, 2]}]}})
    assert got == {1: {0, 2}}


def test_visible_shot_count_fails_when_selected_shot_missing():
    """selected shot index 가 shot_director.shots 에 실재하지 않으면 AppError
    fail-fast — visible_shot_count undercount 방지 (range review IMPORTANT 1)."""
    shot_director_data = {"scenes": [
        {"scene_index": 1, "shots": [
            {"shot_index": 0, "visible_entity_ids": ["C01"]}]},
    ]}
    with pytest.raises(AppError):
        compute_visible_shot_count_from_checkpoints(
            shot_director_data, {1: {0, 1}})
