"""HTTP client for making requests to the Worqhat API."""

import os
from typing import Optional, Dict, Any, Union
import requests

from .exceptions import APIError, AuthenticationError, NotFoundError, RateLimitError


class HTTPClient:
    """HTTP client for the Worqhat API."""

    def __init__(
        self,
        api_key: Optional[str] = None,
        base_url: str = "https://api.worqhat.app",
        target: Optional[str] = None,
        timeout: int = 60,
    ):
        """
        Initialize the HTTP client.

        Args:
            api_key: API key for authentication. Defaults to WORQHAT_API_KEY environment variable.
            base_url: Base URL for the API.
            target: Backend target ('app' or 'fyi').
            timeout: Request timeout in seconds.
        """
        self.api_key = api_key or os.environ.get("WORQHAT_API_KEY")
        if not self.api_key:
            raise AuthenticationError(
                "API key is required. Provide it via api_key parameter or WORQHAT_API_KEY environment variable."
            )

        self.base_url = base_url.rstrip("/")
        self.target = target
        self.timeout = timeout
        self.session = requests.Session()

        # Set default headers
        self.session.headers.update(
            {
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json",
            }
        )

        # Add target header if specified
        if self.target:
            self.session.headers["x-worqhat-target"] = self.target

    def _handle_error(self, response: requests.Response) -> None:
        """Handle error responses from the API."""
        try:
            error_data = response.json()
            error_message = error_data.get("message", response.text)
            error_code = response.status_code
        except ValueError:
            error_message = response.text
            error_code = response.status_code

        if response.status_code == 401:
            raise AuthenticationError(error_message, code=error_code)
        elif response.status_code == 404:
            raise NotFoundError(error_message, code=error_code)
        elif response.status_code == 429:
            raise RateLimitError(error_message, code=error_code)
        else:
            raise APIError(error_message, code=error_code)

    def get(self, path: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """
        Make a GET request.

        Args:
            path: API endpoint path.
            params: Query parameters.

        Returns:
            Response data as a dictionary.
        """
        url = f"{self.base_url}{path}"
        response = self.session.get(url, params=params, timeout=self.timeout)

        if not response.ok:
            self._handle_error(response)

        return response.json()

    def post(
        self,
        path: str,
        json: Optional[Dict[str, Any]] = None,
        data: Optional[Any] = None,
        files: Optional[Dict[str, Any]] = None,
    ) -> Dict[str, Any]:
        """
        Make a POST request.

        Args:
            path: API endpoint path.
            json: JSON data to send.
            data: Form data to send.
            files: Files to upload.

        Returns:
            Response data as a dictionary.
        """
        url = f"{self.base_url}{path}"

        # Remove Content-Type header for multipart/form-data
        headers = {}
        if files:
            headers = {"Content-Type": None}

        response = self.session.post(
            url, json=json, data=data, files=files, headers=headers or None, timeout=self.timeout
        )

        if not response.ok:
            self._handle_error(response)

        return response.json()

    def put(self, path: str, json: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """
        Make a PUT request.

        Args:
            path: API endpoint path.
            json: JSON data to send.

        Returns:
            Response data as a dictionary.
        """
        url = f"{self.base_url}{path}"
        response = self.session.put(url, json=json, timeout=self.timeout)

        if not response.ok:
            self._handle_error(response)

        return response.json()

    def delete(self, path: str, json: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """
        Make a DELETE request.

        Args:
            path: API endpoint path.
            json: JSON data to send.

        Returns:
            Response data as a dictionary.
        """
        url = f"{self.base_url}{path}"
        response = self.session.delete(url, json=json, timeout=self.timeout)

        if not response.ok:
            self._handle_error(response)

        return response.json()

    def close(self) -> None:
        """Close the HTTP session."""
        self.session.close()

    def __enter__(self) -> "HTTPClient":
        return self

    def __exit__(self, *args: Any) -> None:
        self.close()
