# shared/clients/external_client.py
"""
External Service Client
Handles all API calls to the external service (weather and traffic data)
"""

import httpx
import structlog
from typing import Dict, Any, Optional, List
from .base_service_client import BaseServiceClient
from shared.config.base import BaseServiceSettings

logger = structlog.get_logger()


class ExternalServiceClient(BaseServiceClient):
    """Client for communicating with the external service"""
    
    def __init__(self, config: BaseServiceSettings, calling_service_name: str = "unknown"):
        super().__init__(calling_service_name, config)
        self.service_url = config.EXTERNAL_SERVICE_URL
    
    def get_service_base_path(self) -> str:
        return "/api/v1"
    
    # ================================================================
    # WEATHER DATA
    # ================================================================
    
    async def get_weather_historical(
        self,
        tenant_id: str,
        start_date: str,
        end_date: str,
        latitude: Optional[float] = None,
        longitude: Optional[float] = None
    ) -> Optional[List[Dict[str, Any]]]:
        """
        Get weather data for a date range and location
        Uses POST request as per original implementation
        """
        # Prepare request payload with proper date handling
        payload = {
            "start_date": start_date,  # Already in ISO format from calling code
            "end_date": end_date,      # Already in ISO format from calling code
            "latitude": latitude or 40.4168,  # Default Madrid coordinates
            "longitude": longitude or -3.7038
        }
        
        logger.info(f"Weather request payload: {payload}", tenant_id=tenant_id)
        
        # Use POST request with extended timeout
        result = await self._make_request(
            "POST",
            "weather/historical",
            tenant_id=tenant_id,
            data=payload,
            timeout=2000.0  # Match original timeout
        )
        
        if result:
            logger.info(f"Successfully fetched {len(result)} weather records")
            return result
        else:
            logger.error("Failed to fetch weather data")
            return []
        
    async def get_weather_forecast(
        self,
        tenant_id: str,
        days: int = 1,
        latitude: Optional[float] = None,
        longitude: Optional[float] = None
    ) -> Optional[List[Dict[str, Any]]]:
        """
        Get weather forecast for location
        FIXED: Uses GET request with query parameters as expected by the weather API
        """
        payload = {
            "latitude": latitude or 40.4168,  # Default Madrid coordinates
            "longitude": longitude or -3.7038,
            "days": days
        }
        
        logger.info(f"Weather forecast request params: {payload}", tenant_id=tenant_id)
        
        result = await self._make_request(
            "POST",
            "weather/forecast",
            tenant_id=tenant_id,
            data=payload,
            timeout=200.0
        )
        
        if result:
            logger.info(f"Successfully fetched weather forecast for {days} days")
            return result
        else:
            logger.error("Failed to fetch weather forecast")
            return []

    
    # ================================================================
    # TRAFFIC DATA  
    # ================================================================
    
    async def get_traffic_data(
        self,
        tenant_id: str,
        start_date: str,
        end_date: str,
        latitude: Optional[float] = None,
        longitude: Optional[float] = None
    ) -> Optional[List[Dict[str, Any]]]:
        """
        Get traffic data for a date range and location
        Uses POST request with extended timeout for Madrid traffic data processing
        """
        # Prepare request payload
        payload = {
            "start_date": start_date,  # Already in ISO format from calling code
            "end_date": end_date,      # Already in ISO format from calling code
            "latitude": latitude or 40.4168,  # Default Madrid coordinates
            "longitude": longitude or -3.7038
        }
        
        logger.info(f"Traffic request payload: {payload}", tenant_id=tenant_id)
        
        # Madrid traffic data can take 5-10 minutes to download and process
        traffic_timeout = httpx.Timeout(
            connect=30.0,    # Connection timeout
            read=600.0,      # Read timeout: 10 minutes (was 30s)
            write=30.0,      # Write timeout
            pool=30.0        # Pool timeout
        )
        
        # Use POST request with extended timeout
        logger.info("Making traffic data request", 
                   url="traffic/historical", 
                   tenant_id=tenant_id, 
                   timeout=traffic_timeout.read)
        
        result = await self._make_request(
            "POST",
            "traffic/historical", 
            tenant_id=tenant_id,
            data=payload,
            timeout=traffic_timeout
        )
        
        if result:
            logger.info(f"Successfully fetched {len(result)} traffic records")
            return result
        else:
            logger.error("Failed to fetch traffic data - _make_request returned None")
            logger.error("This could be due to: network timeout, HTTP error, authentication failure, or service unavailable")
            return None
    
    async def get_stored_traffic_data_for_training(
        self,
        tenant_id: str,
        start_date: str,
        end_date: str,
        latitude: Optional[float] = None,
        longitude: Optional[float] = None
    ) -> Optional[List[Dict[str, Any]]]:
        """
        Get stored traffic data specifically for model training/re-training
        This method prioritizes database-stored data over API calls
        """
        # Prepare request payload
        payload = {
            "start_date": start_date,
            "end_date": end_date,
            "latitude": latitude or 40.4168,  # Default Madrid coordinates
            "longitude": longitude or -3.7038,
            "stored_only": True  # Flag to indicate we want stored data only
        }
        
        logger.info(f"Training traffic data request: {payload}", tenant_id=tenant_id)
        
        # Standard timeout since we're only querying the database
        training_timeout = httpx.Timeout(
            connect=30.0,
            read=120.0,  # 2 minutes should be enough for database query
            write=30.0,
            pool=30.0
        )
        
        result = await self._make_request(
            "POST",
            "traffic/stored",  # New endpoint for stored traffic data
            tenant_id=tenant_id,
            data=payload,
            timeout=training_timeout
        )
        
        if result:
            logger.info(f"Successfully retrieved {len(result)} stored traffic records for training")
            return result
        else:
            logger.warning("No stored traffic data available for training")
            return None