"""BotManifold unified API client."""

from __future__ import annotations

import os
from typing import Any

import requests

from botmanifold.arena.client import ArenaClient
from botmanifold.verify.client import VerifyClient


class BotManifoldError(Exception):
    """Base exception for BotManifold API errors."""
    pass


class AuthenticationError(BotManifoldError):
    """Raised when API authentication fails."""
    pass


class BotManifoldClient:
    """Unified client for the BotManifold platform.

    This is the main entry point for the BotManifold SDK. Use it to:
    - Verify policy safety (primary use case)
    - Submit to arena competitions

    Example:
        >>> client = BotManifoldClient(api_key="bm_live_...")
        >>>
        >>> # Verify a policy (primary)
        >>> report = client.verify.run("my_policy.zip", scenario="messy_room")
        >>> print(f"Verdict: {report.verdict}")
        >>>
        >>> # Submit to arena (competition)
        >>> submission = client.arena.submit("my_policy.zip", scenario="messy_room")
        >>> print(f"Submitted: {submission.id}")

    Args:
        api_key: Your BotManifold API key. If not provided, reads from
            BOTMANIFOLD_API_KEY or BOTARENA_API_KEY environment variable.
        base_url: API base URL. Defaults to production API.
        timeout: Request timeout in seconds.
    """

    DEFAULT_BASE_URL = "https://api.botmanifold.com"

    def __init__(
        self,
        api_key: str | None = None,
        base_url: str | None = None,
        timeout: int = 30,
    ) -> None:
        """Initialize the client."""
        self.api_key = (
            api_key
            or os.environ.get("BOTMANIFOLD_API_KEY")
            or os.environ.get("BOTARENA_API_KEY")
        )
        self.base_url = (
            base_url
            or os.environ.get("BOTMANIFOLD_API_URL")
            or os.environ.get("BOTARENA_API_URL")
            or self.DEFAULT_BASE_URL
        ).rstrip("/")
        self.timeout = timeout

        # Get version from package metadata
        try:
            from importlib.metadata import version as get_version
            sdk_version = get_version("botmanifold")
        except Exception:
            sdk_version = "0.3.0"

        self._session = requests.Session()
        if self.api_key:
            self._session.headers["Authorization"] = f"Bearer {self.api_key}"
        self._session.headers["User-Agent"] = f"botmanifold-sdk/{sdk_version}"

        # Initialize sub-clients
        self._verify = VerifyClient(self)
        self._arena = ArenaClient(self)

    @property
    def verify(self) -> VerifyClient:
        """Access the Verify API (primary).

        Use this to verify policy safety before deployment.

        Example:
            >>> report = client.verify.run("policy.zip", scenario="messy_room")
            >>> if report.is_safe:
            ...     print("Policy is safe!")
        """
        return self._verify

    @property
    def arena(self) -> ArenaClient:
        """Access the Arena API (competition).

        Use this to submit policies to competitions and view leaderboards.

        Example:
            >>> submission = client.arena.submit("policy.zip", scenario="messy_room")
            >>> leaderboard = client.arena.leaderboard(scenario="messy_room")
        """
        return self._arena

    def _request(
        self,
        method: str,
        endpoint: str,
        **kwargs,
    ) -> dict[str, Any]:
        """Make an API request."""
        url = f"{self.base_url}{endpoint}"
        kwargs.setdefault("timeout", self.timeout)

        try:
            response = self._session.request(method, url, **kwargs)
        except requests.RequestException as e:
            raise BotManifoldError(f"Request failed: {e}") from e

        if response.status_code == 401:
            raise AuthenticationError("Invalid API key")
        if response.status_code == 403:
            raise AuthenticationError("Access denied")

        if not response.ok:
            try:
                detail = response.json().get("detail", response.text)
            except ValueError:
                detail = response.text
            raise BotManifoldError(f"API error ({response.status_code}): {detail}")

        return response.json()

    def health_check(self) -> bool:
        """Check if the API is healthy.

        Returns:
            True if API is reachable and healthy.
        """
        try:
            data = self._request("GET", "/health")
            return data.get("status") == "healthy"
        except BotManifoldError:
            return False


# Backwards compatibility alias
Client = BotManifoldClient
