"""Time series service for Edge API SDK."""

from typing import Optional, List, Dict, Any, Union
from datetime import date, datetime
import pandas as pd
from edge.exceptions import InvalidParameterError


class TimeSeriesService:
    """Service for accessing time series data."""

    def __init__(self, client):
        """Initialize with parent client."""
        self.client = client

    def get_metadata(
        self,
        series_code: Optional[str] = None,
        source_name: Optional[str] = None,
        theme_name: Optional[str] = None,
        commodity_code: Optional[str] = None,
        region_code: Optional[str] = None,
        limit: int = 50,
    ) -> pd.DataFrame:
        """
        Get time series metadata based on various filters.

        Args:
            series_code: Specific series code to filter by
            source_name: Data source name to filter by
            theme_name: Theme name to filter by (e.g., 'PRICE', 'PRODUCTION')
            commodity_code: Commodity code to filter by
            region_code: Region code to filter by
            limit: Maximum results to return

        Returns:
            DataFrame with series metadata
        """
        params = {"limit": limit}
        if series_code:
            params["series_code"] = series_code
        if source_name:
            params["source_name"] = source_name
        if theme_name:
            params["theme_name"] = theme_name
        if commodity_code:
            params["commodity_code"] = commodity_code
        if region_code:
            params["region_code"] = region_code

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

    def get_data(
        self,
        series_code: str,
        source_name: str,
        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 from a specific source.

        Args:
            series_code: The series code to retrieve
            source_name: The data source name
            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
        """
        params = {"source_name": source_name}
        if start_date:
            params["start_date"] = self.client._format_date(start_date)
        if end_date:
            params["end_date"] = self.client._format_date(end_date)
        if limit:
            params["limit"] = limit

        response = self.client._get(f"/data/series/{series_code}/data", params=params)

        # Extract data points from response
        if "data" in response:
            df = self.client._to_dataframe(response["data"])
            if not df.empty:
                df["series_code"] = series_code
                df["source_name"] = source_name
            return df
        return pd.DataFrame()

    def get_multiple(
        self,
        series_configs: List[Dict[str, str]],
        start_date: Optional[Union[str, date, datetime]] = None,
        end_date: Optional[Union[str, date, datetime]] = None,
        limit: Optional[int] = None,
    ) -> pd.DataFrame:
        """
        Get multiple time series and combine them into a single DataFrame.

        Args:
            series_configs: List of dicts with 'series_code' and 'source_name'
            start_date: Start date for all series
            end_date: End date for all series
            limit: Maximum records per series

        Returns:
            Combined DataFrame with all series
        """
        payload = {
            "series": series_configs,
        }
        if start_date:
            payload["start_date"] = self.client._format_date(start_date)
        if end_date:
            payload["end_date"] = self.client._format_date(end_date)
        if limit:
            payload["limit"] = limit

        responses = self.client._post("/data/series/multiple", json=payload)

        # Combine all series data
        all_data = []
        for response in responses:
            if "data" in response:
                series_df = self.client._to_dataframe(response["data"])
                if not series_df.empty:
                    series_df["series_code"] = response.get("series_code")
                    series_df["source_name"] = response.get("source_name")
                    all_data.append(series_df)

        if all_data:
            return pd.concat(all_data, ignore_index=True)
        return pd.DataFrame()

    def search(
        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.client._get("/data/series/search", params=params)
        return self.client._to_dataframe(data)