"""Tests for FailureMode enum — verifies all 16 values exist after Phase 3 additions."""


def test_failure_mode_has_23_values():
    """10 original + 6 Phase 3 + 7 follow-on additions = 23 total."""
    from recoil.pipeline._lib.critics import FailureMode

    assert len(FailureMode) == 23


def test_original_10_values_present():
    """All original Phase 2.5 values must still exist (backward compat)."""
    from recoil.pipeline._lib.critics import FailureMode

    originals = [
        "none",
        "anatomy_face_merge",
        "anatomy_limb_miscount",
        "identity_drift",
        "background_contamination",
        "wardrobe_mismatch",
        "lighting_mismatch",
        "grid_influence",
        "safety_softened",
        "unknown",
    ]
    for val in originals:
        assert val in [m.value for m in FailureMode], f"Missing original value: {val}"


def test_phase3_6_new_values_present():
    """6 new Phase 3 values (NOT 7 — no BUDGET_EXCEEDED)."""
    from recoil.pipeline._lib.critics import FailureMode

    new_values = [
        "motion_failure",
        "end_frame_drift",
        "content_filter_hard_block",
        "ref_bleed",
        "audio_sync_drift",
        "coverage_geometry_broken",
    ]
    for val in new_values:
        assert val in [m.value for m in FailureMode], f"Missing Phase 3 value: {val}"


def test_budget_exceeded_not_in_failure_mode():
    """BUDGET_EXCEEDED must NOT be in FailureMode — it's a budget gate signal, not a critic failure."""
    from recoil.pipeline._lib.critics import FailureMode

    assert "budget_exceeded" not in [m.value for m in FailureMode]


def test_failure_mode_values_are_stable_strings():
    """All FailureMode values serialize to lowercase snake_case strings (ops.log contract)."""
    from recoil.pipeline._lib.critics import FailureMode

    for member in FailureMode:
        assert isinstance(member.value, str)
        assert member.value == member.value.lower()
        assert " " not in member.value
