"""Base service class for synchronous operations."""

from typing import Any, Dict, Optional
import requests
from sed_sh.exceptions import (
    SedSHError,
    AuthenticationError,
    RateLimitError,
    ResourceNotFoundError,
    InvalidRequestError,
    PaymentRequiredError,
    ServerError,
    NetworkError,
)


class BaseService:
    """Base class for all synchronous service clients.

    This class handles common HTTP operations and error handling.
    All exceptions are caught and converted to appropriate SedSHError subclasses.
    """

    def __init__(self, base_url: str, api_key: str, timeout: int) -> None:
        """Initialize the service.

        Args:
            base_url: API base URL
            api_key: API key for authentication
            timeout: Request timeout in seconds
        """
        self.base_url = base_url.rstrip("/")
        self.api_key = api_key
        self.timeout = timeout
        self.session = requests.Session()
        self.session.headers.update(
            {
                "Authorization": f"Bearer {api_key}",
                "User-Agent": "sed-sh-python/0.1.0",
            }
        )

    def _request(
        self,
        method: str,
        path: str,
        json: Optional[Dict[str, Any]] = None,
        data: Optional[Any] = None,
        headers: Optional[Dict[str, str]] = None,
        params: Optional[Dict[str, Any]] = None,
    ) -> Any:
        """Make an HTTP request.

        Args:
            method: HTTP method (GET, POST, DELETE, etc.)
            path: API endpoint path
            json: JSON request body
            data: Raw request body
            headers: Additional headers
            params: Query parameters

        Returns:
            Response data (usually dict)

        Raises:
            SedSHError: On any error
        """
        url = f"{self.base_url}{path}"

        try:
            response = self.session.request(
                method=method,
                url=url,
                json=json,
                data=data,
                headers=headers,
                params=params,
                timeout=self.timeout,
            )

            # Handle different status codes
            if response.status_code == 401:
                raise AuthenticationError(
                    "Authentication failed. Check your API key.",
                    status_code=401,
                    response=self._safe_json(response),
                )
            elif response.status_code == 402:
                raise PaymentRequiredError(
                    "Payment required. Insufficient account balance.",
                    status_code=402,
                    response=self._safe_json(response),
                )
            elif response.status_code == 404:
                raise ResourceNotFoundError(
                    "Resource not found.",
                    status_code=404,
                    response=self._safe_json(response),
                )
            elif response.status_code == 429:
                raise RateLimitError(
                    "Rate limit exceeded. Please slow down your requests.",
                    status_code=429,
                    response=self._safe_json(response),
                )
            elif response.status_code == 400:
                error_data = self._safe_json(response)
                error_msg = error_data.get("error", "Invalid request parameters")
                raise InvalidRequestError(
                    error_msg, status_code=400, response=error_data
                )
            elif 500 <= response.status_code < 600:
                raise ServerError(
                    f"Server error: {response.status_code}",
                    status_code=response.status_code,
                    response=self._safe_json(response),
                )

            # Raise for other error status codes
            response.raise_for_status()

            # Return JSON response if available
            if response.content:
                try:
                    return response.json()
                except ValueError:
                    return response.text

            return None

        except requests.exceptions.Timeout as e:
            raise NetworkError(
                f"Request timeout after {self.timeout} seconds"
            ) from e
        except requests.exceptions.ConnectionError as e:
            raise NetworkError("Network connection error") from e
        except requests.exceptions.RequestException as e:
            if not isinstance(e, SedSHError):
                raise SedSHError(f"Request failed: {str(e)}") from e
            raise

    def _safe_json(self, response: requests.Response) -> Dict[str, Any]:
        """Safely extract JSON from response.

        Args:
            response: Response object

        Returns:
            JSON data or empty dict
        """
        try:
            return response.json()
        except ValueError:
            return {}

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