"""Tests for the graduation test runner.

Refs: #953 (Graduation Test)
"""

from unittest.mock import patch

import pytest


@pytest.mark.unit
class TestConditionResults:
    """Tests for individual graduation condition evaluations."""

    def test_economic_independence_pass(self):
        """Passes when sats earned exceeds sats spent."""
        from timmy.sovereignty.graduation import evaluate_economic_independence

        result = evaluate_economic_independence(sats_earned=100.0, sats_spent=50.0)
        assert result.passed is True
        assert result.actual == 50.0  # net
        assert "Earned: 100.0" in result.detail

    def test_economic_independence_fail_net_negative(self):
        """Fails when spending exceeds earnings."""
        from timmy.sovereignty.graduation import evaluate_economic_independence

        result = evaluate_economic_independence(sats_earned=10.0, sats_spent=50.0)
        assert result.passed is False

    def test_economic_independence_fail_zero_earnings(self):
        """Fails when earnings are zero even if spending is zero."""
        from timmy.sovereignty.graduation import evaluate_economic_independence

        result = evaluate_economic_independence(sats_earned=0.0, sats_spent=0.0)
        assert result.passed is False

    def test_operational_independence_pass(self):
        """Passes when uptime meets threshold and no interventions."""
        from timmy.sovereignty.graduation import evaluate_operational_independence

        result = evaluate_operational_independence(uptime_hours=24.0, human_interventions=0)
        assert result.passed is True

    def test_operational_independence_fail_low_uptime(self):
        """Fails when uptime is below threshold."""
        from timmy.sovereignty.graduation import evaluate_operational_independence

        result = evaluate_operational_independence(uptime_hours=20.0, human_interventions=0)
        assert result.passed is False

    def test_operational_independence_fail_interventions(self):
        """Fails when there are human interventions."""
        from timmy.sovereignty.graduation import evaluate_operational_independence

        result = evaluate_operational_independence(uptime_hours=24.0, human_interventions=2)
        assert result.passed is False


@pytest.mark.unit
class TestGraduationReport:
    """Tests for the GraduationReport rendering."""

    def test_to_dict(self):
        """Report serializes to dict correctly."""
        from timmy.sovereignty.graduation import ConditionResult, GraduationReport

        report = GraduationReport(
            all_passed=False,
            conditions=[
                ConditionResult(name="Test", passed=True, actual=0, target=0, unit=" calls")
            ],
        )
        d = report.to_dict()
        assert d["all_passed"] is False
        assert len(d["conditions"]) == 1
        assert d["conditions"][0]["name"] == "Test"

    def test_to_markdown(self):
        """Report renders to readable markdown."""
        from timmy.sovereignty.graduation import ConditionResult, GraduationReport

        report = GraduationReport(
            all_passed=True,
            conditions=[
                ConditionResult(name="Perception", passed=True, actual=0, target=0),
                ConditionResult(name="Decision", passed=True, actual=3, target=5),
            ],
        )
        md = report.to_markdown()
        assert "PASSED" in md
        assert "Perception" in md
        assert "Decision" in md
        assert "falsework" in md.lower()


@pytest.mark.unit
class TestRunGraduationTest:
    """Tests for the full graduation test runner."""

    @patch("timmy.sovereignty.graduation.evaluate_perception_independence")
    @patch("timmy.sovereignty.graduation.evaluate_decision_independence")
    @patch("timmy.sovereignty.graduation.evaluate_narration_independence")
    def test_all_pass(self, mock_narr, mock_dec, mock_perc):
        """Full graduation passes when all 5 conditions pass."""
        from timmy.sovereignty.graduation import ConditionResult, run_graduation_test

        mock_perc.return_value = ConditionResult(name="Perception", passed=True, actual=0, target=0)
        mock_dec.return_value = ConditionResult(name="Decision", passed=True, actual=3, target=5)
        mock_narr.return_value = ConditionResult(name="Narration", passed=True, actual=0, target=0)

        report = run_graduation_test(
            sats_earned=100.0,
            sats_spent=50.0,
            uptime_hours=24.0,
            human_interventions=0,
        )

        assert report.all_passed is True
        assert len(report.conditions) == 5
        assert all(c.passed for c in report.conditions)

    @patch("timmy.sovereignty.graduation.evaluate_perception_independence")
    @patch("timmy.sovereignty.graduation.evaluate_decision_independence")
    @patch("timmy.sovereignty.graduation.evaluate_narration_independence")
    def test_partial_fail(self, mock_narr, mock_dec, mock_perc):
        """Graduation fails when any single condition fails."""
        from timmy.sovereignty.graduation import ConditionResult, run_graduation_test

        mock_perc.return_value = ConditionResult(name="Perception", passed=True, actual=0, target=0)
        mock_dec.return_value = ConditionResult(name="Decision", passed=False, actual=10, target=5)
        mock_narr.return_value = ConditionResult(name="Narration", passed=True, actual=0, target=0)

        report = run_graduation_test(
            sats_earned=100.0,
            sats_spent=50.0,
            uptime_hours=24.0,
            human_interventions=0,
        )

        assert report.all_passed is False

    def test_persist_report(self, tmp_path):
        """Graduation report persists to JSON file."""
        from timmy.sovereignty.graduation import (
            ConditionResult,
            GraduationReport,
            persist_graduation_report,
        )

        report = GraduationReport(
            all_passed=False,
            conditions=[ConditionResult(name="Test", passed=False, actual=5, target=0)],
        )

        with patch("timmy.sovereignty.graduation.settings") as mock_settings:
            mock_settings.repo_root = str(tmp_path)
            path = persist_graduation_report(report)

        assert path.exists()
        import json

        with open(path) as f:
            data = json.load(f)
        assert data["all_passed"] is False
