# ================================================================ # services/data/app/api/weather.py # ================================================================ """Weather data API endpoints""" from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.ext.asyncio import AsyncSession from typing import List, Optional from datetime import datetime, timedelta from app.core.database import get_db from app.core.auth import verify_token from app.services.weather_service import WeatherService from app.services.messaging import data_publisher from app.schemas.external import ( WeatherDataResponse, WeatherForecastResponse, LocationRequest, DateRangeRequest ) router = APIRouter() weather_service = WeatherService() @router.get("/current", response_model=WeatherDataResponse) async def get_current_weather( latitude: float = Query(..., description="Latitude"), longitude: float = Query(..., description="Longitude"), current_user: dict = Depends(verify_token) ): """Get current weather for location""" try: weather = await weather_service.get_current_weather(latitude, longitude) if not weather: raise HTTPException(status_code=404, detail="Weather data not available") return weather except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/forecast", response_model=List[WeatherForecastResponse]) async def get_weather_forecast( latitude: float = Query(..., description="Latitude"), longitude: float = Query(..., description="Longitude"), days: int = Query(7, description="Number of forecast days", ge=1, le=14), current_user: dict = Depends(verify_token) ): """Get weather forecast for location""" try: forecast = await weather_service.get_weather_forecast(latitude, longitude, days) # Publish event await data_publisher.publish_weather_updated({ "type": "forecast_requested", "latitude": latitude, "longitude": longitude, "days": days, "timestamp": datetime.utcnow().isoformat() }) return forecast except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/historical", response_model=List[WeatherDataResponse]) async def get_historical_weather( latitude: float = Query(..., description="Latitude"), longitude: float = Query(..., description="Longitude"), start_date: datetime = Query(..., description="Start date"), end_date: datetime = Query(..., description="End date"), db: AsyncSession = Depends(get_db), current_user: dict = Depends(verify_token) ): """Get historical weather data""" try: # Validate date range if end_date <= start_date: raise HTTPException(status_code=400, detail="End date must be after start date") if (end_date - start_date).days > 365: raise HTTPException(status_code=400, detail="Date range cannot exceed 365 days") historical_data = await weather_service.get_historical_weather( latitude, longitude, start_date, end_date, db ) # Publish event await data_publisher.publish_weather_updated({ "type": "historical_requested", "latitude": latitude, "longitude": longitude, "start_date": start_date.isoformat(), "end_date": end_date.isoformat(), "records_count": len(historical_data), "timestamp": datetime.utcnow().isoformat() }) return historical_data except Exception as e: raise HTTPException(status_code=500, detail=str(e))