"""
Custom exceptions for image generation MCP server.

This module defines the exception hierarchy for proper error handling
following MCP best practices. All exceptions include structured error
codes and messages suitable for client consumption.
"""

from __future__ import annotations

from typing import Any

from .shard.enums import Provider


class ImageGenerationError(Exception):
    """Base exception for all image generation errors.

    All derived exceptions should include:
    - error_code: A stable, machine-readable error code
    - user_message: A human-readable message suitable for clients
    - details: Optional additional context
    """

    def __init__(self, message: str, error_code: str = "image_generation_error", details: dict[str, Any] | None = None):
        super().__init__(message)
        self.error_code = error_code
        self.user_message = message
        self.details = details or {}


class ProviderError(ImageGenerationError):
    """Raised when a provider API fails or returns an error."""

    def __init__(self, message: str, provider: Provider, details: dict[str, Any] | None = None):
        super().__init__(message, error_code="provider_error", details={"provider": provider.value, **(details or {})})
        self.provider = provider


class ModelNotFoundError(ImageGenerationError):
    """Raised when a requested model is not available."""

    def __init__(self, model: str, provider: Provider):
        super().__init__(f"Model '{model}' not found for provider '{provider.value}'. Use the 'get_model_capabilities' tool to check available models.", error_code="model_not_found", details={"model": model, "provider": provider.value})


class ProviderUnavailableError(ImageGenerationError):
    """Raised when a provider is not enabled (missing credentials)."""

    def __init__(self, provider: Provider):
        super().__init__(f"Provider '{provider.value}' is not enabled. Please check your credentials.", error_code="provider_unavailable", details={"provider": provider.value})
        self.provider = provider


class ValidationError(ImageGenerationError):
    """Raised when request parameters are invalid."""

    def __init__(self, message: str, field: str | None = None):
        super().__init__(message, error_code="validation_error", details={"field": field} if field else {})


class NoImagesGeneratedError(ImageGenerationError):
    """Raised when the provider returns no images."""

    def __init__(self, provider: Provider, model: str):
        super().__init__(f"No images were generated by {provider.value} model '{model}'. Try adjusting your prompt or model parameters.", error_code="no_images_generated", details={"provider": provider.value, "model": model})


class UnsupportedOperationError(ImageGenerationError):
    """Raised when an operation is not supported by a provider/model."""

    def __init__(self, operation: str, provider: Provider, model: str):
        super().__init__(f"Operation '{operation}' is not supported by {provider.value} model '{model}'.", error_code="unsupported_operation", details={"operation": operation, "provider": provider.value, "model": model})


class ConfigurationError(ImageGenerationError):
    """Raised when there's an issue with server configuration."""

    def __init__(self, message: str, setting: str | None = None):
        super().__init__(message, error_code="configuration_error", details={"setting": setting} if setting else {})


class RateLimitError(ImageGenerationError):
    """Raised when provider rate limits are exceeded."""

    def __init__(self, provider: Provider, retry_after: int | None = None):
        super().__init__(
            f"Rate limit exceeded for provider '{provider.value}'." + (f" Try again in {retry_after} seconds." if retry_after else ""), error_code="rate_limit_exceeded", details={"provider": provider.value, "retry_after": retry_after}
        )


class AuthenticationError(ImageGenerationError):
    """Raised when provider authentication fails."""

    def __init__(self, provider: Provider):
        super().__init__(f"Authentication failed for provider '{provider.value}'. Please check your API credentials.", error_code="authentication_error", details={"provider": provider.value})
