# services/external/app/api/weather.py
"""
Weather API Endpoints
"""

from fastapi import APIRouter, Depends, HTTPException, Query, BackgroundTasks, Path
from typing import List, Optional, Dict, Any
from datetime import datetime, date
import structlog
from uuid import UUID

from app.schemas.weather import (
    WeatherDataResponse,
    WeatherForecastResponse,
    WeatherForecastRequest,
    HistoricalWeatherRequest,
    HourlyForecastRequest,
    HourlyForecastResponse
)
from app.services.weather_service import WeatherService
from app.services.messaging import publish_weather_updated

# Import unified authentication from shared library
from shared.auth.decorators import (
    get_current_user_dep
)

from sqlalchemy.ext.asyncio import AsyncSession
from app.core.database import get_db

router = APIRouter(tags=["weather"])
logger = structlog.get_logger()
weather_service = WeatherService()

@router.get("/tenants/{tenant_id}/weather/current", response_model=WeatherDataResponse)
async def get_current_weather(
    latitude: float = Query(..., description="Latitude"),
    longitude: float = Query(..., description="Longitude"),
    tenant_id: UUID = Path(..., description="Tenant ID"),
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
):
    """Get current weather data for location"""
    try:
        logger.debug("Getting current weather", 
                    lat=latitude, 
                    lon=longitude,
                    tenant_id=tenant_id,
                    user_id=current_user["user_id"])
        
        weather = await weather_service.get_current_weather(latitude, longitude)
        
        if not weather:
            raise HTTPException(status_code=503, detail="Weather service temporarily unavailable")
        
        # Publish event
        try:
            await publish_weather_updated({
                "type": "current_weather_requested",
                "tenant_id": tenant_id,
                "latitude": latitude,
                "longitude": longitude,
                "requested_by": current_user["user_id"],
                "timestamp": datetime.utcnow().isoformat()
            })
        except Exception as e:
            logger.warning("Failed to publish weather event", error=str(e))
        
        return weather
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error("Failed to get current weather", error=str(e))
        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")

@router.post("/tenants/{tenant_id}/weather/historical")
async def get_historical_weather(
    request: HistoricalWeatherRequest,
    db: AsyncSession = Depends(get_db),
    tenant_id: UUID = Path(..., description="Tenant ID"),
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
):
    """Get historical weather data with date range in payload"""
    try:
        # Validate date range
        if request.end_date <= request.start_date:
            raise HTTPException(status_code=400, detail="End date must be after start date")
        
        if (request.end_date - request.start_date).days > 1000:
            raise HTTPException(status_code=400, detail="Date range cannot exceed 90 days")
        
        historical_data = await weather_service.get_historical_weather(
            request.latitude, request.longitude, request.start_date, request.end_date)
        
        # Publish event (with error handling)
        try:
            await publish_weather_updated({
                "type": "historical_requested",
                "latitude": request.latitude,
                "longitude": request.longitude,
                "start_date": request.start_date.isoformat(),
                "end_date": request.end_date.isoformat(),
                "records_count": len(historical_data),
                "timestamp": datetime.utcnow().isoformat()
            })
        except Exception as pub_error:
            logger.warning("Failed to publish historical weather event", error=str(pub_error))
            # Continue processing
        
        return historical_data
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error("Unexpected error in historical weather API", error=str(e))
        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")


@router.post("/tenants/{tenant_id}/weather/forecast", response_model=List[WeatherForecastResponse])
async def get_weather_forecast(
    request: WeatherForecastRequest,
    tenant_id: UUID = Path(..., description="Tenant ID"),
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
):
    """Get weather forecast for location"""
    try:
        logger.debug("Getting weather forecast", 
                    lat=request.latitude, 
                    lon=request.longitude, 
                    days=request.days,
                    tenant_id=tenant_id)
        
        forecast = await weather_service.get_weather_forecast(request.latitude, request.longitude, request.days)
        
        # Don't return 404 for empty forecast - return empty list with 200 status
        if not forecast:
            logger.info("Weather forecast unavailable - returning empty list")
            return []
        
        # Publish event
        try:
            await publish_weather_updated({
                "type": "forecast_requested",
                "tenant_id": tenant_id,
                "latitude": request.latitude,
                "longitude": request.longitude,
                "days": request.days,
                "requested_by": current_user["user_id"],
                "timestamp": datetime.utcnow().isoformat()
            })
        except Exception as e:
            logger.warning("Failed to publish forecast event", error=str(e))
        
        return forecast
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error("Failed to get weather forecast", error=str(e))
        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")

@router.post("/tenants/{tenant_id}/weather/hourly-forecast", response_model=List[HourlyForecastResponse])
async def get_hourly_weather_forecast(
    request: HourlyForecastRequest,
    tenant_id: UUID = Path(..., description="Tenant ID"),
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
):
    """Get hourly weather forecast for location using AEMET API
    
    This endpoint provides hourly weather predictions for up to 48 hours,
    perfect for detailed bakery operations planning and weather-based recommendations.
    """
    try:
        logger.debug("Getting hourly weather forecast", 
                    lat=request.latitude, 
                    lon=request.longitude, 
                    hours=request.hours,
                    tenant_id=tenant_id)
        
        hourly_forecast = await weather_service.get_hourly_forecast(
            request.latitude, request.longitude, request.hours
        )
        
        # Don't return 404 for empty hourly forecast - return empty list with 200 status
        if not hourly_forecast:
            logger.info("Hourly weather forecast unavailable - returning empty list")
            return []
        
        # Publish event
        try:
            await publish_weather_updated({
                "type": "hourly_forecast_requested",
                "tenant_id": tenant_id,
                "latitude": request.latitude,
                "longitude": request.longitude,
                "hours": request.hours,
                "requested_by": current_user["user_id"],
                "forecast_count": len(hourly_forecast),
                "timestamp": datetime.utcnow().isoformat()
            })
        except Exception as e:
            logger.warning("Failed to publish hourly forecast event", error=str(e))
        
        return hourly_forecast
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error("Failed to get hourly weather forecast", error=str(e))
        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")

@router.get("/weather/status")
async def get_weather_status():
    """Get AEMET API status and diagnostics"""
    try:
        from app.core.config import settings
        
        # Test AEMET API connectivity
        aemet_status = "unknown"
        aemet_message = "Not tested"
        
        try:
            # Quick test of AEMET API
            test_weather = await weather_service.get_current_weather(40.4168, -3.7038)
            if test_weather and hasattr(test_weather, 'source') and test_weather.source == "aemet":
                aemet_status = "healthy"
                aemet_message = "AEMET API responding correctly"
            elif test_weather and hasattr(test_weather, 'source') and test_weather.source == "synthetic":
                aemet_status = "degraded"
                aemet_message = "AEMET API unavailable - using synthetic data"
            else:
                aemet_status = "degraded"
                aemet_message = "Weather service returned unexpected data format"
        except Exception as e:
            aemet_status = "unhealthy"
            aemet_message = f"AEMET API error: {str(e)}"
        
        return {
            "status": "ok",
            "aemet": {
                "status": aemet_status,
                "message": aemet_message,
                "api_key_configured": bool(settings.AEMET_API_KEY),
                "enabled": getattr(settings, 'AEMET_ENABLED', True),
                "base_url": settings.AEMET_BASE_URL,
                "timeout": settings.AEMET_TIMEOUT,  # Now correctly shows 60 from config
                "retry_attempts": settings.AEMET_RETRY_ATTEMPTS
            },
            "timestamp": datetime.utcnow().isoformat(),
            "service": "external-weather-service"
        }
        
    except Exception as e:
        logger.error("Failed to get weather status", error=str(e))
        raise HTTPException(status_code=500, detail=f"Status check failed: {str(e)}")
