//! Application-facing control and outcome types for batch Tree operations
//! (`update_many`). See `docs/superpowers/specs/26-06-24-armdb-batch-tree-ops.md`.

/// What a batch update closure decided for one key. The absence/deletion policy
/// lives entirely in the closure: it receives `Option<&T>` (`None` = key absent)
/// and returns one of these.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BatchWrite<T> {
    /// Insert (if absent) or overwrite (if present) with this value.
    Set(T),
    /// Leave the key untouched (no write, no hook).
    Keep,
    /// Delete the key. On an **absent** key this is a no-op (`Applied::Kept`).
    Delete,
}

/// What actually happened to one key — a self-sufficient application event
/// channel (`old` + `new` are present here, so duplicating an `on_write` hook is
/// optional).
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Applied<T> {
    /// `Set` was applied. `old = Some(..)` on overwrite, `None` on insert.
    Written { old: Option<T>, new: T },
    /// `Keep`, or `Delete` against an absent key.
    Kept,
    /// `Delete` against an existing key; carries the removed value.
    Deleted(T),
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn batch_types_construct_and_compare() {
        let w: BatchWrite<u32> = BatchWrite::Set(7);
        assert_eq!(w, BatchWrite::Set(7));
        assert_ne!(w, BatchWrite::Keep);

        let a: Applied<u32> = Applied::Written { old: None, new: 7 };
        assert_eq!(a, Applied::Written { old: None, new: 7 });
        assert_eq!(Applied::<u32>::Kept, Applied::Kept);
        assert_eq!(Applied::Deleted(3u32), Applied::Deleted(3));
    }
}
