"""scene_detail active pack reproduction surface enumeration drift gate.

Area C migration (2026-05-12). active scene_detail prompt pack 안
reproduction surface 의 9 노운 키워드의 enumeration 형태 회귀 차단.

자연 문장 단독 등장은 false-positive 회피 위해 허용. enumeration 형태만 차단:
- 괄호 내 4+ comma/slash/middot 구분 noun (`(A, B, C, D)`)
- 4+ consecutive bullet lines, 각 bullet 가 noun 단독
"""
import pathlib
import re


REPRODUCTION_NOUNS = frozenset({
    "photograph", "poster", "painting", "portrait",
    "monitor", "TV", "mirror", "projection",
    "window reflection",
    "사진", "포스터", "그림", "초상화",
    "모니터", "거울", "투영", "창문 반사",
})

PROMPT_ROOT = (
    pathlib.Path(__file__).parent.parent.parent.parent
    / "prompts" / "_base" / "scene_detail"
)


def _resolve_active_pack() -> pathlib.Path:
    """numeric prefix 기준 가장 큰 directory 가 active pack."""
    def _ver(p: pathlib.Path) -> int:
        head = p.name.split(".")[0]
        return int(head) if head.isdigit() else -1

    dirs = [p for p in PROMPT_ROOT.iterdir() if p.is_dir()]
    assert dirs, f"no scene_detail packs found at {PROMPT_ROOT}"
    return max(dirs, key=_ver)


def _count_enumeration_violations(text: str) -> list[tuple[int, str]]:
    """enumeration 형태 reproduction noun 사용 detect.

    Returns list of (line_number, line_excerpt) tuples for each violation.
    """
    violations: list[tuple[int, str]] = []
    lines = text.splitlines()
    noun_set_lower = {n.lower() for n in REPRODUCTION_NOUNS}

    # (1) 괄호 enumeration: ( ... ) or [ ... ] 안 4+ 토큰 + 3+ noun hit.
    for idx, line in enumerate(lines, start=1):
        for m in re.finditer(r"[\(\[]([^\)\]]{1,200})[\)\]]", line):
            inside = m.group(1)
            parts = re.split(r"[,/·ㆍ]\s*", inside)
            noun_hits = sum(
                1 for p in parts if p.strip().lower() in noun_set_lower
            )
            if len(parts) >= 4 and noun_hits >= 3:
                violations.append((idx, line.strip()[:120]))

    # (2) bullet enumeration: 4+ consecutive `- noun` or `* noun` lines
    # where each bullet content is a noun-only line.
    bullet_run: list[tuple[int, str]] = []
    for idx, line in enumerate(lines, start=1):
        stripped = line.strip()
        if stripped.startswith("- ") or stripped.startswith("* "):
            content = stripped[2:].strip().lower()
            if content in noun_set_lower:
                bullet_run.append((idx, line.strip()[:120]))
            else:
                if len(bullet_run) >= 4:
                    violations.extend(bullet_run)
                bullet_run = []
        else:
            if len(bullet_run) >= 4:
                violations.extend(bullet_run)
            bullet_run = []
    if len(bullet_run) >= 4:
        violations.extend(bullet_run)

    return violations


def test_active_pack_system_md_no_enumeration():
    active = _resolve_active_pack()
    system_md = active / "system.md"
    assert system_md.exists(), f"{system_md} missing"
    violations = _count_enumeration_violations(
        system_md.read_text(encoding="utf-8")
    )
    assert not violations, (
        f"scene_detail/{active.name}/system.md 안 reproduction noun "
        f"enumeration 잔존 ({len(violations)} hit): {violations[:5]}"
    )


def test_active_pack_detail_schema_no_enumeration():
    active = _resolve_active_pack()
    schema = active / "detail_schema.json"
    assert schema.exists(), f"{schema} missing"
    violations = _count_enumeration_violations(
        schema.read_text(encoding="utf-8")
    )
    assert not violations, (
        f"scene_detail/{active.name}/detail_schema.json 안 reproduction noun "
        f"enumeration 잔존 ({len(violations)} hit): {violations[:5]}"
    )


def test_natural_sentence_allowed():
    """자연 문장 안 단독 등장 — false-positive 회피."""
    text = (
        "A photograph on the wall reflects ambient light, "
        "while the mirror behind subject shows partial view."
    )
    violations = _count_enumeration_violations(text)
    assert not violations, (
        f"자연 문장 false-positive: {violations}. "
        f"enumeration 형태만 차단해야 함."
    )


def test_self_test_paren_enumeration_caught():
    """gate 신뢰성 lock-in — 명백한 괄호 enumeration 은 catch."""
    text = (
        "Reproduction surfaces (photograph, poster, painting, portrait, monitor)"
    )
    violations = _count_enumeration_violations(text)
    assert violations, "gate 가 명백한 괄호 enumeration 미검출 = silent disarm"


def test_self_test_bullet_enumeration_caught():
    """gate 신뢰성 lock-in — bullet enumeration catch."""
    text = "\n".join([
        "Reproduction surfaces:",
        "- photograph",
        "- poster",
        "- painting",
        "- portrait",
        "- monitor",
    ])
    violations = _count_enumeration_violations(text)
    assert violations, "gate 가 bullet enumeration 미검출 = silent disarm"


def test_active_pack_is_v22_or_later():
    """active pack 이 v22 (Area C migration 직후) 이상."""
    active = _resolve_active_pack()
    version_str = active.name.split(".")[0]
    assert version_str.isdigit() and int(version_str) >= 22, (
        f"active pack = {active.name}, expected v22+ (Area C migration)."
    )
