"""Export endpoints that return data in seed JSON format.""" from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload from app.core.database import get_session from app.models.evolution import Evolution from app.models.game import Game from app.models.pokemon import Pokemon from app.models.route import Route from app.models.route_encounter import RouteEncounter router = APIRouter() @router.get("/games") async def export_games(session: AsyncSession = Depends(get_session)): """Export all games in seed JSON format.""" result = await session.execute( select(Game).order_by(Game.name) ) games = result.scalars().all() return [ { "name": g.name, "slug": g.slug, "generation": g.generation, "region": g.region, "release_year": g.release_year, "color": g.color, } for g in games ] @router.get("/games/{game_id}/routes") async def export_game_routes( game_id: int, session: AsyncSession = Depends(get_session), ): """Export routes and encounters for a game in seed JSON format.""" # Verify game exists game = await session.get(Game, game_id) if not game: raise HTTPException(status_code=404, detail="Game not found") # Load all routes for this game with encounters and pokemon result = await session.execute( select(Route) .where(Route.game_id == game_id) .options( selectinload(Route.route_encounters).selectinload(RouteEncounter.pokemon), ) .order_by(Route.order) ) routes = result.scalars().all() # Build parent-child mapping parent_routes = [r for r in routes if r.parent_route_id is None] children_by_parent: dict[int, list[Route]] = {} for r in routes: if r.parent_route_id is not None: children_by_parent.setdefault(r.parent_route_id, []).append(r) def format_encounters(route: Route) -> list[dict]: return [ { "pokeapi_id": enc.pokemon.pokeapi_id, "pokemon_name": enc.pokemon.name, "method": enc.encounter_method, "encounter_rate": enc.encounter_rate, "min_level": enc.min_level, "max_level": enc.max_level, } for enc in sorted(route.route_encounters, key=lambda e: -e.encounter_rate) ] def format_route(route: Route) -> dict: data: dict = { "name": route.name, "order": route.order, "encounters": format_encounters(route), } children = children_by_parent.get(route.id, []) if children: data["children"] = [ format_child(c) for c in sorted(children, key=lambda r: r.order) ] return data def format_child(route: Route) -> dict: data: dict = { "name": route.name, "order": route.order, "encounters": format_encounters(route), } if route.pinwheel_zone is not None: data["pinwheel_zone"] = route.pinwheel_zone return data return { "filename": f"{game.slug}.json", "data": [format_route(r) for r in parent_routes], } @router.get("/pokemon") async def export_pokemon(session: AsyncSession = Depends(get_session)): """Export all pokemon in seed JSON format.""" result = await session.execute( select(Pokemon).order_by(Pokemon.pokeapi_id) ) pokemon_list = result.scalars().all() return [ { "pokeapi_id": p.pokeapi_id, "national_dex": p.national_dex, "name": p.name, "types": p.types, "sprite_url": p.sprite_url, } for p in pokemon_list ] @router.get("/evolutions") async def export_evolutions(session: AsyncSession = Depends(get_session)): """Export all evolutions in seed JSON format.""" result = await session.execute( select(Evolution) .options( selectinload(Evolution.from_pokemon), selectinload(Evolution.to_pokemon), ) .order_by(Evolution.id) ) evolutions = result.scalars().all() return [ { "from_pokeapi_id": e.from_pokemon.pokeapi_id, "to_pokeapi_id": e.to_pokemon.pokeapi_id, "trigger": e.trigger, "min_level": e.min_level, "item": e.item, "held_item": e.held_item, "condition": e.condition, "region": e.region, } for e in evolutions ]