"""운영자 선언 무콘티 예외 — 기본값이 no-op 인가 (2026-07-30).

콘티가 끝내 실패한 샷을 BGFIRST 정책 대상 밖으로 빼는 운영자 스위치다.
위험한 종류의 스위치라(잘못 켜지면 "legacy 무음 하강 금지" 계약이 뚫린다)
**기본값이 빈 집합이고 그 빈 집합은 어떤 샷도 해제하지 않는다**는 것을
유닛으로 고정한다.

게이트 자체는 ``bgfirst_on and not _op_no_conti and (...)`` 이므로,
``_op_no_conti = tag in exempt`` 가 빈 집합에서 항상 거짓이면 표현식은
스위치 도입 전과 동치다.
"""
from __future__ import annotations

import pytest

from app.services.still_recipe_service import parse_no_conti_exempt_tags


@pytest.mark.parametrize("raw", ["", None, "   ", ",", ",,,", " , , "])
def test_blank_values_yield_empty_set(raw):
    """기본값·공백·구분자만 있는 값은 전부 빈 집합 = 완전 no-op."""
    assert parse_no_conti_exempt_tags(raw) == set()


def test_empty_set_exempts_no_shot():
    """빈 집합은 어떤 샷 태그도 해제하지 않는다(게이트 동치 증명의 축)."""
    exempt = parse_no_conti_exempt_tags("")
    for tag in ("S1sh7", "S104sh4", "", "*", "ALL"):
        assert (tag in exempt) is False


def test_settings_default_is_blank():
    """config 기본값이 빈 문자열 — env 를 건드리지 않은 실행은 기존과 동일."""
    from app.core.config import Settings

    field = Settings.model_fields["bgfirst_no_conti_exempt_tags"]
    assert field.default == ""


def test_declared_tags_are_parsed_and_trimmed():
    assert parse_no_conti_exempt_tags(" S1sh7 , S65sh4 ") == {
        "S1sh7", "S65sh4"}


def test_only_declared_tags_are_exempt():
    """선언되지 않은 샷은 그대로 정책 대상 — 부분 해제가 전면 해제가 되지 않는다."""
    exempt = parse_no_conti_exempt_tags("S1sh7,S65sh4")
    assert "S1sh7" in exempt
    assert "S1sh70" not in exempt      # prefix 로 번지지 않는다
    assert "s1sh7" not in exempt       # 대소문자 관대화 없음 (정확 일치)
    assert "S41sh2" not in exempt


def test_duplicates_collapse():
    assert parse_no_conti_exempt_tags("S1sh7,S1sh7") == {"S1sh7"}
