"""
Custom exception classes for the Rootly MCP Server.

This module defines specific exception types for better error handling
and debugging throughout the application.
"""


class RootlyMCPError(Exception):
    """Base exception for all Rootly MCP Server errors."""

    def __init__(self, message: str, details: dict | None = None):
        super().__init__(message)
        self.message = message
        self.details = details or {}


class RootlyAuthenticationError(RootlyMCPError):
    """Raised when API authentication fails."""

    pass


class RootlyAuthorizationError(RootlyMCPError):
    """Raised when the user lacks permissions for the requested resource."""

    pass


class RootlyNetworkError(RootlyMCPError):
    """Raised when network connectivity issues occur."""

    pass


class RootlyTimeoutError(RootlyNetworkError):
    """Raised when a request times out."""

    pass


class RootlyValidationError(RootlyMCPError):
    """Raised when input validation fails."""

    pass


class RootlyRateLimitError(RootlyMCPError):
    """Raised when API rate limits are exceeded."""

    def __init__(self, message: str, retry_after: int | None = None, details: dict | None = None):
        super().__init__(message, details)
        self.retry_after = retry_after


class RootlyAPIError(RootlyMCPError):
    """Raised when the Rootly API returns an error response."""

    def __init__(self, message: str, status_code: int | None = None, details: dict | None = None):
        super().__init__(message, details)
        self.status_code = status_code


class RootlyServerError(RootlyAPIError):
    """Raised when the Rootly API returns a 5xx server error."""

    pass


class RootlyClientError(RootlyAPIError):
    """Raised when the Rootly API returns a 4xx client error."""

    pass


class RootlyConfigurationError(RootlyMCPError):
    """Raised when there's a configuration error (e.g., missing API token)."""

    pass


class RootlyResourceNotFoundError(RootlyClientError):
    """Raised when a requested resource is not found (404)."""

    pass


def categorize_exception(exception: Exception) -> tuple[type[RootlyMCPError], str]:
    """
    Categorize a generic exception into a specific Rootly exception type.

    Args:
        exception: The exception to categorize

    Returns:
        Tuple of (exception_class, error_message)
    """
    error_str = str(exception).lower()
    exception_type = type(exception).__name__.lower()

    # Authentication errors (401)
    if any(
        keyword in error_str
        for keyword in ["401", "unauthorized", "authentication failed", "invalid token"]
    ):
        return RootlyAuthenticationError, f"Authentication failed: {exception}"

    # Authorization errors (403)
    if any(
        keyword in error_str
        for keyword in ["403", "forbidden", "permission denied", "access denied"]
    ):
        return RootlyAuthorizationError, f"Authorization failed: {exception}"

    # Rate limit errors (429)
    if any(keyword in error_str for keyword in ["429", "rate limit", "too many requests"]):
        return RootlyRateLimitError, f"Rate limit exceeded: {exception}"

    # Resource not found (404)
    if any(keyword in error_str for keyword in ["404", "not found"]):
        return RootlyResourceNotFoundError, f"Resource not found: {exception}"

    # Client errors (4xx)
    if any(keyword in error_str for keyword in ["400", "bad request", "invalid"]):
        return RootlyClientError, f"Client error: {exception}"

    # Server errors (5xx)
    if any(keyword in error_str for keyword in ["500", "502", "503", "504", "server error"]):
        return RootlyServerError, f"Server error: {exception}"

    # Timeout errors
    if any(keyword in exception_type for keyword in ["timeout", "timedout"]):
        return RootlyTimeoutError, f"Request timed out: {exception}"

    # Network/Connection errors
    if any(keyword in exception_type for keyword in ["connection", "network"]):
        return RootlyNetworkError, f"Network error: {exception}"

    # Validation errors
    if any(keyword in exception_type for keyword in ["validation", "pydantic", "field"]):
        return RootlyValidationError, f"Validation error: {exception}"

    # Configuration errors
    if any(keyword in error_str for keyword in ["not set", "missing", "configuration"]):
        return RootlyConfigurationError, f"Configuration error: {exception}"

    # Default to generic API error
    return RootlyAPIError, f"API error: {exception}"
