"""Tests for eval case selection and failure-based filtering from run logs."""

from __future__ import annotations

from pathlib import Path

from evals import select_cases
from llmdebug import _json as json


def _write_jsonl(path: Path, rows: list[dict]) -> None:
    path.write_text("".join(json.dumps(row) + "\n" for row in rows), encoding="utf-8")


def test_select_cases_failed_mode_with_duplicate_attempt_last_write_wins(tmp_path, capsys) -> None:
    input_path = tmp_path / "run.jsonl"
    output_path = tmp_path / "failed.txt"
    _write_jsonl(
        input_path,
        [
            # case_a attempt 1 originally failing, then duplicate attempt row marks success.
            {"case_id": "case_a", "condition": "traceback_only", "attempt": 1, "success": False},
            {"case_id": "case_a", "condition": "traceback_only", "attempt": 1, "success": True},
            {"case_id": "case_b", "condition": "traceback_only", "attempt": 1, "success": False},
            {"case_id": "case_c", "condition": "traceback_only", "attempt": 2, "success": True},
            {"case_id": "case_d", "condition": "with_snapshot", "attempt": 3, "success": False},
        ],
    )

    exit_code = select_cases.main(
        [
            "--results-jsonl",
            str(input_path),
            "--condition",
            "traceback_only",
            "--mode",
            "failed",
            "--out",
            str(output_path),
        ]
    )

    assert exit_code == 0
    assert output_path.read_text(encoding="utf-8") == "case_b\n"
    assert "Selected 1 case(s)" in capsys.readouterr().out


def test_select_cases_attempt_ge_mode(tmp_path) -> None:
    input_path = tmp_path / "run.jsonl"
    output_path = tmp_path / "attempt_ge.txt"
    _write_jsonl(
        input_path,
        [
            {"case_id": "case_a", "condition": "traceback_only", "attempt": 1, "success": True},
            {"case_id": "case_b", "condition": "traceback_only", "attempt": 2, "success": True},
            {"case_id": "case_c", "condition": "traceback_only", "attempt": 3, "success": False},
        ],
    )

    exit_code = select_cases.main(
        [
            "--results-jsonl",
            str(input_path),
            "--condition",
            "traceback_only",
            "--mode",
            "attempt-ge",
            "--attempt-threshold",
            "2",
            "--out",
            str(output_path),
        ]
    )

    assert exit_code == 0
    assert output_path.read_text(encoding="utf-8") == "case_b\ncase_c\n"


def test_select_cases_failed_or_attempt_ge_mode(tmp_path) -> None:
    input_path = tmp_path / "run.jsonl"
    output_path = tmp_path / "union.txt"
    _write_jsonl(
        input_path,
        [
            {"case_id": "case_a", "condition": "traceback_only", "attempt": 1, "success": False},
            {"case_id": "case_b", "condition": "traceback_only", "attempt": 2, "success": True},
            {"case_id": "case_c", "condition": "traceback_only", "attempt": 1, "success": True},
        ],
    )

    exit_code = select_cases.main(
        [
            "--results-jsonl",
            str(input_path),
            "--condition",
            "traceback_only",
            "--mode",
            "failed-or-attempt-ge",
            "--attempt-threshold",
            "2",
            "--out",
            str(output_path),
        ]
    )

    assert exit_code == 0
    assert output_path.read_text(encoding="utf-8") == "case_a\ncase_b\n"


def test_select_cases_fails_when_condition_missing(tmp_path, capsys) -> None:
    input_path = tmp_path / "run.jsonl"
    output_path = tmp_path / "missing.txt"
    _write_jsonl(
        input_path,
        [
            {"case_id": "case_a", "condition": "with_snapshot", "attempt": 1, "success": False},
        ],
    )

    exit_code = select_cases.main(
        [
            "--results-jsonl",
            str(input_path),
            "--condition",
            "traceback_only",
            "--out",
            str(output_path),
        ]
    )

    assert exit_code == 2
    assert "No rows found for condition='traceback_only'" in capsys.readouterr().out


def test_select_cases_failed_mode_includes_request_budget_exceeded(tmp_path, capsys) -> None:
    input_path = tmp_path / "run.jsonl"
    output_path = tmp_path / "failed.txt"
    _write_jsonl(
        input_path,
        [
            {
                "case_id": "case_budget_failed",
                "condition": "traceback_only",
                "attempt": 2,
                "success": False,
                "note": "patcher_request_failed",
                "patch_meta": {"patcher_request_failure_error": "request_budget_exceeded"},
            },
            {
                "case_id": "case_tests_failed",
                "condition": "traceback_only",
                "attempt": 1,
                "success": False,
                "note": "tests_still_failing",
            },
            {
                "case_id": "case_success",
                "condition": "traceback_only",
                "attempt": 1,
                "success": True,
                "note": "success",
            },
        ],
    )

    exit_code = select_cases.main(
        [
            "--results-jsonl",
            str(input_path),
            "--condition",
            "traceback_only",
            "--mode",
            "failed",
            "--out",
            str(output_path),
        ]
    )

    assert exit_code == 0
    assert output_path.read_text(encoding="utf-8") == "case_budget_failed\ncase_tests_failed\n"
    captured = capsys.readouterr().out
    assert "Terminal request_budget_exceeded failures: 1 (selected=1)." in captured


def test_select_cases_failed_mode_respects_max_attempt_filter(tmp_path) -> None:
    input_path = tmp_path / "run.jsonl"
    output_path = tmp_path / "failed.txt"
    _write_jsonl(
        input_path,
        [
            {
                "case_id": "case_failed_attempt_2",
                "condition": "traceback_only",
                "attempt": 2,
                "success": False,
            },
            {
                "case_id": "case_failed_attempt_3",
                "condition": "traceback_only",
                "attempt": 3,
                "success": False,
            },
        ],
    )

    exit_code = select_cases.main(
        [
            "--results-jsonl",
            str(input_path),
            "--condition",
            "traceback_only",
            "--mode",
            "failed",
            "--max-attempt",
            "2",
            "--out",
            str(output_path),
        ]
    )

    assert exit_code == 0
    assert output_path.read_text(encoding="utf-8") == "case_failed_attempt_2\n"
