"""CLI entry point for the PokeDB import tool.

Usage:
    # From tools/import-pokedb/ (auto-downloads PokeDB data on first run):
    python -m import_pokedb

    # With options:
    python -m import_pokedb --game firered
    python -m import_pokedb --pokedb-dir ~/my-pokedb-data/
    python -m import_pokedb --output /tmp/seed-output/
"""

from __future__ import annotations

import argparse
import sys
from pathlib import Path

from .loader import load_pokedb_data, load_seed_config
from .mappings import PokemonMapper, LocationMapper, build_version_map, map_encounter_method
from .output import sort_routes, merge_special_encounters, write_game_json, write_games_json, write_pokemon_json
from .processing import filter_encounters_for_game, process_encounters, build_routes
from .sprites import download_all_sprites, download_sprites

SEEDS_DIR_CANDIDATES = [
    Path("backend/src/app/seeds"),                # from repo root
    Path("../../backend/src/app/seeds"),           # from tools/import-pokedb/
]

SPRITES_DIR_CANDIDATES = [
    Path("frontend/public/sprites"),              # from repo root
    Path("../../frontend/public/sprites"),         # from tools/import-pokedb/
]


def find_seeds_dir() -> Path:
    """Locate the backend seeds directory."""
    for candidate in SEEDS_DIR_CANDIDATES:
        if (candidate / "version_groups.json").exists():
            return candidate.resolve()
    # Fallback
    return Path("backend/src/app/seeds").resolve()


def find_sprites_dir() -> Path:
    """Locate the frontend sprites directory."""
    for candidate in SPRITES_DIR_CANDIDATES:
        if candidate.parent.exists():
            return candidate.resolve()
    # Fallback
    return Path("frontend/public/sprites").resolve()


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        prog="import-pokedb",
        description="Convert PokeDB.org JSON data exports into nuzlocke-tracker seed format.",
    )
    parser.add_argument(
        "--pokedb-dir",
        type=Path,
        default=None,
        help="Path to directory containing PokeDB JSON export files (default: .pokedb_cache/)",
    )
    parser.add_argument(
        "--output",
        type=Path,
        default=None,
        help="Output directory for seed JSON files (default: backend/src/app/seeds/data/)",
    )
    parser.add_argument(
        "--game",
        type=str,
        default=None,
        help="Generate data for a specific game slug only (default: all games)",
    )
    return parser


def main(argv: list[str] | None = None) -> None:
    parser = build_parser()
    args = parser.parse_args(argv)

    seeds_dir = find_seeds_dir()
    pokedb_dir: Path = args.pokedb_dir or (seeds_dir / ".pokedb_cache")
    output_dir: Path = args.output or (seeds_dir / "data")
    output_dir.mkdir(parents=True, exist_ok=True)

    print(f"PokeDB data:  {pokedb_dir.resolve()}")
    print(f"Seeds config: {seeds_dir}")
    print(f"Output:       {output_dir.resolve()}")
    print()

    # Load PokeDB export data
    pokedb = load_pokedb_data(pokedb_dir)
    print(pokedb.summary())
    print()

    # Load existing seed configuration
    config = load_seed_config(seeds_dir)
    print(f"Loaded {len(config.version_groups)} version groups")
    print(f"Loaded route order for {len(config.route_order)} version groups")
    if config.special_encounters:
        se_count = len(config.special_encounters.get("encounters", {}))
        print(f"Loaded special encounters for {se_count} version groups")
    print()

    # Determine which games to process
    target_game = args.game
    if target_game:
        found = False
        for vg_info in config.version_groups.values():
            if target_game in vg_info.get("versions", []):
                found = True
                break
        if not found:
            print(f"Error: Game '{target_game}' not found in version_groups.json", file=sys.stderr)
            sys.exit(1)
        print(f"Target: {target_game}")
    else:
        total_games = sum(
            len(vg.get("versions", []))
            for vg in config.version_groups.values()
        )
        print(f"Target: all {total_games} games")

    # Build mappings
    print("\nBuilding mappings...")

    pokemon_json = seeds_dir / "data" / "pokemon.json"
    pokemon_mapper = PokemonMapper(pokemon_json, pokedb)

    location_mapper = LocationMapper(pokedb)

    version_map = build_version_map(pokedb, config.version_groups)
    print(f"  Mapped {len(version_map)} PokeDB versions to our game slugs")

    # Report encounter method coverage
    pokedb_methods = {e.get("encounter_method_identifier", "") for e in pokedb.encounters}
    pokedb_methods.discard("")
    mapped_methods = {m for m in pokedb_methods if map_encounter_method(m) is not None}
    unmapped_methods = pokedb_methods - mapped_methods
    print(f"  Encounter methods: {len(mapped_methods)} mapped, {len(unmapped_methods)} unmapped")
    if unmapped_methods:
        print("  Unmapped methods:", file=sys.stderr)
        for m in sorted(unmapped_methods):
            print(f"    - {m}", file=sys.stderr)

    # Spot-check pokemon mapping on actual encounter data
    form_ids_in_encounters: set[str] = set()
    for e in pokedb.encounters:
        fid = e.get("pokemon_form_identifier")
        if fid:
            form_ids_in_encounters.add(fid)
    mapped_forms = 0
    for fid in form_ids_in_encounters:
        if pokemon_mapper.lookup(fid) is not None:
            mapped_forms += 1
    total_forms = len(form_ids_in_encounters)
    print(f"  Pokemon forms: {mapped_forms}/{total_forms} mapped from encounters")

    pokemon_mapper.report_unmapped()

    # Process encounters per game
    print("\nProcessing encounters...")

    games_to_process: list[tuple[str, str, int]] = []  # (vg_key, game_slug, generation)
    for vg_key, vg_info in config.version_groups.items():
        generation = vg_info.get("generation", 0)
        for slug in vg_info.get("versions", []):
            if target_game and slug != target_game:
                continue
            games_to_process.append((vg_key, slug, generation))

    all_encountered_form_ids: set[str] = set()

    for vg_key, game_slug, generation in games_to_process:
        print(f"\n--- {game_slug} ---")

        # Filter encounters for this game
        game_encounters = filter_encounters_for_game(pokedb.encounters, game_slug)
        if not game_encounters:
            print(f"  No encounters found in PokeDB data")
            continue

        print(f"  Raw encounters: {len(game_encounters)}")

        # Track encountered form IDs for pokemon.json
        for e in game_encounters:
            fid = e.get("pokemon_form_identifier")
            if fid:
                all_encountered_form_ids.add(fid)

        # Process into grouped encounters
        encounters_by_area = process_encounters(
            game_encounters, generation, pokemon_mapper, location_mapper,
        )
        print(f"  Location areas with encounters: {len(encounters_by_area)}")

        # Build route hierarchy
        routes = build_routes(encounters_by_area, location_mapper)

        # Merge special encounters (starters, gifts, fossils)
        routes = merge_special_encounters(routes, config, vg_key, pokemon_mapper)

        # Sort routes by game progression order
        routes = sort_routes(routes, config, vg_key)

        # Stats
        total_routes = sum(1 + len(r.children) for r in routes)
        total_enc = sum(
            len(r.encounters) + sum(len(c.encounters) for c in r.children)
            for r in routes
        )
        print(f"  Routes: {total_routes}")
        print(f"  Encounter entries: {total_enc}")

        # Write per-game JSON
        write_game_json(routes, output_dir, game_slug)

    # Download sprites to frontend/public/sprites
    sprites_dir = find_sprites_dir()
    print(f"\nDownloading sprites to {sprites_dir}...")
    sprite_map = download_sprites(pokemon_mapper, all_encountered_form_ids, sprites_dir)
    print(f"  Sprite map covers {len(sprite_map)} forms")

    # Download sprites for ALL pokemon (including non-encountered evolutions etc.)
    all_sprite_ids = download_all_sprites(pokemon_mapper, sprites_dir)

    # Write global JSON files
    print("\nWriting global data files...")
    write_games_json(config, output_dir)
    write_pokemon_json(pokemon_mapper, all_encountered_form_ids, sprite_map, output_dir)

    print("\nDone!")


if __name__ == "__main__":
    main()
