"""tests/test_verification_proof_step_verifier.py — Unit tests for ProofStepVerifier."""
import pytest

pytestmark = pytest.mark.unit


class TestImport:
    def test_import_verifier(self):
        from llm_guard.verification.proof_step_verifier import ProofStepVerifier
        assert ProofStepVerifier is not None

    def test_import_result(self):
        from llm_guard.verification.proof_step_verifier import ProofVerificationResult
        assert ProofVerificationResult is not None


class TestInstantiation:
    def test_default_construction(self):
        from llm_guard.verification.proof_step_verifier import ProofStepVerifier
        v = ProofStepVerifier()
        assert v.use_z3 is True

    def test_no_z3(self):
        from llm_guard.verification.proof_step_verifier import ProofStepVerifier
        v = ProofStepVerifier(use_z3=False)
        assert not v._z3_available


class TestExtractBoxed:
    def test_simple_boxed(self):
        from llm_guard.verification.proof_step_verifier import ProofStepVerifier
        v = ProofStepVerifier(use_z3=False)
        result = v.extract_boxed(r"The answer is \boxed{42}.")
        assert result == ["42"]

    def test_multiple_boxed(self):
        from llm_guard.verification.proof_step_verifier import ProofStepVerifier
        v = ProofStepVerifier(use_z3=False)
        result = v.extract_boxed(r"\boxed{3} and \boxed{7}")
        assert len(result) == 2

    def test_no_boxed(self):
        from llm_guard.verification.proof_step_verifier import ProofStepVerifier
        v = ProofStepVerifier(use_z3=False)
        result = v.extract_boxed("No boxed expression here.")
        assert result == []

    def test_nested_braces(self):
        from llm_guard.verification.proof_step_verifier import ProofStepVerifier
        v = ProofStepVerifier(use_z3=False)
        result = v.extract_boxed(r"\boxed{\frac{1}{2}}")
        assert len(result) == 1


class TestParseExpression:
    def test_integer(self):
        from llm_guard.verification.proof_step_verifier import ProofStepVerifier
        v = ProofStepVerifier(use_z3=False)
        expr = v.parse_expression("42")
        assert expr is not None

    def test_fraction_latex(self):
        from llm_guard.verification.proof_step_verifier import ProofStepVerifier
        v = ProofStepVerifier(use_z3=False)
        expr = v.parse_expression(r"\frac{1}{2}")
        assert expr is not None

    def test_invalid_expression(self):
        from llm_guard.verification.proof_step_verifier import ProofStepVerifier
        v = ProofStepVerifier(use_z3=False)
        expr = v.parse_expression("not math !!!")
        # Should return None or at least not raise
        # Some expressions may parse to symbols; that's OK


class TestVerify:
    def test_no_boxed_returns_unverifiable(self):
        from llm_guard.verification.proof_step_verifier import ProofStepVerifier
        v = ProofStepVerifier(use_z3=False)
        result = v.verify("The solution is x = 5.", "5")
        assert result.coverage == 0.0
        assert result.risk == 0.5
        assert not result.parse_success

    def test_correct_numeric_answer(self):
        from llm_guard.verification.proof_step_verifier import ProofStepVerifier
        v = ProofStepVerifier(use_z3=False)
        result = v.verify(r"Therefore \boxed{42}.", "42")
        assert result.parse_success
        assert result.risk == pytest.approx(0.1, abs=0.05)

    def test_wrong_numeric_answer(self):
        from llm_guard.verification.proof_step_verifier import ProofStepVerifier
        v = ProofStepVerifier(use_z3=False)
        result = v.verify(r"Therefore \boxed{42}.", "99")
        assert result.parse_success
        assert result.risk == pytest.approx(0.9, abs=0.05)

    def test_coverage_field(self):
        from llm_guard.verification.proof_step_verifier import ProofStepVerifier
        v = ProofStepVerifier(use_z3=False)
        result = v.verify(r"\boxed{7}", "7")
        assert result.coverage == 1.0

    def test_verified_steps_counted(self):
        from llm_guard.verification.proof_step_verifier import ProofStepVerifier
        v = ProofStepVerifier(use_z3=False)
        result = v.verify(r"\boxed{3} step one, \boxed{7} final.", "7")
        assert result.verified_steps >= 1
