from fastapi import APIRouter, Depends, Query, HTTPException import asyncpg from ..dependencies import get_db, get_cache # DropdownService deprecated; using normalized schema service from ..services.vehicles_service import VehiclesService from ..repositories.vehicles_repository import VehiclesRepository from ..services.cache_service import CacheService from ..models.responses import ( MakesResponse, ModelsResponse, TrimsResponse, EnginesResponse, MakeItem, ModelItem, TrimItem, EngineItem ) import logging logger = logging.getLogger(__name__) router = APIRouter(prefix="/vehicles", tags=["Vehicles"]) @router.get("/years", response_model=list[int]) async def get_years( db: asyncpg.Connection = Depends(get_db), cache: CacheService = Depends(get_cache), ): """Get available model years (distinct, desc)""" service = VehiclesService(cache, VehiclesRepository()) return await service.get_years(db) @router.get("/makes", response_model=MakesResponse) async def get_makes( year: int = Query(..., description="Model year", ge=1980, le=2050), db: asyncpg.Connection = Depends(get_db), cache: CacheService = Depends(get_cache) ): """Get makes for a specific year Hierarchical API: First level - requires year parameter only """ try: service = VehiclesService(cache, VehiclesRepository()) makes = await service.get_makes(db, year) return MakesResponse(makes=[MakeItem(**m) for m in makes]) except Exception as e: logger.error(f"Failed to get makes for year {year}: {e}") raise HTTPException( status_code=500, detail=f"Failed to retrieve makes for year {year}" ) @router.get("/models", response_model=ModelsResponse) async def get_models( year: int = Query(..., description="Model year", ge=1980, le=2050), make_id: int = Query(..., description="Make ID", ge=1), db: asyncpg.Connection = Depends(get_db), cache: CacheService = Depends(get_cache) ): """Get models for year and make Hierarchical API: Second level - requires year and make_id parameters """ try: service = VehiclesService(cache, VehiclesRepository()) models = await service.get_models(db, year, make_id) return ModelsResponse(models=[ModelItem(**m) for m in models]) except Exception as e: logger.error(f"Failed to get models for year {year}, make {make_id}: {e}") raise HTTPException( status_code=500, detail=f"Failed to retrieve models for year {year}, make {make_id}" ) @router.get("/trims", response_model=TrimsResponse) async def get_trims( year: int = Query(..., description="Model year", ge=1980, le=2050), make_id: int = Query(..., description="Make ID", ge=1), model_id: int = Query(..., description="Model ID", ge=1), db: asyncpg.Connection = Depends(get_db), cache: CacheService = Depends(get_cache) ): """Get trims for year, make, and model Hierarchical API: Third level - requires year, make_id, and model_id parameters """ try: service = VehiclesService(cache, VehiclesRepository()) trims = await service.get_trims(db, year, model_id) return TrimsResponse(trims=[TrimItem(**t) for t in trims]) except Exception as e: logger.error(f"Failed to get trims for year {year}, make {make_id}, model {model_id}: {e}") raise HTTPException( status_code=500, detail=f"Failed to retrieve trims for year {year}, make {make_id}, model {model_id}" ) @router.get("/engines", response_model=EnginesResponse) async def get_engines( year: int = Query(..., description="Model year", ge=1980, le=2050), make_id: int = Query(..., description="Make ID", ge=1), model_id: int = Query(..., description="Model ID", ge=1), trim_id: int = Query(..., description="Trim ID", ge=1), db: asyncpg.Connection = Depends(get_db), cache: CacheService = Depends(get_cache) ): """Get engines for year, make, model, and trim""" try: service = VehiclesService(cache, VehiclesRepository()) engines = await service.get_engines(db, year, model_id, trim_id) return EnginesResponse(engines=[EngineItem(**e) for e in engines]) except Exception as e: logger.error( f"Failed to get engines for year {year}, make {make_id}, model {model_id}, trim {trim_id}: {e}" ) raise HTTPException( status_code=500, detail=( f"Failed to retrieve engines for year {year}, make {make_id}, model {model_id}, trim {trim_id}" ) )