//! Error types for RAG system

use thiserror::Error;

/// Result type for RAG operations
pub type Result<T> = std::result::Result<T, RagError>;

/// Error types for RAG operations
#[derive(Error, Debug)]
pub enum RagError {
    #[error("Configuration error: {0}")]
    Config(String),

    #[error("Database error: {0}")]
    Database(String),

    #[error("Embedding error: {0}")]
    Embedding(String),

    #[error("Retrieval error: {0}")]
    Retrieval(String),

    #[error("LLM error: {0}")]
    LlmError(String),

    #[error("Context error: {0}")]
    Context(String),

    #[error("I/O error: {0}")]
    Io(#[from] std::io::Error),

    #[error("SurrealDB error: {0}")]
    Surrealdb(String),

    #[error("JSON error: {0}")]
    Json(#[from] serde_json::Error),

    #[error("Regex error: {0}")]
    Regex(#[from] regex::Error),

    #[error("HTTP error: {0}")]
    Http(String),

    #[error("Invalid input: {0}")]
    InvalidInput(String),

    #[error("Not found: {0}")]
    NotFound(String),

    #[error("Internal error: {0}")]
    Internal(String),

    #[error("Tool error: {0}")]
    ToolError(String),
}

impl RagError {
    /// Create a configuration error
    pub fn config(msg: impl Into<String>) -> Self {
        RagError::Config(msg.into())
    }

    /// Create a database error
    pub fn database(msg: impl Into<String>) -> Self {
        RagError::Database(msg.into())
    }

    /// Create an embedding error
    pub fn embedding(msg: impl Into<String>) -> Self {
        RagError::Embedding(msg.into())
    }

    /// Create a retrieval error
    pub fn retrieval(msg: impl Into<String>) -> Self {
        RagError::Retrieval(msg.into())
    }

    /// Create an LLM error
    pub fn llm(msg: impl Into<String>) -> Self {
        RagError::LlmError(msg.into())
    }

    /// Create a context error
    pub fn context(msg: impl Into<String>) -> Self {
        RagError::Context(msg.into())
    }

    /// Create a SurrealDB error
    pub fn surrealdb(msg: impl Into<String>) -> Self {
        RagError::Surrealdb(msg.into())
    }

    /// Create an HTTP error
    pub fn http(msg: impl Into<String>) -> Self {
        RagError::Http(msg.into())
    }

    /// Create an invalid input error
    pub fn invalid_input(msg: impl Into<String>) -> Self {
        RagError::InvalidInput(msg.into())
    }

    /// Create a not found error
    pub fn not_found(msg: impl Into<String>) -> Self {
        RagError::NotFound(msg.into())
    }

    /// Create an internal error
    pub fn internal(msg: impl Into<String>) -> Self {
        RagError::Internal(msg.into())
    }

    /// Create a tool error
    pub fn tool(msg: impl Into<String>) -> Self {
        RagError::ToolError(msg.into())
    }
}
