//! State tree error types.

/// Errors from state tree operations.
#[derive(Debug, thiserror::Error)]
pub enum StateTreeError {
    /// redb database-level error (e.g., file I/O, corruption).
    #[error("redb database: {0}")]
    Database(#[from] redb::DatabaseError),

    /// redb internal storage error.
    #[error("redb storage: {0}")]
    Storage(#[from] redb::StorageError),

    /// redb table error (e.g., table not found, schema mismatch).
    #[error("redb table: {0}")]
    Table(#[from] redb::TableError),

    /// redb transaction error. Boxed because `TransactionError` is large.
    #[error("redb transaction: {0}")]
    Transaction(Box<redb::TransactionError>),

    /// redb commit error.
    #[error("redb commit: {0}")]
    Commit(#[from] redb::CommitError),

    /// Jellyfish Merkle Tree operation error.
    #[error("jmt (v{version}): {source}")]
    Jmt {
        /// The version being operated on.
        version: u64,
        /// Underlying JMT error.
        #[source]
        source: anyhow::Error,
    },

    /// Value exceeds the configured maximum size.
    #[error("value too large: {size} bytes exceeds cap of {cap}")]
    ValueTooLarge {
        /// Actual value size in bytes.
        size: usize,
        /// Configured maximum.
        cap: usize,
    },

    /// Batch exceeds the configured maximum entry count.
    #[error("batch too large: {count} entries exceeds cap of {cap}")]
    BatchTooLarge {
        /// Actual entry count.
        count: usize,
        /// Configured maximum.
        cap: usize,
    },

    /// redb durability configuration error.
    #[error("redb durability: {0}")]
    Durability(#[from] redb::SetDurabilityError),

    /// Proof verification failed.
    #[error("proof verification failed: {reason}")]
    ProofInvalid {
        /// Description of why the proof is invalid.
        reason: String,
    },

    /// Serialization/deserialization error (borsh).
    #[error("serialization: {0}")]
    Serialization(String),

    /// Filesystem I/O error (e.g., creating the data directory before opening redb).
    #[error("io ({path}): {source}")]
    Io {
        /// Path that failed.
        path: std::path::PathBuf,
        /// Underlying io error.
        #[source]
        source: std::io::Error,
    },
}

impl From<redb::TransactionError> for StateTreeError {
    fn from(e: redb::TransactionError) -> Self {
        Self::Transaction(Box::new(e))
    }
}

/// Result alias for state tree operations.
pub(crate) type Result<T> = std::result::Result<T, StateTreeError>;
