"""HTTP client for fetching datasets from remote API."""

import time
import logging
from typing import Dict, Any, List
import requests

logger = logging.getLogger(__name__)


class DatasetHTTPClient:
    """HTTP client for fetching evaluation datasets from Klira API."""

    def __init__(
        self,
        api_key: str,
        api_url: str = "https://api.getklira.com/v1/evals/datasets",
        timeout: int = 10,
        retries: int = 3,
    ):
        """
        Initialize HTTP client.

        Args:
            api_key: Klira API key (must start with 'klira_')
            api_url: Base API URL (default: https://api.getklira.com/v1/evals/datasets)
            timeout: Request timeout in seconds
            retries: Number of retry attempts on failure
        """
        if not api_key or not api_key.startswith("klira_"):
            raise ValueError("Invalid API key - must start with 'klira_'")

        self.api_url = api_url
        self.timeout = timeout
        self.retries = retries
        self.headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        }

    def fetch_dataset_items(self, dataset_id: str) -> List[Dict[str, Any]]:
        """
        Fetch items for a specific dataset.

        GET {api_url}/{dataset_id}
        Returns list of item dicts with messages, metadata, etc.

        Args:
            dataset_id: The dataset ID to fetch

        Returns:
            List of dataset item dicts

        Raises:
            requests.RequestException: On HTTP errors
            ValueError: On invalid response format
        """
        url = f"{self.api_url}/{dataset_id}"

        for attempt in range(self.retries):
            try:
                logger.info(
                    f"Fetching dataset {dataset_id} from {url} "
                    f"(attempt {attempt + 1}/{self.retries})"
                )

                response = requests.get(
                    url, headers=self.headers, timeout=self.timeout
                )
                response.raise_for_status()

                data = response.json()

                # Validate response format
                self._validate_response(data)

                items = data["items"]
                logger.info(
                    f"Successfully fetched dataset {dataset_id} "
                    f"(items: {len(items)})"
                )

                return items

            except requests.RequestException as e:
                logger.warning(
                    f"Dataset fetch attempt {attempt + 1} failed: {e}"
                )

                if attempt < self.retries - 1:
                    # Exponential backoff: 1s, 2s, 4s
                    sleep_time = 2**attempt
                    logger.info(f"Retrying in {sleep_time}s...")
                    time.sleep(sleep_time)
                else:
                    # Final attempt failed
                    logger.error(
                        f"Failed to fetch dataset after {self.retries} attempts"
                    )
                    raise

        # This line is unreachable but added for mypy
        raise RuntimeError(
            "Failed to fetch dataset after all retries"
        )  # pragma: no cover

    def _validate_response(self, data: Dict[str, Any]) -> None:
        """
        Validate API response format.

        Expected format:
        {
            "dataset": {"id": "...", "status": "ready", ...},
            "items": [...],
            "fetched_at": "..."
        }
        """
        if not isinstance(data, dict):
            raise ValueError(f"Expected dict response, got {type(data)}")

        if "items" not in data:
            raise ValueError("Response missing 'items' field")

        if not isinstance(data["items"], list):
            raise ValueError(
                f"Expected 'items' to be list, got {type(data['items'])}"
            )

        # Validate dataset status if present
        dataset_info = data.get("dataset", {})
        if dataset_info and dataset_info.get("status") != "ready":
            status = dataset_info.get("status", "unknown")
            raise ValueError(
                f"Dataset is not ready (status: {status}). "
                "Wait for dataset processing to complete."
            )
