//! Error types for the backup-manager crate.
//!
//! All public APIs return [`Result<T>`] which is shorthand for
//! `std::result::Result<T, BackupError>`.

use thiserror::Error;

/// Top-level error type for the backup-manager.
#[derive(Debug, Error)]
pub enum BackupError {
    /// Configuration could not be loaded or validated.
    #[error("configuration error: {0}")]
    Config(String),

    /// A policy file could not be deserialised or violated a contract.
    #[error("policy error: {0}")]
    Policy(String),

    /// A backup provider (restic, kopia) failed.
    #[error("provider '{provider}' error: {message}")]
    Provider {
        /// Provider identifier (`restic`, `kopia`, ...).
        provider: String,
        /// Underlying error message from the provider invocation.
        message: String,
    },

    /// A destination was unreachable or rejected the operation.
    #[error("destination '{destination}' error: {message}")]
    Destination {
        /// Destination identifier (matches `BackupPolicy.destinations[].name`).
        destination: String,
        /// Underlying error.
        message: String,
    },

    /// The vault (secretumvault) returned an error or was unreachable.
    #[error("vault error: {0}")]
    Vault(String),

    /// NATS publish/subscribe error.
    #[error("nats error: {0}")]
    Nats(String),

    /// A Kubernetes API call failed.
    #[error("kubernetes error: {0}")]
    Kubernetes(String),

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

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

    /// A pre/post hook exited non-zero.
    #[error("hook '{hook}' failed: exit {exit_code}")]
    HookFailed {
        /// Hook identifier (`pre`, `post`, or a named hook).
        hook: String,
        /// Process exit code.
        exit_code: i32,
    },

    /// Any other anyhow-flavoured failure that does not fit the categories above.
    #[error("{0}")]
    Other(#[from] anyhow::Error),
}

/// Crate-local result alias.
pub type Result<T> = std::result::Result<T, BackupError>;
