"""Tests for prover state models.

Generated by our friend.
"""

import pytest

from ax_prover.models.files import Location
from ax_prover.models.messages import (
    BuildFailedFeedback,
    BuildSuccessFeedback,
    ProposalMessage,
    ReviewApprovedFeedback,
    ReviewRejectedFeedback,
)
from ax_prover.models.proving import (
    ProverAgentState,
    ProverMetrics,
    ProverResult,
    ReviewDecision,
    TargetItem,
)


@pytest.fixture
def sample_location():
    return Location(name="thm", module_path="Test.Module", is_external=False)


@pytest.fixture
def sample_item(sample_location):
    return TargetItem(title="Test Theorem", location=sample_location)


@pytest.fixture
def proposal(sample_location):
    return ProposalMessage(reasoning="r", code="sorry", location=sample_location)


@pytest.fixture
def build_failed():
    return BuildFailedFeedback(error_output="error")


@pytest.fixture
def build_success():
    return BuildSuccessFeedback()


@pytest.fixture
def review_approved():
    return ReviewApprovedFeedback()


@pytest.fixture
def review_rejected():
    return ReviewRejectedFeedback(feedback="statement changed")


class TestProverAgentStateProperties:
    """Tests for ProverAgentState computed properties."""

    def test_iteration_count_empty(self, sample_item):
        """Empty messages gives iteration count 0."""
        state = ProverAgentState(item=sample_item)
        assert state.iteration_count == 0

    def test_iteration_count_with_proposals(self, sample_item, proposal, build_failed):
        """Counts ProposalMessage instances."""
        state = ProverAgentState(item=sample_item, messages=[proposal, build_failed, proposal])
        assert state.iteration_count == 2

    def test_last_proposal_returns_most_recent(self, sample_item, sample_location):
        """Returns the last ProposalMessage in the list."""
        p1 = ProposalMessage(reasoning="first", code="c1", location=sample_location)
        p2 = ProposalMessage(reasoning="second", code="c2", location=sample_location)
        state = ProverAgentState(item=sample_item, messages=[p1, p2])
        assert state.last_proposal.reasoning == "second"

    def test_last_proposal_none_when_empty(self, sample_item):
        """Returns None when no proposals exist."""
        state = ProverAgentState(item=sample_item)
        assert state.last_proposal is None

    def test_last_feedback_returns_most_recent(
        self, sample_item, proposal, build_failed, build_success
    ):
        """Returns the last FeedbackMessage."""
        state = ProverAgentState(
            item=sample_item, messages=[proposal, build_failed, proposal, build_success]
        )
        assert state.last_feedback.feedback_type == "build_success"

    def test_approved_true(self, sample_item, proposal, review_approved):
        """approved is True when ReviewApprovedFeedback present."""
        state = ProverAgentState(item=sample_item, messages=[proposal, review_approved])
        assert state.approved is True

    def test_approved_false(self, sample_item, proposal, build_failed):
        """approved is False when only build feedback."""
        state = ProverAgentState(item=sample_item, messages=[proposal, build_failed])
        assert state.approved is False


class TestNormalizeMessages:
    """Tests for the normalize_messages model validator."""

    def test_pydantic_models_passed_through(self, sample_item, proposal, build_failed):
        """Already-instantiated messages are preserved."""
        state = ProverAgentState(item=sample_item, messages=[proposal, build_failed])
        assert isinstance(state.messages[0], ProposalMessage)
        assert isinstance(state.messages[1], BuildFailedFeedback)

    def test_empty_messages_no_error(self, sample_item):
        """Empty message list works."""
        state = ProverAgentState(item=sample_item, messages=[])
        assert state.messages == []


class TestProverMetrics:
    """Tests for ProverMetrics defaults."""

    def test_defaults(self):
        """All metrics default to 0 / False."""
        m = ProverMetrics()
        assert m.build_timeout_count == 0
        assert m.compilation_error_count == 0
        assert m.number_of_iterations == 0
        assert m.reviewer_rejections == 0
        assert m.max_iterations_reached is False


class TestProverResult:
    """Tests for ProverResult structured output schema."""

    def test_defaults(self):
        """imports and opens default to empty lists."""
        r = ProverResult(updated_theorem="theorem foo := sorry")
        assert r.imports == []
        assert r.opens == []
        assert r.updated_theorem == "theorem foo := sorry"


class TestReviewDecision:
    """Tests for ReviewDecision model."""

    def test_stores_checks(self):
        """All check fields are stored correctly."""
        d = ReviewDecision(check_1=True, check_2=True, check_3=False, approved=True)
        assert d.check_1 is True
        assert d.check_2 is True
        assert d.check_3 is False
        assert d.approved is True
