"""CLI entry point for all dataset importers.

Usage:
    python -m evals.importers.cli debugbench --max-cases 40 --validate
    python -m evals.importers.cli pyresbugs --max-cases 150 --validate
    python -m evals.importers.cli humanevalpack --max-cases 20 --validate
    python -m evals.importers.cli condefects --repo-path /path/to/ConDefects --max-cases 15
    python -m evals.importers.cli mutmut --target src/llmdebug --max-cases 30
    python -m evals.importers.cli debugbench --max-cases 5 --dry-run
"""

from __future__ import annotations

import argparse
import json
from pathlib import Path

from evals.run_eval import (
    add_execution_arguments,
    build_execution_config_from_args,
    check_testcontainers_runtime_available,
    set_active_execution_config,
)
from evals.validate_cases import check_pytest_available


def main(argv: list[str] | None = None) -> int:
    execution_flags_parser = argparse.ArgumentParser(add_help=False)
    add_execution_arguments(execution_flags_parser, include_defaults=False)
    parser = argparse.ArgumentParser(
        description="Import external dataset cases into the llmdebug framework."
    )
    add_execution_arguments(parser)
    sub = parser.add_subparsers(dest="source", help="Dataset source to import from.")

    # DebugBench
    db = sub.add_parser(
        "debugbench",
        help="Import from DebugBench (HuggingFace).",
        parents=[execution_flags_parser],
    )
    db.add_argument("--max-cases", type=int, default=0, help="Max cases to import (0 = unlimited).")
    db.add_argument("--output-dir", default="evals/cases")
    db.add_argument("--validate", action="store_true")
    db.add_argument("--dry-run", action="store_true")

    # PyResBugs
    prb = sub.add_parser(
        "pyresbugs",
        help="Import from PyResBugs (HuggingFace).",
        parents=[execution_flags_parser],
    )
    prb.add_argument(
        "--max-cases", type=int, default=0, help="Max cases to import (0 = unlimited)."
    )
    prb.add_argument("--output-dir", default="evals/cases")
    prb.add_argument("--validate", action="store_true")
    prb.add_argument("--dry-run", action="store_true")

    # HumanEvalPack
    hep = sub.add_parser(
        "humanevalpack",
        help="Import from HumanEvalPack (HuggingFace).",
        parents=[execution_flags_parser],
    )
    hep.add_argument("--max-cases", type=int, default=20)
    hep.add_argument("--output-dir", default="evals/cases")
    hep.add_argument("--validate", action="store_true")
    hep.add_argument("--dry-run", action="store_true")

    # ConDefects
    cd = sub.add_parser(
        "condefects",
        help="Import from ConDefects (local clone + Test.zip).",
        parents=[execution_flags_parser],
    )
    cd.add_argument("--repo-path", required=True, help="Path to cloned ConDefects repo.")
    cd.add_argument(
        "--test-zip", required=True, help="Path to Test.zip with test input/output data."
    )
    cd.add_argument("--max-cases", type=int, default=0, help="Max cases to import (0 = unlimited).")
    cd.add_argument("--output-dir", default="evals/cases")
    cd.add_argument("--validate", action="store_true")
    cd.add_argument("--dry-run", action="store_true")

    # mutmut
    mm = sub.add_parser(
        "mutmut",
        help="Generate cases from mutmut mutations.",
        parents=[execution_flags_parser],
    )
    mm.add_argument("--target", required=True, help="Python module/package to mutate.")
    mm.add_argument("--max-cases", type=int, default=30)
    mm.add_argument("--output-dir", default="evals/cases")
    mm.add_argument("--validate", action="store_true")
    mm.add_argument("--dry-run", action="store_true")

    args = parser.parse_args(argv)
    try:
        execution_config = build_execution_config_from_args(args)
    except ValueError as exc:
        print(f"Invalid arguments: {exc}")
        return 2

    if not args.source:
        parser.print_help()
        return 2
    if bool(args.validate):
        if execution_config.executor == "local":
            ok, message = check_pytest_available()
        else:
            ok, message = check_testcontainers_runtime_available()
        if not ok:
            print(f"Environment check failed: {message}")
            return 2

    output_dir = Path(args.output_dir)
    if not output_dir.is_absolute():
        output_dir = Path.cwd() / output_dir

    previous_execution_config = set_active_execution_config(execution_config)
    try:
        if args.source == "debugbench":
            from evals.importers.debugbench_importer import import_debugbench

            results = import_debugbench(
                output_dir,
                max_cases=args.max_cases,
                validate=args.validate,
                dry_run=args.dry_run,
            )

        elif args.source == "pyresbugs":
            from evals.importers.pyresbugs_importer import import_pyresbugs

            results = import_pyresbugs(
                output_dir,
                max_cases=args.max_cases,
                validate=args.validate,
                dry_run=args.dry_run,
            )

        elif args.source == "humanevalpack":
            from evals.importers.humanevalpack_importer import import_humanevalpack

            results = import_humanevalpack(
                output_dir,
                max_cases=args.max_cases,
                validate=args.validate,
                dry_run=args.dry_run,
            )

        elif args.source == "condefects":
            from evals.importers.condefects_importer import import_condefects

            results = import_condefects(
                output_dir,
                repo_path=Path(args.repo_path),
                test_zip=Path(args.test_zip),
                max_cases=args.max_cases,
                validate=args.validate,
                dry_run=args.dry_run,
            )

        elif args.source == "mutmut":
            from evals.importers.mutmut_generator import import_mutmut

            results = import_mutmut(
                output_dir,
                target=args.target,
                max_cases=args.max_cases,
                validate=args.validate,
                dry_run=args.dry_run,
            )

        else:
            print(f"Unknown source: {args.source}")
            return 2
    finally:
        set_active_execution_config(previous_execution_config)

    mode = "previewed" if args.dry_run else "imported"
    print(f"\n{len(results)} case(s) {mode} from {args.source}.")

    if args.dry_run and results:
        print("\nPreview:")
        for r in results[:5]:
            print(f"  {r['case_id']}: {json.dumps(r.get('metadata', {}), indent=None)[:120]}...")
        if len(results) > 5:
            print(f"  ... and {len(results) - 5} more")

    return 0


if __name__ == "__main__":
    raise SystemExit(main())
