# tests/test_wave2_proof.py
"""Tests for ProofStepVerifier (wave2 29.2)."""
from __future__ import annotations

import sys
from pathlib import Path
import pytest

ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT))

SAMPLE_SOLUTION = r"""
We solve the equation $x^2 - 5x + 6 = 0$.
Factoring: $(x-2)(x-3) = 0$, so $x = 2$ or $x = 3$.
The positive solution is $\boxed{3}$.
"""

SOLUTION_NO_BOX = "The answer is approximately 3.14. We cannot determine the exact form."

MULTI_BOX_SOLUTION = r"""
First, $a + b = \boxed{7}$. Then $a \cdot b = \boxed{12}$.
"""


def test_import():
    from llm_guard.verification.proof_step_verifier import ProofStepVerifier
    assert ProofStepVerifier is not None


def test_result_import():
    from llm_guard.verification.proof_step_verifier import ProofStepVerifier, ProofVerificationResult
    assert ProofVerificationResult is not None


def test_instantiates():
    from llm_guard.verification.proof_step_verifier import ProofStepVerifier
    v = ProofStepVerifier()
    assert v is not None


def test_extract_boxed_finds_answer():
    from llm_guard.verification.proof_step_verifier import ProofStepVerifier
    v = ProofStepVerifier()
    exprs = v.extract_boxed(SAMPLE_SOLUTION)
    assert len(exprs) >= 1
    assert "3" in exprs


def test_extract_boxed_empty_when_no_box():
    from llm_guard.verification.proof_step_verifier import ProofStepVerifier
    v = ProofStepVerifier()
    exprs = v.extract_boxed(SOLUTION_NO_BOX)
    assert isinstance(exprs, list)
    # May or may not find expressions; must not crash


def test_extract_boxed_multi():
    from llm_guard.verification.proof_step_verifier import ProofStepVerifier
    v = ProofStepVerifier()
    exprs = v.extract_boxed(MULTI_BOX_SOLUTION)
    assert len(exprs) >= 2


def test_parse_expression_integer():
    from llm_guard.verification.proof_step_verifier import ProofStepVerifier
    v = ProofStepVerifier()
    result = v.parse_expression("3")
    assert result is not None


def test_parse_expression_fraction():
    from llm_guard.verification.proof_step_verifier import ProofStepVerifier
    v = ProofStepVerifier()
    result = v.parse_expression(r"\frac{1}{2}")
    # May succeed or fail (LaTeX not natively parsed by sympy) — must not crash
    assert result is None or result is not None


def test_verify_returns_result():
    from llm_guard.verification.proof_step_verifier import ProofStepVerifier, ProofVerificationResult
    v = ProofStepVerifier()
    result = v.verify(SAMPLE_SOLUTION, "3")
    assert isinstance(result, ProofVerificationResult)
    assert hasattr(result, "coverage")
    assert hasattr(result, "risk")
    assert hasattr(result, "verified_steps")
    assert 0.0 <= result.coverage <= 1.0
    assert 0.0 <= result.risk <= 1.0


def test_verify_correct_answer_low_risk():
    from llm_guard.verification.proof_step_verifier import ProofStepVerifier
    v = ProofStepVerifier()
    result = v.verify(SAMPLE_SOLUTION, "3")
    # Correct answer in box → low risk
    assert result.risk < 0.7, f"Expected low risk for correct answer, got {result.risk}"


def test_verify_wrong_answer_higher_risk():
    from llm_guard.verification.proof_step_verifier import ProofStepVerifier
    v = ProofStepVerifier()
    result_correct = v.verify(SAMPLE_SOLUTION, "3")
    result_wrong = v.verify(SAMPLE_SOLUTION, "99")  # wrong answer
    # Wrong answer should have >= risk
    assert result_wrong.risk >= result_correct.risk
