"""CLI for unified evaluation.

Usage:
    uv run python -m essence_wars.eval --agents ppo-generalist greedy mcts-100
    uv run python -m essence_wars.eval --preset validate
    uv run python -m essence_wars.eval --preset benchmark
"""

from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path

from .unified import PRESETS, UnifiedEvaluator


def prompt_train_missing(missing_agents: list) -> bool:
    """Prompt user to train missing agents."""
    from essence_wars.models import ModelRegistry

    try:
        registry = ModelRegistry.load()
    except FileNotFoundError:
        return False

    print("\nMissing models detected:")
    trainable = []
    for spec in missing_agents:
        if spec.registry_name:
            model = registry.get(spec.registry_name)
            if model:
                print(f"  - {spec.name}")
                trainable.append(model)

    if not trainable:
        print("  (no trainable models in missing list)")
        return False

    print("\nOptions:")
    print("  [1] Train missing models now")
    print("  [2] Continue without missing models")
    print("  [3] Abort")

    try:
        choice = input("\nChoice [1]: ").strip() or "1"
    except (EOFError, KeyboardInterrupt):
        return False

    if choice == "1":
        import subprocess

        print()
        for i, model in enumerate(trainable, 1):
            print(f"[{i}/{len(trainable)}] Training {model.name}...")
            print(f"  Command: {model.train_cmd}")

            result = subprocess.run(model.train_cmd, shell=True, check=False)
            if result.returncode != 0:
                print(f"  Training failed (exit code {result.returncode})")
                return False

            print("  Complete")
            print()

        return True

    elif choice == "2":
        return False

    else:
        sys.exit(0)


def cmd_evaluate(args: argparse.Namespace) -> int:
    """Run evaluation."""
    # Determine agents from preset or explicit list
    if args.preset:
        if args.preset not in PRESETS:
            print(f"Unknown preset: {args.preset}", file=sys.stderr)
            print(f"Available: {', '.join(PRESETS.keys())}")
            return 1

        preset = PRESETS[args.preset]
        agent_specs = preset["agents"]
        games_per_matchup = args.games or preset["games_per_matchup"]
        print(f"Using preset '{args.preset}': {preset['description']}")
        print()
    else:
        agent_specs = args.agents
        games_per_matchup = args.games or 50

    if not agent_specs:
        print("No agents specified. Use --agents or --preset.", file=sys.stderr)
        return 1

    # Create evaluator
    evaluator = UnifiedEvaluator(
        games_per_matchup=games_per_matchup,
        verbose=not args.quiet,
        update_elo=not args.no_elo,
    )

    # Check availability
    available, missing = evaluator.check_availability(agent_specs)

    if missing and not args.quiet:
        # Offer to train missing models
        trained = prompt_train_missing(missing)
        if trained:
            # Re-check availability
            available, missing = evaluator.check_availability(agent_specs)

    if not available:
        print("No agents available for evaluation.", file=sys.stderr)
        return 1

    # Continue with available agents
    if missing and not args.quiet:
        print(f"Proceeding with {len(available)} available agents")
        print()

    # Run evaluation
    try:
        results = evaluator.evaluate(
            [spec.name if spec.registry_name else f"{spec.agent_type}" + (f"-{spec.config.get('simulations', spec.config.get('depth', ''))}" if spec.config else "") for spec in available],
            games_per_matchup=games_per_matchup,
        )
    except KeyboardInterrupt:
        print("\nEvaluation interrupted.")
        return 130

    # Print summary
    print()
    print(results.summary())

    # Save results if output path specified
    if args.output:
        output_path = Path(args.output)
        output_data = {
            "agents": results.agents,
            "elo_ratings": results.elo_ratings,
            "total_games": results.total_games,
            "elapsed_seconds": results.elapsed_seconds,
            "matchups": [
                {
                    "agent1": m.agent1,
                    "agent2": m.agent2,
                    "games": m.games,
                    "agent1_wins": m.agent1_wins,
                    "agent2_wins": m.agent2_wins,
                    "draws": m.draws,
                    "agent1_win_rate": m.agent1_win_rate,
                    "agent2_win_rate": m.agent2_win_rate,
                }
                for m in results.matchups
            ],
        }
        with output_path.open("w") as f:
            json.dump(output_data, f, indent=2)
        print(f"\nResults saved to: {output_path}")

    return 0


def cmd_presets(_args: argparse.Namespace) -> int:
    """List available presets."""
    print("Available presets:\n")
    for name, preset in PRESETS.items():
        print(f"  {name}")
        print(f"    {preset['description']}")
        print(f"    Agents: {', '.join(preset['agents'])}")
        print(f"    Games/matchup: {preset['games_per_matchup']}")
        print()
    return 0


def main(argv: list[str] | None = None) -> int:
    """Main entry point for the CLI."""
    parser = argparse.ArgumentParser(
        prog="python -m essence_wars.eval",
        description="Unified evaluation for Essence Wars agents",
    )

    parser.add_argument(
        "--agents",
        nargs="+",
        help="Agent specifications (e.g., ppo-generalist greedy mcts-100)",
    )
    parser.add_argument(
        "--preset",
        choices=list(PRESETS.keys()),
        help="Use a preset configuration",
    )
    parser.add_argument(
        "--games",
        type=int,
        help="Games per matchup (default: 50, or preset default)",
    )
    parser.add_argument(
        "--output",
        "-o",
        help="Save results to JSON file",
    )
    parser.add_argument(
        "--no-elo",
        action="store_true",
        help="Don't update agent_elo.json",
    )
    parser.add_argument(
        "--quiet",
        "-q",
        action="store_true",
        help="Minimal output",
    )
    parser.add_argument(
        "--list-presets",
        action="store_true",
        help="List available presets and exit",
    )

    args = parser.parse_args(argv)

    if args.list_presets:
        return cmd_presets(args)

    return cmd_evaluate(args)


if __name__ == "__main__":
    sys.exit(main())
