"""episode_reference_policy manifest 계산 + text_only 추출."""
from app.core.episode_reference_policy import (
    compute_episode_reference_policy,
    extract_text_only_subjects,
)


def test_character_two_visible_shots_is_reference_required():
    manifest = compute_episode_reference_policy(
        visible_shot_count={"C01": 3, "C08": 1},
        entity_types={"C01": "character", "C08": "character"},
        variant_pole_short_ids=set(),
    )
    assert manifest["policy"]["C01"]["mode"] == "reference_required"
    assert manifest["policy"]["C08"]["mode"] == "text_only"


def test_variant_pole_protected_even_with_one_shot():
    manifest = compute_episode_reference_policy(
        visible_shot_count={"C12": 1},
        entity_types={"C12": "character"},
        variant_pole_short_ids={"C12"},
    )
    assert manifest["policy"]["C12"]["mode"] == "reference_required"
    assert "variant" in manifest["policy"]["C12"]["reason"]


def test_nonhuman_uses_same_rule_as_character():
    manifest = compute_episode_reference_policy(
        visible_shot_count={"C09": 2},
        entity_types={"C09": "character"},
        variant_pole_short_ids=set(),
    )
    assert manifest["policy"]["C09"]["mode"] == "reference_required"


def test_prop_mode_is_reference_candidate_not_required():
    """prop 은 provisional — mode 가 reference_candidate (생성 확정 아님)."""
    manifest = compute_episode_reference_policy(
        visible_shot_count={"P10": 2, "P11": 1},
        entity_types={"P10": "prop", "P11": "prop"},
        variant_pole_short_ids=set(),
    )
    assert manifest["policy"]["P10"]["mode"] == "reference_candidate"
    assert manifest["policy"]["P10"]["provisional"] is True
    assert manifest["policy"]["P11"]["mode"] == "text_only"


def test_extract_text_only_subjects_chars_only():
    """overlay 는 text_only character subject 만 추출. prop 제외."""
    manifest = compute_episode_reference_policy(
        visible_shot_count={"C08": 1, "P11": 1, "C01": 3},
        entity_types={"C08": "character", "P11": "prop", "C01": "character"},
        variant_pole_short_ids=set(),
    )
    text_only = extract_text_only_subjects(manifest)
    assert set(text_only) == {"C08"}
    assert isinstance(text_only["C08"], str)


def test_extract_handles_none_manifest():
    assert extract_text_only_subjects(None) == {}
    assert extract_text_only_subjects({}) == {}
