//! Error types for tool operations.

use thiserror::Error;

/// Result type for tool operations.
pub type ToolResult<T> = Result<T, ToolError>;

/// Errors that can occur during tool operations.
#[derive(Error, Debug)]
pub enum ToolError {
    /// File or directory not found.
    #[error("Not found: {path}")]
    NotFound { path: String },

    /// Permission denied by OS or sandbox policy.
    #[error("Permission denied: {reason}")]
    PermissionDenied { reason: String },

    /// Path outside allowed sandbox roots.
    #[error("Sandbox violation: {reason}")]
    SandboxViolation { reason: String },

    /// Path matched blocklist pattern.
    #[error("Blocked path: {reason}")]
    BlockedPath { reason: String },

    /// File too large to process.
    #[error("File too large: {size} bytes exceeds limit of {limit} bytes")]
    FileTooLarge { size: u64, limit: u64 },

    /// Invalid encoding (non-UTF-8).
    #[error("Encoding not supported: {encoding}")]
    EncodingUnsupported { encoding: String },

    /// User rejected permission prompt.
    #[error("Permission rejected by user")]
    PermissionRejected,

    /// Terminal operation failed.
    #[error("Terminal error: {message}")]
    TerminalError { message: String },

    /// Terminal not found.
    #[error("Terminal not found: {terminal_id}")]
    TerminalNotFound { terminal_id: String },

    /// Search operation exceeded limits.
    #[error("Search limit exceeded: {reason}")]
    SearchLimitExceeded { reason: String },

    /// Invalid configuration.
    #[error("Invalid configuration: {0}")]
    InvalidConfig(String),

    /// File read error with detailed information.
    #[error("Failed to read file {path}: {source}")]
    FileReadError {
        path: String,
        #[source]
        source: std::io::Error,
    },

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

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

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

    /// Generic error.
    #[error("{0}")]
    Other(#[from] anyhow::Error),
}

impl ToolError {
    /// Create a sandbox violation error without exposing the full path.
    pub fn sandbox_violation(reason: impl Into<String>) -> Self {
        Self::SandboxViolation {
            reason: reason.into(),
        }
    }

    /// Create a blocked path error without exposing the full path.
    pub fn blocked_path(reason: impl Into<String>) -> Self {
        Self::BlockedPath {
            reason: reason.into(),
        }
    }

    /// Create a permission denied error.
    pub fn permission_denied(reason: impl Into<String>) -> Self {
        Self::PermissionDenied {
            reason: reason.into(),
        }
    }

    /// Create a terminal error.
    pub fn terminal_error(message: impl Into<String>) -> Self {
        Self::TerminalError {
            message: message.into(),
        }
    }
}
