"""Custom exception classes for DSOL."""

from typing import Any


class DSOLError(Exception):
    """Base exception for all DSOL errors.

    Provides structured error response with code, message, and optional details.
    """

    def __init__(
        self,
        message: str,
        code: str = "DSOL_ERROR",
        details: dict[str, Any] | None = None,
    ) -> None:
        """Initialize DSOL error.

        Args:
            message: Human-readable error message.
            code: Machine-readable error code.
            details: Additional error context.
        """
        self.message = message
        self.code = code
        self.details = details or {}
        super().__init__(message)

    def to_dict(self) -> dict[str, Any]:
        """Convert exception to dictionary for JSON response.

        Returns:
            Dictionary with error structure for API response.
        """
        return {
            "error": {
                "code": self.code,
                "message": self.message,
                "details": self.details,
            }
        }


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

    def __init__(
        self,
        message: str,
        details: dict[str, Any] | None = None,
    ) -> None:
        super().__init__(message=message, code="VALIDATION_ERROR", details=details)


class NotFoundError(DSOLError):
    """Raised when a requested resource is not found."""

    def __init__(
        self,
        message: str,
        details: dict[str, Any] | None = None,
    ) -> None:
        super().__init__(message=message, code="NOT_FOUND", details=details)


class AuthenticationError(DSOLError):
    """Raised when authentication fails."""

    def __init__(
        self,
        message: str = "Authentication required",
        details: dict[str, Any] | None = None,
    ) -> None:
        super().__init__(message=message, code="AUTHENTICATION_ERROR", details=details)


class ExtractionError(DSOLError):
    """Raised when document extraction fails."""

    def __init__(
        self,
        message: str,
        details: dict[str, Any] | None = None,
    ) -> None:
        super().__init__(message=message, code="EXTRACTION_ERROR", details=details)


class RetrievalError(DSOLError):
    """Raised when knowledge retrieval fails."""

    def __init__(
        self,
        message: str,
        details: dict[str, Any] | None = None,
    ) -> None:
        super().__init__(message=message, code="RETRIEVAL_ERROR", details=details)


class IndexingError(DSOLError):
    """Raised when knowledge indexing fails."""

    def __init__(
        self,
        message: str,
        details: dict[str, Any] | None = None,
    ) -> None:
        super().__init__(message=message, code="INDEXING_ERROR", details=details)


class QueryError(DSOLError):
    """Raised when query processing fails."""

    def __init__(
        self,
        message: str,
        details: dict[str, Any] | None = None,
    ) -> None:
        super().__init__(message=message, code="QUERY_ERROR", details=details)


class DocumentNotFoundError(NotFoundError):
    """Raised when a document is not found or not processed."""

    def __init__(
        self,
        message: str = "Document not found or not processed",
        details: dict[str, Any] | None = None,
    ) -> None:
        super().__init__(message=message, details=details)
