""" Player Router - Refactored Thin HTTP layer using PlayerService for business logic. """ from fastapi import APIRouter, Query, Response, Depends from typing import Optional, List from ..dependencies import oauth2_scheme, cache_result, handle_db_errors from ..services.base import BaseService from ..services.player_service import PlayerService router = APIRouter(prefix="/api/v3/players", tags=["players"]) @router.get("") @handle_db_errors @cache_result(ttl=30 * 60, key_prefix="players") async def get_players( season: Optional[int] = None, name: Optional[str] = None, team_id: list = Query(default=None), pos: list = Query(default=None), strat_code: list = Query(default=None), is_injured: Optional[bool] = None, sort: Optional[str] = None, short_output: Optional[bool] = False, csv: Optional[bool] = False, ): """Get players with filtering and sorting.""" result = PlayerService.get_players( season=season, team_id=team_id if team_id else None, pos=pos if pos else None, strat_code=strat_code if strat_code else None, name=name, is_injured=is_injured, sort=sort, short_output=short_output or False, as_csv=csv or False ) if csv: return Response(content=result, media_type="text/csv") return result @router.get("/search") @handle_db_errors @cache_result(ttl=15 * 60, key_prefix="players-search") async def search_players( q: str = Query(..., description="Search query for player name"), season: Optional[int] = Query(default=None, description="Season to search (0 for all)"), limit: int = Query(default=10, ge=1, le=50), short_output: bool = False, ): """Search players by name with fuzzy matching.""" return PlayerService.search_players( query_str=q, season=season, limit=limit, short_output=short_output ) @router.get("/{player_id}") @handle_db_errors @cache_result(ttl=30 * 60, key_prefix="player") async def get_one_player( player_id: int, short_output: Optional[bool] = False ): """Get a single player by ID.""" return PlayerService.get_player(player_id, short_output=short_output or False) @router.put("/{player_id}") async def put_player( player_id: int, new_player: dict, token: str = Depends(oauth2_scheme) ): """Update a player (full replacement).""" return PlayerService.update_player(player_id, new_player, token) @router.patch("/{player_id}") async def patch_player( player_id: int, token: str = Depends(oauth2_scheme), name: Optional[str] = None, wara: Optional[float] = None, image: Optional[str] = None, image2: Optional[str] = None, team_id: Optional[int] = None, season: Optional[int] = None, pos_1: Optional[str] = None, pos_2: Optional[str] = None, pos_3: Optional[str] = None, pos_4: Optional[str] = None, pos_5: Optional[str] = None, pos_6: Optional[str] = None, pos_7: Optional[str] = None, pos_8: Optional[str] = None, vanity_card: Optional[str] = None, headshot: Optional[str] = None, il_return: Optional[str] = None, demotion_week: Optional[int] = None, strat_code: Optional[str] = None, bbref_id: Optional[str] = None, injury_rating: Optional[str] = None, sbaref_id: Optional[int] = None, ): """Patch a player (partial update).""" # Build dict of provided fields data = {} locals_dict = locals() for key, value in locals_dict.items(): if key not in ('player_id', 'token') and value is not None: data[key] = value return PlayerService.patch_player(player_id, data, token) @router.post("") async def post_players( p_list: dict, token: str = Depends(oauth2_scheme) ): """Create multiple players.""" return PlayerService.create_players(p_list.get("players", []), token) @router.delete("/{player_id}") async def delete_player( player_id: int, token: str = Depends(oauth2_scheme) ): """Delete a player.""" return PlayerService.delete_player(player_id, token)