from typing import Optional from fastapi import APIRouter, HTTPException import httpx from pydantic import BaseModel from config import get_settings router = APIRouter(prefix="/dispensaries", tags=["Dispensaries"]) settings = get_settings() class DispensaryQuery(BaseModel): lat: Optional[float] = None lng: Optional[float] = None city: Optional[str] = None state: Optional[str] = None radius: Optional[int] = 25 limit: Optional[int] = 20 offset: Optional[int] = 0 async def fetch_from_api(endpoint: str, params: dict = None): """Fetch data from the external dispensary API""" headers = {} if settings.dispensary_api_key: headers["X-API-Key"] = settings.dispensary_api_key async with httpx.AsyncClient() as client: try: response = await client.get( f"{settings.dispensary_api_url}{endpoint}", params=params, headers=headers, timeout=30.0 ) response.raise_for_status() return response.json() except httpx.HTTPStatusError as e: raise HTTPException( status_code=e.response.status_code, detail=f"API error: {e.response.text}" ) except httpx.RequestError as e: raise HTTPException( status_code=503, detail=f"Failed to connect to dispensary API: {str(e)}" ) @router.get("/") async def search_dispensaries( lat: Optional[float] = None, lng: Optional[float] = None, city: Optional[str] = None, state: Optional[str] = "AZ", radius: int = 25, limit: int = 20, offset: int = 0, open_now: bool = False, min_rating: Optional[float] = None ): """Search for dispensaries by location""" params = { "limit": limit, "offset": offset, "state": state } if lat and lng: params["lat"] = lat params["lng"] = lng params["radius"] = radius if city: params["city"] = city # Fetch from external API data = await fetch_from_api("/api/az/stores", params) # Apply client-side filters if needed stores = data.get("stores", []) if open_now: # Filter stores that are currently open # This would need actual business hours logic pass if min_rating: stores = [s for s in stores if (s.get("rating") or 0) >= min_rating] return { "dispensaries": stores, "total": len(stores), "limit": limit, "offset": offset } @router.get("/{dispensary_id}") async def get_dispensary(dispensary_id: int): """Get details for a specific dispensary""" data = await fetch_from_api(f"/api/az/stores/{dispensary_id}") return data @router.get("/{dispensary_id}/products") async def get_dispensary_products( dispensary_id: int, category: Optional[str] = None, search: Optional[str] = None, limit: int = 50, offset: int = 0 ): """Get products for a specific dispensary""" params = { "limit": limit, "offset": offset } if category: params["category"] = category if search: params["search"] = search data = await fetch_from_api(f"/api/az/stores/{dispensary_id}/products", params) return data @router.get("/{dispensary_id}/categories") async def get_dispensary_categories(dispensary_id: int): """Get product categories for a dispensary""" data = await fetch_from_api(f"/api/az/stores/{dispensary_id}/categories") return data @router.get("/nearby") async def get_nearby_dispensaries( lat: float, lng: float, radius: int = 10, limit: int = 10 ): """Get nearby dispensaries by coordinates""" params = { "lat": lat, "lng": lng, "radius": radius, "limit": limit } data = await fetch_from_api("/api/az/stores", params) return data.get("stores", []) @router.get("/featured") async def get_featured_dispensaries(limit: int = 6): """Get featured dispensaries for the homepage""" # For now, return top-rated dispensaries params = { "limit": limit, "sort": "rating" } data = await fetch_from_api("/api/az/stores", params) return data.get("stores", [])