""" Card search router for MTG card database. Provides endpoints for searching and retrieving MTG card data from the MTG PostgreSQL database with Redis caching. """ from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.ext.asyncio import AsyncSession from app.core.database import mtg_get_db from app.core.redis_client import cache_get, cache_set from app.services.card_database import ( search_cards, get_card_by_name, get_cards_by_set, get_card_types, get_card_rarities, get_sets, get_set_by_code, get_card_statistics, ) router = APIRouter(prefix="/mtg/cards", tags=["MTG Cards"]) @router.get("/search") async def search_cards_endpoint( q: str = Query(..., min_length=1, description="Search query"), limit: int = Query(100, ge=1, le=500, description="Maximum results"), offset: int = Query(0, ge=0, description="Number of results to skip"), db: AsyncSession = Depends(mtg_get_db), ): """ Search cards by name, type, or mana cost. Uses Redis cache to improve performance for repeated searches. """ cache_key = f"card_search:{q}:{limit}:{offset}" # Check cache first cached = await cache_get(cache_key) if cached: return {"cached": True, "results": cached} # Query database results = await search_cards(q, db, limit, offset) # Cache results for 5 minutes await cache_set(cache_key, str(results), ttl=300) return {"cached": False, "results": results} @router.get("/{card_name}") async def get_card_endpoint( card_name: str, set_code: str | None = Query(None, description="Filter by set code"), db: AsyncSession = Depends(mtg_get_db), ): """ Get a specific card by name. Optional set_code filter to get a specific printing. """ cache_key = f"card_by_name:{card_name}:{set_code or 'all'}" cached = await cache_get(cache_key) if cached: return {"cached": True, "results": cached} card = await get_card_by_name(card_name, db, set_code) if not card: raise HTTPException(status_code=404, detail="Card not found") # Cache for 10 minutes await cache_set(cache_key, str(card), ttl=600) return {"cached": False, "results": card} @router.get("/set/{set_code}") async def get_cards_by_set_endpoint( set_code: str, limit: int = Query(1000, ge=1, le=5000, description="Maximum results"), offset: int = Query(0, ge=0, description="Number of results to skip"), db: AsyncSession = Depends(mtg_get_db), ): """ Get all cards in a specific set. """ cache_key = f"set_cards:{set_code}:{limit}:{offset}" cached = await cache_get(cache_key) if cached: return {"cached": True, "results": cached} results = await get_cards_by_set(set_code, db, limit, offset) # Cache for 15 minutes await cache_set(cache_key, str(results), ttl=900) return {"cached": False, "results": results} @router.get("/types") async def get_card_types_endpoint( db: AsyncSession = Depends(mtg_get_db), ): """ Get all unique card types. """ cache_key = "card_types:all" cached = await cache_get(cache_key) if cached: return {"cached": True, "results": cached} types = await get_card_types(db) # Cache for 30 minutes await cache_set(cache_key, str(types), ttl=1800) return {"cached": False, "results": types} @router.get("/rarities") async def get_card_rarities_endpoint( db: AsyncSession = Depends(mtg_get_db), ): """ Get all unique card rarities. """ cache_key = "card_rarities:all" cached = await cache_get(cache_key) if cached: return {"cached": True, "results": cached} rarities = await get_card_rarities(db) # Cache for 30 minutes await cache_set(cache_key, str(rarities), ttl=1800) return {"cached": False, "results": rarities} @router.get("/sets") async def get_sets_endpoint( db: AsyncSession = Depends(mtg_get_db), ): """ Get all sets. """ cache_key = "all_sets:all" cached = await cache_get(cache_key) if cached: return {"cached": True, "results": cached} sets = await get_sets(db) # Cache for 1 hour await cache_set(cache_key, str(sets), ttl=3600) return {"cached": False, "results": sets} @router.get("/sets/{set_code}") async def get_set_endpoint( set_code: str, db: AsyncSession = Depends(mtg_get_db), ): """ Get a specific set by code. """ cache_key = f"set_by_code:{set_code}" cached = await cache_get(cache_key) if cached: return {"cached": True, "results": cached} mtg_set = await get_set_by_code(set_code, db) if not mtg_set: raise HTTPException(status_code=404, detail="Set not found") # Cache for 1 hour await cache_set(cache_key, str(mtg_set), ttl=3600) return {"cached": False, "results": mtg_set} @router.get("/statistics") async def get_card_statistics_endpoint( db: AsyncSession = Depends(mtg_get_db), ): """ Get overall card database statistics. """ cache_key = "card_statistics:all" cached = await cache_get(cache_key) if cached: return {"cached": True, "results": cached} stats = await get_card_statistics(db) # Cache for 1 hour await cache_set(cache_key, str(stats), ttl=3600) return {"cached": False, "results": stats}