"""Base client class for Edge API SDK."""

from typing import Optional, Dict, Any, List
import httpx
from datetime import date, datetime
import pandas as pd
from edge.config import EdgeAPIConfig
from edge.exceptions import EdgeAPIError, AuthenticationError, DataNotFoundError


class BaseClient:
    """Base client for making API requests."""

    def __init__(self, config: EdgeAPIConfig):
        """Initialize the base client."""
        self.config = config
        self.client = httpx.Client(
            base_url=config.api_url,
            headers=config.headers,
            timeout=config.timeout,
        )

    def __enter__(self):
        """Context manager entry."""
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Context manager exit."""
        self.close()

    def close(self):
        """Close the HTTP client."""
        self.client.close()

    def _handle_response(self, response: httpx.Response) -> Any:
        """Handle API response and raise appropriate exceptions."""
        if response.status_code == 200:
            return response.json()
        elif response.status_code == 401:
            raise AuthenticationError("Invalid or missing API key")
        elif response.status_code == 404:
            error_data = response.json() if response.content else {}
            raise DataNotFoundError(error_data.get("error", "Resource not found"))
        elif response.status_code >= 400:
            error_data = response.json() if response.content else {}
            raise EdgeAPIError(f"API error: {error_data.get('error', response.text)}")
        else:
            response.raise_for_status()

    def _get(self, endpoint: str, params: Optional[Dict] = None) -> Any:
        """Make a GET request."""
        response = self.client.get(endpoint, params=params)
        return self._handle_response(response)

    def _post(self, endpoint: str, json: Optional[Dict] = None) -> Any:
        """Make a POST request."""
        response = self.client.post(endpoint, json=json)
        return self._handle_response(response)

    @staticmethod
    def _to_dataframe(data: List[Dict]) -> pd.DataFrame:
        """Convert API response to pandas DataFrame."""
        if not data:
            return pd.DataFrame()
        df = pd.DataFrame(data)

        # Convert date columns
        date_columns = ['observation_date', 'data_start_date', 'data_end_date', 'start_date', 'end_date']
        for col in date_columns:
            if col in df.columns:
                df[col] = pd.to_datetime(df[col])

        return df

    @staticmethod
    def _format_date(date_value: Any) -> Optional[str]:
        """Format date to ISO string for API requests."""
        if date_value is None:
            return None
        if isinstance(date_value, str):
            return date_value
        if isinstance(date_value, (datetime, date)):
            return date_value.isoformat()
        return str(date_value)