"""Tests for the CriticOutcome enum and CriticResult.outcome field."""
import pytest
from recoil.core.critic import Outcome, CriticResult, Dimension, Severity


def test_outcome_enum_has_three_values():
    assert Outcome.PASS.value == "pass"
    assert Outcome.FAIL.value == "fail"
    assert Outcome.ERROR.value == "error"


def test_critic_result_default_is_pass():
    result = CriticResult(critic_name="test")
    assert result.outcome == Outcome.PASS
    assert result.passed is True


def test_critic_result_passed_is_false_on_error():
    """Legacy callers using .passed must see False on ERROR."""
    result = CriticResult(critic_name="test", outcome=Outcome.ERROR, error="boom")
    assert result.passed is False
    assert result.errored is True


def test_critic_result_passed_is_false_on_fail():
    result = CriticResult(critic_name="test", outcome=Outcome.FAIL)
    assert result.passed is False
    assert result.errored is False


def test_critic_result_passed_is_true_on_pass():
    result = CriticResult(critic_name="test", outcome=Outcome.PASS)
    assert result.passed is True
    assert result.errored is False


def test_critic_result_to_dict_serializes_outcome():
    result = CriticResult(
        critic_name="test",
        outcome=Outcome.ERROR,
        dimensions=[Dimension(name="X", severity=Severity.HARD, passed=False, message="boom")],
    )
    d = result.to_dict()
    assert d["outcome"] == "error"
    assert d["dimensions"][0]["severity"] == "hard"


def test_critic_loop_returns_error_on_exception():
    """Vision API down → ERROR outcome, NOT silent PASS."""
    from recoil.core.critic import CriticLoop, Outcome

    class _CrashCritic(CriticLoop):
        def evaluate(self, artifact, context):
            raise RuntimeError("simulated vision API failure")

    critic = _CrashCritic(name="crash_test", max_attempts=1)
    artifact, result = critic.run("dummy_artifact")
    assert result.outcome == Outcome.ERROR
    assert result.passed is False  # legacy check
    assert result.errored is True
    assert "simulated vision API failure" in result.error
    assert artifact == "dummy_artifact"  # original returned, not corrupted


def test_critic_loop_error_logged_to_experience_pool(tmp_path):
    """ERROR outcomes still write to experience pool — JT needs the audit trail."""
    from recoil.core.critic import CriticLoop, Dimension, Severity

    class _CrashCritic(CriticLoop):
        def evaluate(self, artifact, context):
            raise RuntimeError("api timeout")

    pool_dir = tmp_path / "exp"
    critic = _CrashCritic(name="test_crit", max_attempts=1, experience_pool_dir=pool_dir, shot_id="EP001_SH01")
    critic.run("art")

    pool_file = pool_dir / "experience_pool.jsonl"
    assert pool_file.exists()
    import json
    entry = json.loads(pool_file.read_text().strip().splitlines()[-1])
    assert entry["critic"] == "test_crit"
    assert entry["passed"] is False
    assert entry["error"] == "api timeout"
