//! Error types for s3bolt.

/// A type alias for `Result<T, S3boltError>`.
pub type Result<T> = std::result::Result<T, S3boltError>;

/// All errors that can occur in s3bolt.
#[derive(Debug, thiserror::Error)]
pub enum S3boltError {
    /// Invalid S3 URI format.
    #[error("invalid S3 URI '{uri}': expected s3://bucket/key")]
    InvalidUri { uri: String },

    /// S3 API error from the AWS SDK.
    #[error("S3 {operation} failed: {message}")]
    S3Api {
        operation: String,
        message: String,
        is_retryable: bool,
    },

    /// Multipart upload failed.
    #[error("multipart copy failed for {size}-byte object: {reason}")]
    MultipartFailed { size: u64, reason: String },

    /// Filter pattern compilation error.
    #[error("invalid filter pattern: {0}")]
    FilterError(String),

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

    /// AWS credential resolution error.
    #[error("credential error: {0}")]
    CredentialError(String),

    /// Configuration validation error.
    #[error("configuration error: {0}")]
    ConfigError(String),

    /// All retries exhausted for a copy job.
    #[error("retries exhausted for '{key}': {last_error}")]
    RetriesExhausted { key: String, last_error: String },

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

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

impl S3boltError {
    /// Returns `true` if the error is retryable.
    pub fn is_retryable(&self) -> bool {
        match self {
            Self::S3Api { is_retryable, .. } => *is_retryable,
            Self::CheckpointError(_) => false,
            _ => false,
        }
    }
}
