use super::batch::WriteBatch;
use super::error::StorageError;
use super::iterator::PrefixIterator;

/// The storage engine trait.
///
/// All access to durable state goes through this interface.
/// Implementations include `InMemoryBackend` (for testing) and
/// `FjallBackend` (for production).
///
/// Keys and values are opaque byte slices — typed serialization
/// is handled by higher modules.
pub trait StorageEngine: Send + Sync {
    /// Read a single key. Returns `None` if the key does not exist.
    ///
    /// # Errors
    ///
    /// Returns `StorageError` on I/O failure or corruption.
    fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, StorageError>;

    /// Write a single key-value pair.
    ///
    /// # Errors
    ///
    /// Returns `StorageError` on I/O failure or if the engine is closed.
    fn put(&self, key: &[u8], value: &[u8]) -> Result<(), StorageError>;

    /// Delete a key. No-op if the key does not exist.
    ///
    /// # Errors
    ///
    /// Returns `StorageError` on I/O failure or if the engine is closed.
    fn delete(&self, key: &[u8]) -> Result<(), StorageError>;

    /// Scan all keys with the given prefix, in lexicographic order.
    ///
    /// Returns a boxed iterator that yields `(key, value)` pairs.
    fn scan_prefix(&self, prefix: &[u8]) -> PrefixIterator<'_>;

    /// Write a batch of operations atomically.
    ///
    /// Either all operations are applied or none are.
    ///
    /// # Errors
    ///
    /// Returns `StorageError` on I/O failure or batch conflict.
    fn write_batch(&self, batch: WriteBatch) -> Result<(), StorageError>;

    /// Force all buffered data to stable storage.
    ///
    /// # Errors
    ///
    /// Returns `StorageError` on I/O failure.
    fn flush(&self) -> Result<(), StorageError>;
}
