"""API client for Agent Duel CLI."""

from typing import Optional

import httpx

from .config import get_api_url, get_token


class APIError(Exception):
    """Exception raised for API errors."""

    def __init__(self, message: str, status_code: Optional[int] = None):
        self.message = message
        self.status_code = status_code
        super().__init__(message)


class APIClient:
    """HTTP client for the Agent Duel API."""

    def __init__(self, token: Optional[str] = None):
        self.base_url = get_api_url()
        self.token = token or get_token()

    def _headers(self) -> dict:
        """Get request headers."""
        headers = {"Content-Type": "application/json"}
        if self.token:
            headers["Authorization"] = f"Token {self.token}"
        return headers

    def _handle_response(self, response: httpx.Response) -> dict:
        """Handle API response and raise errors if needed."""
        if response.status_code >= 400:
            try:
                data = response.json()
                message = data.get("detail") or data.get("error") or str(data)
            except Exception:
                message = f"HTTP {response.status_code}"
            raise APIError(message, response.status_code)

        if response.status_code == 204:
            return {}

        return response.json()

    def login(self, email: str, password: str) -> dict:
        """Log in and get auth token."""
        with httpx.Client() as client:
            response = client.post(
                f"{self.base_url}/auth/login",
                json={"email": email, "password": password},
                headers={"Content-Type": "application/json"},
            )
            return self._handle_response(response)

    def get_me(self) -> dict:
        """Get current user info."""
        with httpx.Client() as client:
            response = client.get(
                f"{self.base_url}/auth/me",
                headers=self._headers(),
            )
            return self._handle_response(response)

    def get_my_agent(self) -> dict:
        """Get current user's agent."""
        with httpx.Client() as client:
            response = client.get(
                f"{self.base_url}/agents/me",
                headers=self._headers(),
            )
            return self._handle_response(response)

    def create_agent(self, name: str) -> dict:
        """Create an agent."""
        with httpx.Client() as client:
            response = client.post(
                f"{self.base_url}/agents",
                json={"name": name},
                headers=self._headers(),
            )
            return self._handle_response(response)

    def get_agent_stats(self) -> dict:
        """Get agent stats."""
        with httpx.Client() as client:
            response = client.get(
                f"{self.base_url}/agents/stats",
                headers=self._headers(),
            )
            return self._handle_response(response)

    def get_my_matches(self) -> dict:
        """Get current user's matches."""
        with httpx.Client() as client:
            response = client.get(
                f"{self.base_url}/matches/mine",
                headers=self._headers(),
            )
            return self._handle_response(response)

    def get_match(self, match_id: int) -> dict:
        """Get match details."""
        with httpx.Client() as client:
            response = client.get(
                f"{self.base_url}/matches/{match_id}",
                headers=self._headers(),
            )
            return self._handle_response(response)

    # Challenge endpoints

    def list_challenges(self) -> dict:
        """List all open challenges."""
        with httpx.Client() as client:
            response = client.get(
                f"{self.base_url}/challenges",
                headers=self._headers(),
            )
            return self._handle_response(response)

    def create_challenge(self, game_type: str = "split-or-steal") -> dict:
        """Create a new open challenge."""
        with httpx.Client() as client:
            response = client.post(
                f"{self.base_url}/challenges",
                json={"game_type": game_type},
                headers=self._headers(),
            )
            return self._handle_response(response)

    def cancel_challenge(self, challenge_id: int) -> dict:
        """Cancel an open challenge."""
        with httpx.Client() as client:
            response = client.delete(
                f"{self.base_url}/challenges/{challenge_id}",
                headers=self._headers(),
            )
            return self._handle_response(response)

    def accept_challenge(self, challenge_id: int) -> dict:
        """Accept an open challenge."""
        with httpx.Client() as client:
            response = client.post(
                f"{self.base_url}/challenges/{challenge_id}/accept",
                json={},
                headers=self._headers(),
            )
            return self._handle_response(response)

    def join_challenge(self, challenge_id: int, preferred_game: Optional[str] = None) -> dict:
        """Join a challenge (accepts if open, or returns match if already accepted by us).

        Args:
            challenge_id: The challenge to join
            preferred_game: Optional game preference from agent's GAME property.
                           Used when joining "all games" challenges to pick the game.
        """
        payload = {}
        if preferred_game:
            payload["preferred_game"] = preferred_game
        with httpx.Client() as client:
            response = client.post(
                f"{self.base_url}/challenges/{challenge_id}/join",
                json=payload,
                headers=self._headers(),
            )
            return self._handle_response(response)

    def get_my_challenges(self) -> dict:
        """Get challenges posted by or accepted by current user."""
        with httpx.Client() as client:
            response = client.get(
                f"{self.base_url}/challenges/mine",
                headers=self._headers(),
            )
            return self._handle_response(response)
