from __future__ import annotations

import argparse
import json
from pathlib import Path
from typing import Any

from coolrl_lost_cities.games.classic.game import GameState, LostCitiesConfig

from coolrl_lost_cities.games.classic.bots.heuristic_py import HeuristicBot
from coolrl_lost_cities.games.classic.bots.registry import (
    AGGRESSIVE_HEURISTIC_PARAMS,
    CAUTIOUS_HEURISTIC_PARAMS,
)

VARIANTS = {
    "default": None,
    "loose": AGGRESSIVE_HEURISTIC_PARAMS,
    "strict": CAUTIOUS_HEURISTIC_PARAMS,
}


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        description="Export heuristic bot parity snapshots for external implementations."
    )
    parser.add_argument("--output", required=True, help="JSONL output path.")
    parser.add_argument("--seeds", type=int, default=50, help="Number of seeds per config.")
    parser.add_argument("--max-steps", type=int, default=10_000)
    return parser.parse_args()


def _configs() -> list[tuple[str, LostCitiesConfig]]:
    return [
        ("classic", LostCitiesConfig()),
        ("small", LostCitiesConfig(n_colors=2, n_ranks=8, hand_size=3)),
        (
            "no-handshakes",
            LostCitiesConfig(n_colors=3, n_ranks=5, n_handshakes=0, hand_size=5),
        ),
    ]


def _record(
    *,
    config_name: str,
    variant_name: str,
    seed: int,
    turn: int,
    state: GameState,
    action: int,
) -> dict[str, Any]:
    return {
        "config_name": config_name,
        "variant": variant_name,
        "seed": seed,
        "turn": turn,
        "phase": state.phase,
        "current_player": state.current_player,
        "expected_action": action,
        "state": state.to_snapshot(),
    }


def main() -> None:
    args = parse_args()
    output = Path(args.output)
    output.parent.mkdir(parents=True, exist_ok=True)
    count = 0
    with output.open("w", encoding="utf-8") as handle:
        for config_name, config in _configs():
            for variant_name, params in VARIANTS.items():
                for seed in range(args.seeds):
                    bot = HeuristicBot(params)
                    state = GameState.new_game(config, seed=seed)
                    for turn in range(args.max_steps):
                        if state.terminal:
                            break
                        action = bot.act(state)
                        handle.write(
                            json.dumps(
                                _record(
                                    config_name=config_name,
                                    variant_name=variant_name,
                                    seed=seed,
                                    turn=turn,
                                    state=state,
                                    action=action,
                                ),
                                sort_keys=True,
                            )
                            + "\n"
                        )
                        count += 1
                        state.apply_action(action)
                    else:
                        raise RuntimeError(
                            f"game did not terminate: config={config_name} "
                            f"variant={variant_name} seed={seed}"
                        )
    print(f"Wrote {count} snapshots to {output}")


if __name__ == "__main__":
    main()
