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
