"""
Domain Exceptions

Custom exceptions for the HoneyDB MCP CLI.
v2.0: Enhanced error recovery with specific exception types.
"""


class HoneyDBError(Exception):
    """Base exception for all HoneyDB MCP CLI errors."""

    def __init__(self, message: str, recovery_hint: str | None = None):
        self.message = message
        self.recovery_hint = recovery_hint
        super().__init__(message)

    def __str__(self) -> str:
        if self.recovery_hint:
            return f"{self.message}\n\n💡 {self.recovery_hint}"
        return self.message


# Configuration Errors
class ConfigurationError(HoneyDBError):
    """Raised when configuration is invalid or missing."""

    pass


class APIKeyMissingError(ConfigurationError):
    """Raised when required API key is not configured."""

    def __init__(self, provider: str):
        super().__init__(
            message=f"API key for {provider} is not configured",
            recovery_hint=f"Set your {provider} API key using: honeydb-ai config set {provider}_api_key YOUR_KEY"
        )


# Session Errors
class SessionError(HoneyDBError):
    """Base exception for session-related errors."""

    pass


class SessionNotFoundError(SessionError):
    """Raised when a session cannot be found."""

    def __init__(self, session_id: str):
        super().__init__(
            message=f"Session '{session_id}' not found",
            recovery_hint="Use 'honeydb-ai session list' to see available sessions"
        )


class SessionCorruptedError(SessionError):
    """
    Raised when a session file is corrupted and cannot be loaded.
    v2.0 Critical: Part of enhanced error recovery strategy.
    """

    def __init__(self, session_id: str, backup_available: bool = False):
        recovery = (
            f"A backup file is available. Try: honeydb-ai session restore {session_id}"
            if backup_available
            else f"No backup available. The session may be permanently lost."
        )
        super().__init__(
            message=f"Session '{session_id}' file is corrupted and cannot be loaded",
            recovery_hint=recovery
        )


class SessionTooLargeError(SessionError):
    """
    Raised when a session exceeds size limits.
    v2.0 Critical: Part of session size limit enforcement.
    """

    def __init__(self, size_bytes: int, max_size_bytes: int):
        super().__init__(
            message=f"Session size ({size_bytes:,} bytes) exceeds maximum ({max_size_bytes:,} bytes)",
            recovery_hint="Start a new session or export this one to continue"
        )


class SessionSaveError(SessionError):
    """Raised when a session cannot be saved."""

    def __init__(self, session_id: str, reason: str):
        super().__init__(
            message=f"Failed to save session '{session_id}': {reason}",
            recovery_hint="Check file permissions and available disk space"
        )


class SessionLoadError(SessionError):
    """Raised when a session cannot be loaded."""

    def __init__(self, session_id: str, reason: str):
        super().__init__(
            message=f"Failed to load session '{session_id}': {reason}",
            recovery_hint="The session file may be corrupted. Try restoring from backup if available."
        )


class SessionLockTimeoutError(SessionError):
    """
    Raised when file lock cannot be acquired within timeout.
    v2.0 Critical: Part of file locking implementation.
    """

    def __init__(self, session_id: str, timeout_seconds: float):
        super().__init__(
            message=f"Could not acquire lock for session '{session_id}' after {timeout_seconds}s",
            recovery_hint="Another process may be modifying this session. Wait and try again."
        )


# LLM Errors
class LLMError(HoneyDBError):
    """Base exception for LLM provider errors."""

    pass


class LLMProviderError(LLMError):
    """Raised when an LLM provider returns an error."""

    def __init__(self, provider: str, message: str):
        super().__init__(
            message=f"{provider} error: {message}",
            recovery_hint="Check your API key and network connection"
        )


class LLMAPIError(LLMError):
    """Raised when an LLM API call fails."""

    def __init__(self, provider: str, status_code: int, message: str):
        super().__init__(
            message=f"{provider} API error ({status_code}): {message}",
            recovery_hint="Check API status and your account limits"
        )


class LLMRateLimitError(LLMError):
    """Raised when rate limit is exceeded."""

    def __init__(self, provider: str, retry_after: int | None = None):
        retry_msg = f" Retry after {retry_after}s." if retry_after else ""
        super().__init__(
            message=f"{provider} rate limit exceeded.{retry_msg}",
            recovery_hint="Wait a moment before sending another request"
        )


class LLMRequestCancelledError(LLMError):
    """
    Raised when user cancels an LLM request (Ctrl+C).
    v2.0 Critical: Part of Ctrl+C cancellation handling.
    """

    def __init__(self):
        super().__init__(
            message="Request cancelled by user",
            recovery_hint=None  # No recovery needed - this is intentional
        )


# Storage Errors
class StorageError(HoneyDBError):
    """Base exception for storage-related errors."""

    pass


class StorageInitializationError(StorageError):
    """Raised when storage cannot be initialized."""

    def __init__(self, path: str, reason: str):
        super().__init__(
            message=f"Failed to initialize storage at '{path}': {reason}",
            recovery_hint="Check directory permissions and available disk space"
        )


# Validation Errors
class ValidationError(HoneyDBError):
    """Raised when input validation fails."""

    pass
