"""Test that fix_registry actually matches realistic Validator output strings.

IMPORTANT: test strings deliberately do NOT contain the category prefix
(`[identity]`, `[wardrobe]`, `[lighting]`) because that prefix already
matches the OLD keyword lists trivially. The whole point of Task 12 is
to verify the EXPANDED keywords (`differs`, `shape`, `feature`, etc.)
match phrasing that has no category prefix. (Opus Finding 7, 2026-04-09 review.)
"""
from recoil.execution.feedback.fix_registry import match_fix
from recoil.execution.step_types import GateVerdict


def _verdict(reason, gate_name="gate_2a"):
    return GateVerdict(passed=False, gate_name=gate_name, reason=reason,
                       details={}, cost=0.0, retriable=True)


def test_identity_drift_matches_realistic_summary():
    """Realistic Validator strings WITHOUT category prefix should match
    the expanded keywords for identity_drift."""
    # These strings contain ONLY new-keyword vocabulary (differs, shape, feature, face, etc.)
    cases = [
        "Score 2 → soft_reject: Face shape differs from reference (NOTICEABLE)",
        "Score 3 → reject: Eye color appears different (CRITICAL)",
        "Score 2 → soft_reject: Nose shape doesn't match the hero (NOTICEABLE)",
        "Score 2 → soft_reject: Different facial features observed (NOTICEABLE)",
    ]
    for reason in cases:
        # Sanity check: NONE of these strings contain old-pattern keywords
        old_kws = ["drift", "inconsisten", "different face", "not matching"]
        # "different face" is excluded by our split on "different from"
        assert not any(kw in reason.lower() for kw in old_kws if kw != "different face"), \
            f"Test string accidentally contains old keyword: {reason}"
        fix = match_fix(_verdict(reason), attempt_number=1)
        assert fix is not None, f"No match for: {reason}"
        assert fix.strategy.value in ("ref_prune_and_anchor", "face_isolation")


def test_wardrobe_matches_realistic_summary():
    """Wardrobe strings without `wardrobe` category prefix."""
    cases = [
        "Score 2 → soft_reject: Shirt color is wrong (NOTICEABLE)",
        "Score 3 → reject: Wearing the wrong jacket (CRITICAL)",
        "Score 2 → soft_reject: Outfit doesn't match the spec (NOTICEABLE)",
    ]
    for reason in cases:
        # Sanity: no `wardrobe` literal
        assert "wardrobe" not in reason.lower(), f"Test string contains old keyword: {reason}"
        fix = match_fix(_verdict(reason), attempt_number=1)
        assert fix is not None, f"No match for: {reason}"
        assert "wardrobe" in fix.strategy.value.lower()


def test_lighting_matches_realistic_summary():
    """Lighting strings without `lighting` category prefix."""
    cases = [
        "Score 2 → soft_reject: Shadow direction appears wrong (NOTICEABLE)",
        "Score 2 → soft_reject: Highlight intensity is inconsistent (NOTICEABLE)",
    ]
    for reason in cases:
        # Sanity: no `lighting` literal
        assert "lighting" not in reason.lower(), f"Test string contains old keyword: {reason}"
        fix = match_fix(_verdict(reason, gate_name="gate_2b"), attempt_number=1)
        assert fix is not None, f"No match for: {reason}"
