//! Error type for ledger operations that extend beyond raw SQL.
//!
//! Constructor Pattern: one cube = one error type + its three trait impls.
//! Kept as a separate module so `ledger.rs` stays under the 200-LOC cap.

use crate::schema::MAX_BRANCH_LEN;
use std::fmt;

/// Maximum depth walked by `ledger::tree()` before aborting with
/// `LedgerError::MaxDepthExceeded`. Guards against cyclic or runaway data.
pub const MAX_TREE_DEPTH: usize = 1024;

/// Errors from ledger ops that extend beyond raw SQL (tree walk + input
/// validation). Hot-path SQL calls still return `rusqlite::Error` directly.
#[derive(Debug)]
pub enum LedgerError {
    Sql(rusqlite::Error),
    /// BFS in `tree()` exceeded `MAX_TREE_DEPTH` iterations.
    MaxDepthExceeded,
    /// Branch name longer than `MAX_BRANCH_LEN` chars (audit L1 cap).
    BranchTooLong { field: &'static str, len: usize },
}

impl fmt::Display for LedgerError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            LedgerError::Sql(e) => write!(f, "sql: {e}"),
            LedgerError::MaxDepthExceeded => write!(
                f,
                "tree walk exceeded {MAX_TREE_DEPTH} iterations (cycle or runaway ledger)"
            ),
            LedgerError::BranchTooLong { field, len } => write!(
                f,
                "{field} length {len} exceeds cap {MAX_BRANCH_LEN}"
            ),
        }
    }
}

impl std::error::Error for LedgerError {}

impl From<rusqlite::Error> for LedgerError {
    fn from(e: rusqlite::Error) -> Self {
        LedgerError::Sql(e)
    }
}
