"""
Test Audit Levels: S (Stop) / A (Abort) / B (Block) / C (Count)
TDD - Tests written BEFORE implementation.

Per MIGRATION_AUDIT.md:
- S: Stop - Immediate halt
- A: Abort - Cancel current operation
- B: Block - Block future operations
- C: Count - Count only (no blocking)
"""

import pytest


class TestAuditLevels:
    """Test Audit System with S/A/B/C levels."""

    def test_audit_level_enum_exists(self):
        """AuditLevel enum should exist with S/A/B/C variants."""
        from theus_core import AuditLevel

        assert hasattr(AuditLevel, "Stop")
        assert hasattr(AuditLevel, "Abort")
        assert hasattr(AuditLevel, "Block")
        assert hasattr(AuditLevel, "Count")

    def test_audit_recipe_with_level(self):
        """AuditRecipe should accept level parameter."""
        from theus_core import AuditRecipe, AuditLevel

        recipe = AuditRecipe(
            level=AuditLevel.Block,
            threshold_max=5,
            threshold_min=2,  # Warning threshold
            reset_on_success=True,
        )

        assert recipe.level == AuditLevel.Block
        assert recipe.threshold_max == 5
        assert recipe.threshold_min == 2

    def test_audit_system_stop_level(self):
        """S-Level: Immediate halt on first failure."""
        from theus_core import AuditSystem, AuditRecipe, AuditLevel

        recipe = AuditRecipe(level=AuditLevel.Stop, threshold_max=1)
        audit = AuditSystem(recipe)

        # First fail should raise immediately
        with pytest.raises(Exception, match="Stop"):
            audit.log_fail("test_key")

    def test_audit_system_abort_level(self):
        """A-Level: Cancel current operation but allow retry."""
        from theus_core import AuditSystem, AuditRecipe, AuditLevel, AuditAbortError

        recipe = AuditRecipe(level=AuditLevel.Abort, threshold_max=3)
        audit = AuditSystem(recipe)

        # Should abort on fail, different error type than Block
        with pytest.raises(AuditAbortError):
            audit.log_fail("test_key")

    def test_audit_system_block_level(self):
        """B-Level: Block after threshold exceeded."""
        from theus_core import AuditSystem, AuditRecipe, AuditLevel, AuditBlockError

        recipe = AuditRecipe(level=AuditLevel.Block, threshold_max=3)
        audit = AuditSystem(recipe)

        # Should not block until threshold
        audit.log_fail("test_key")  # count=1
        audit.log_fail("test_key")  # count=2
        audit.log_fail("test_key")  # count=3

        # Fourth should block
        with pytest.raises(AuditBlockError):
            audit.log_fail("test_key")

    def test_audit_system_count_level(self):
        """C-Level: Count only, never block."""
        from theus_core import AuditSystem, AuditRecipe, AuditLevel

        recipe = AuditRecipe(level=AuditLevel.Count, threshold_max=3)
        audit = AuditSystem(recipe)

        # Should never raise, just count
        for _ in range(10):
            audit.log_fail("test_key")  # No exception

        assert audit.get_count("test_key") == 10

    # @pytest.mark.skip(reason="AuditWarning requires Python warnings integration - deferred to v3.1")
    def test_audit_dual_threshold_warning(self):
        """Dual-Threshold: Warning at min, Block at max."""
        from theus_core import AuditSystem, AuditRecipe, AuditLevel, AuditWarning

        recipe = AuditRecipe(
            level=AuditLevel.Block,
            threshold_min=2,  # Warning
            threshold_max=5,  # Block
        )
        audit = AuditSystem(recipe)

        audit.log_fail("test_key")  # count=1, no warning
        audit.log_fail("test_key")  # count=2, warning threshold

        # Third fail should trigger warning (not block)
        with pytest.warns(AuditWarning):
            audit.log_fail("test_key")  # count=3

        # Continue until block
        audit.log_fail("test_key")  # count=4
        audit.log_fail("test_key")  # count=5

        with pytest.raises(Exception):
            audit.log_fail("test_key")  # count=6, now blocked

    def test_reset_on_success_false_flaky_detector(self):
        """Flaky Detector: Errors accumulate despite successes (reset_on_success=False)."""
        from theus_core import AuditSystem, AuditRecipe, AuditLevel, AuditBlockError

        recipe = AuditRecipe(
            level=AuditLevel.Block,
            threshold_max=3,
            reset_on_success=False  # Flaky Detector Mode
        )
        audit = AuditSystem(recipe)

        # Interleave failures and successes
        audit.log_fail("flaky_key")      # count=1
        audit.log_success("flaky_key")   # count STILL 1 (no reset)
        assert audit.get_count("flaky_key") == 1

        audit.log_fail("flaky_key")      # count=2
        audit.log_success("flaky_key")   # count STILL 2
        assert audit.get_count("flaky_key") == 2

        audit.log_fail("flaky_key")      # count=3
        audit.log_success("flaky_key")   # count STILL 3
        assert audit.get_count("flaky_key") == 3

        # 4th fail should block even though we had successes in between
        with pytest.raises(AuditBlockError):
            audit.log_fail("flaky_key")  # count=4 → BLOCK
