"""Tests for the dataset importers CLI dispatch and argument parsing."""

from __future__ import annotations

import sys
import types
from pathlib import Path

from evals.importers import cli as importers_cli
from evals.importers.top3_bootstrap import MaterializationReport, SourceMaterializationReport


def _install_fake_debugbench_importer(monkeypatch):
    calls: dict[str, object] = {}

    fake_module = types.ModuleType("evals.importers.debugbench_importer")

    def _fake_import_debugbench(output_dir, max_cases, validate, dry_run):
        calls["output_dir"] = output_dir
        calls["max_cases"] = max_cases
        calls["validate"] = validate
        calls["dry_run"] = dry_run
        return []

    fake_module.import_debugbench = _fake_import_debugbench
    monkeypatch.setitem(sys.modules, "evals.importers.debugbench_importer", fake_module)
    return calls


def _install_fake_top3_bootstrap(monkeypatch, *, hard_fail: bool):
    calls: dict[str, object] = {}

    fake_module = types.ModuleType("evals.importers.top3_bootstrap")

    class _Dataset:
        def __init__(self, source: str) -> None:
            self.source = source

    class _Manifest:
        def __init__(self) -> None:
            self.datasets = [_Dataset("bugsinpy"), _Dataset("pybughive"), _Dataset("trickybugs")]

    def _fake_prepare_top3_lock_manifest(manifest_path):
        calls["prepare_manifest_path"] = manifest_path
        return _Manifest()

    def _fake_materialize_top3(
        *,
        manifest_path,
        output_dir,
        data_root,
        download_policy,
        jobs,
        max_cases,
        validate,
        dry_run,
    ):
        calls["materialize_manifest_path"] = manifest_path
        calls["materialize_output_dir"] = output_dir
        calls["materialize_data_root"] = data_root
        calls["download_policy"] = download_policy
        calls["jobs"] = jobs
        calls["max_cases"] = max_cases
        calls["validate"] = validate
        calls["dry_run"] = dry_run
        report = MaterializationReport(
            schema_version=1,
            started_at_utc="2026-01-01T00:00:00+00:00",
            finished_at_utc="2026-01-01T00:00:01+00:00",
            manifest_path=str(manifest_path),
            data_root=str(data_root),
            output_dir=str(output_dir),
            download_policy=download_policy,
            max_cases=max_cases,
            validate=validate,
            dry_run=dry_run,
            jobs=jobs,
            sources=[
                SourceMaterializationReport(
                    source="bugsinpy",
                    attempted=3,
                    imported=2,
                    skipped=1,
                    hard_failed=False,
                    skip_reasons={"example_reason": 1},
                    imported_case_ids=["bip_a", "bip_b"],
                    notes=[],
                )
            ],
        )
        return report, Path("evals/artifacts/import_reports/top3-test.json")

    def _fake_report_has_hard_failures(report) -> bool:
        del report
        return hard_fail

    fake_module.prepare_top3_lock_manifest = _fake_prepare_top3_lock_manifest
    fake_module.materialize_top3 = _fake_materialize_top3
    fake_module.report_has_hard_failures = _fake_report_has_hard_failures
    monkeypatch.setitem(sys.modules, "evals.importers.top3_bootstrap", fake_module)
    return calls


def test_importers_cli_accepts_execution_flags_after_subcommand(monkeypatch) -> None:
    calls = _install_fake_debugbench_importer(monkeypatch)
    exit_code = importers_cli.main(["debugbench", "--executor", "local", "--dry-run"])
    assert exit_code == 0
    assert calls["dry_run"] is True
    assert isinstance(calls["output_dir"], Path)


def test_importers_cli_accepts_execution_flags_before_subcommand(monkeypatch) -> None:
    calls = _install_fake_debugbench_importer(monkeypatch)
    exit_code = importers_cli.main(["--executor", "local", "debugbench", "--dry-run"])
    assert exit_code == 0
    assert calls["dry_run"] is True
    assert isinstance(calls["output_dir"], Path)


def test_cli_registry_parser_supports_materialize_top3() -> None:
    parser = importers_cli._build_parser()
    parsed = parser.parse_args(["--executor", "local", "materialize-top3"])
    assert parsed.source == "materialize-top3"


def test_prepare_top3_writes_manifest_via_bootstrap(monkeypatch, tmp_path) -> None:
    calls = _install_fake_top3_bootstrap(monkeypatch, hard_fail=False)
    manifest_path = tmp_path / "top3.lock.json"
    exit_code = importers_cli.main(["prepare-top3", "--manifest", str(manifest_path)])
    assert exit_code == 0
    assert calls["prepare_manifest_path"] == manifest_path


def test_materialize_top3_parses_arguments_and_executes(monkeypatch, tmp_path) -> None:
    calls = _install_fake_top3_bootstrap(monkeypatch, hard_fail=False)
    monkeypatch.setattr(importers_cli, "check_pytest_available", lambda: (True, "ok"))

    exit_code = importers_cli.main(
        [
            "--executor",
            "local",
            "materialize-top3",
            "--manifest",
            str(tmp_path / "top3.lock.json"),
            "--output-dir",
            str(tmp_path / "cases"),
            "--data-root",
            str(tmp_path / "data"),
            "--download-policy",
            "never",
            "--jobs",
            "3",
            "--max-cases",
            "9",
            "--validate",
            "--dry-run",
        ]
    )

    assert exit_code == 0
    assert calls["download_policy"] == "never"
    assert calls["jobs"] == 3
    assert calls["max_cases"] == 9
    assert calls["validate"] is True
    assert calls["dry_run"] is True
    assert calls["materialize_output_dir"] == tmp_path / "cases"
    assert calls["materialize_data_root"] == tmp_path / "data"


def test_materialize_top3_returns_nonzero_on_hard_failure(monkeypatch, tmp_path) -> None:
    _install_fake_top3_bootstrap(monkeypatch, hard_fail=True)
    monkeypatch.setattr(importers_cli, "check_pytest_available", lambda: (True, "ok"))

    exit_code = importers_cli.main(
        [
            "--executor",
            "local",
            "materialize-top3",
            "--manifest",
            str(tmp_path / "top3.lock.json"),
            "--output-dir",
            str(tmp_path / "cases"),
            "--data-root",
            str(tmp_path / "data"),
            "--download-policy",
            "never",
        ]
    )

    assert exit_code == 1
