//! Error type used across the crate.

use thiserror::Error;

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

/// All errors surfaced by ragdrift-core.
#[derive(Error, Debug)]
pub enum RagDriftError {
    /// Baseline and current samples have incompatible shapes.
    #[error("dimension mismatch: baseline={baseline:?}, current={current:?}")]
    DimensionMismatch {
        /// Shape of the baseline sample.
        baseline: Vec<usize>,
        /// Shape of the current sample.
        current: Vec<usize>,
    },

    /// A sample is too small for the requested computation.
    #[error("insufficient samples: needed at least {needed}, got {got}")]
    InsufficientSamples {
        /// Minimum required sample count.
        needed: usize,
        /// Actual sample count provided.
        got: usize,
    },

    /// A numerical step produced NaN or +/-inf.
    #[error("numerical instability in {step}: {reason}")]
    NumericalInstability {
        /// Name of the algorithm step.
        step: String,
        /// Free-form description.
        reason: String,
    },

    /// An invalid configuration value was supplied.
    #[error("invalid configuration: {0}")]
    InvalidConfig(String),

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

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