"""Exception classes for OctaMem SDK."""

from __future__ import annotations


class OctaMemError(Exception):
    """Base exception for all OctaMem errors."""

    def __init__(
        self,
        message: str,
        *,
        code: str = "OCTAMEM_ERROR",
        status_code: int | None = None,
    ) -> None:
        super().__init__(message)
        self.message = message
        self.code = code
        self.status_code = status_code

    def __repr__(self) -> str:
        return f"{self.__class__.__name__}(message={self.message!r}, code={self.code!r})"


class AuthenticationError(OctaMemError):
    """Raised when authentication fails (invalid/expired API key)."""

    def __init__(self, message: str = "Authentication failed. Check your API key.") -> None:
        super().__init__(message, code="AUTH_ERROR", status_code=401)


class MethodNotSupportedError(OctaMemError):
    """Raised when a method is not supported for this memory type."""

    def __init__(self, message: str = "Method not supported for this memory.") -> None:
        super().__init__(message, code="METHOD_NOT_SUPPORTED", status_code=403)


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

    def __init__(self, message: str = "Resource not found.") -> None:
        super().__init__(message, code="NOT_FOUND", status_code=404)


class ValidationError(OctaMemError):
    """Raised when input validation fails."""

    def __init__(self, message: str) -> None:
        super().__init__(message, code="VALIDATION_ERROR", status_code=400)


class RateLimitError(OctaMemError):
    """Raised when rate limit is exceeded."""

    def __init__(self, retry_after: float | None = None) -> None:
        if retry_after is not None:
            message = f"Rate limit exceeded. Retry after {retry_after} seconds."
        else:
            message = "Rate limit exceeded. Try again later."
        super().__init__(message, code="RATE_LIMIT", status_code=429)
        self.retry_after = retry_after


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

    def __init__(
        self,
        message: str,
        status_code: int,
        code: str | None = None,
    ) -> None:
        super().__init__(message, code=code or "API_ERROR", status_code=status_code)


class APIConnectionError(OctaMemError):
    """Raised when unable to connect to the API."""

    def __init__(self, message: str = "Failed to connect to OctaMem API.") -> None:
        super().__init__(message, code="CONNECTION_ERROR")


class APITimeoutError(OctaMemError):
    """Raised when request times out."""

    def __init__(self, timeout: float) -> None:
        super().__init__(f"Request timed out after {timeout}s", code="TIMEOUT_ERROR", status_code=408)
        self.timeout = timeout


class InternalServerError(OctaMemError):
    """Raised when the API returns a 5xx error."""

    def __init__(self, message: str = "Internal server error.", status_code: int = 500) -> None:
        super().__init__(message, code="INTERNAL_ERROR", status_code=status_code)
