"""Main Edge API Client."""

from typing import Optional, List, Dict, Any, Union
from datetime import date, datetime
import pandas as pd

from edge.config import EdgeAPIConfig
from edge.client.base import BaseClient
from edge.services.time_series import TimeSeriesService
from edge.services.usda import USDAService
from edge.services.cme import CMEService


class Edge(BaseClient):
    """Main client for accessing Edge API data."""

    def __init__(
        self,
        base_url: Optional[str] = None,
        api_key: Optional[str] = None,
        environment: str = "production",
        timeout: int = 30,
    ):
        """
        Initialize the Edge API client.

        Args:
            base_url: Base URL for the API (defaults to EDGE_API_BASE_URL env var)
            api_key: API key for authentication (defaults to EDGE_API_KEY env var)
            environment: Environment name (production, staging, development)
            timeout: Request timeout in seconds
        """
        config = EdgeAPIConfig(
            base_url=base_url,
            api_key=api_key,
            environment=environment,
            timeout=timeout,
        )

        # Validate API key is present
        if not config.api_key:
            raise ValueError(
                "API key is required. Please provide an API key via the 'api_key' "
                "parameter or set the EDGE_API_KEY environment variable."
            )

        super().__init__(config)

        # Initialize services
        self.time_series = TimeSeriesService(self)
        self.usda = USDAService(self)
        self.cme = CMEService(self)

    def health_check(self) -> Dict[str, Any]:
        """Check API health status."""
        return self._get("/data/health")

    def list_sources(self) -> pd.DataFrame:
        """List all available data sources."""
        data = self._get("/data/sources")
        return self._to_dataframe(data)

    def list_commodities(
        self,
        category: Optional[str] = None,
        is_active: bool = True,
    ) -> pd.DataFrame:
        """
        List available commodities.

        Args:
            category: Filter by category name
            is_active: Filter by active status

        Returns:
            DataFrame with commodity information
        """
        params = {"is_active": is_active}
        if category:
            params["category"] = category

        data = self._get("/data/commodities", params=params)
        return self._to_dataframe(data)

    def list_regions(
        self,
        region_type: Optional[str] = None,
        country_code: Optional[str] = None,
    ) -> pd.DataFrame:
        """
        List available geographic regions.

        Args:
            region_type: Filter by region type (COUNTRY, STATE, etc.)
            country_code: Filter by country code

        Returns:
            DataFrame with region information
        """
        params = {}
        if region_type:
            params["region_type"] = region_type
        if country_code:
            params["country_code"] = country_code

        data = self._get("/data/regions", params=params)
        return self._to_dataframe(data)

    def list_themes(self) -> pd.DataFrame:
        """List available time series themes."""
        data = self._get("/data/themes")
        return self._to_dataframe(data)

    def search_series(
        self,
        search_term: str,
        source_name: Optional[str] = None,
        limit: int = 50,
    ) -> pd.DataFrame:
        """
        Search for time series by description or code.

        Args:
            search_term: Term to search for
            source_name: Optional source filter
            limit: Maximum results to return

        Returns:
            DataFrame with matching series metadata
        """
        params = {"search_term": search_term, "limit": limit}
        if source_name:
            params["source_name"] = source_name

        data = self._get("/data/series/search", params=params)
        return self._to_dataframe(data)

    def get_series(
        self,
        series_code: str,
        source_name: str = "USDA",
        start_date: Optional[Union[str, date, datetime]] = None,
        end_date: Optional[Union[str, date, datetime]] = None,
        limit: Optional[int] = None,
    ) -> pd.DataFrame:
        """
        Get time series data for a specific series (convenience method).

        Args:
            series_code: The series code to retrieve
            source_name: The data source name (default: USDA)
            start_date: Start date for filtering
            end_date: End date for filtering
            limit: Maximum number of records to return

        Returns:
            DataFrame with time series data
        """
        return self.time_series.get_data(
            series_code=series_code,
            source_name=source_name,
            start_date=start_date,
            end_date=end_date,
            limit=limit,
        )