from __future__ import annotations

from typing import Any, Optional


class CardogError(Exception):
    """Base exception for all Cardog SDK errors."""


class APIError(CardogError):
    """Raised when the API returns an error response."""

    def __init__(
        self,
        message: str,
        status_code: int,
        code: Optional[str] = None,
        body: Optional[Any] = None,
    ) -> None:
        super().__init__(message)
        self.status_code = status_code
        self.code = code
        self.body = body

    def __str__(self) -> str:
        parts = [f"[{self.status_code}]"]
        if self.code:
            parts.append(f"({self.code})")
        parts.append(super().__str__())
        return " ".join(parts)


class AuthenticationError(APIError):
    """Raised when authentication fails (401)."""


class PermissionError(APIError):
    """Raised when the request is forbidden (403)."""


class NotFoundError(APIError):
    """Raised when the requested resource is not found (404)."""


class RateLimitError(APIError):
    """Raised when the rate limit is exceeded (429)."""

    def __init__(
        self,
        message: str,
        status_code: int = 429,
        code: Optional[str] = None,
        body: Optional[Any] = None,
        retry_after: Optional[float] = None,
    ) -> None:
        super().__init__(message, status_code, code, body)
        self.retry_after = retry_after


class ServerError(APIError):
    """Raised when the server returns a 5xx error."""


class ConnectionError(CardogError):
    """Raised when a connection to the API cannot be established."""


class TimeoutError(CardogError):
    """Raised when a request times out."""
