pub mod engine;
pub mod rocks_engine;

use async_trait::async_trait;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum StorageError {
    #[error("RocksDB error: {0}")]
    RocksDb(#[from] rocksdb::Error),
    #[error("Serialization error: {0}")]
    Serialization(String),
}

#[derive(Debug)]
pub struct CasResult {
    pub success: bool,
    pub current_version: u64,
    pub new_version: u64,
}

#[async_trait]
pub trait StorageEngine: Send + Sync {
    async fn put_raw(&self, key: &[u8], value: &[u8]) -> Result<(), StorageError>;
    async fn get_raw(&self, key: &[u8]) -> Result<Option<Vec<u8>>, StorageError>;
    async fn delete_raw(&self, key: &[u8]) -> Result<(), StorageError>;
    async fn get_cas(&self, key: &[u8]) -> Result<Option<(u64, Vec<u8>)>, StorageError>;
    async fn compare_and_swap(
        &self,
        key: &[u8],
        expected_version: u64,
        value: &[u8],
    ) -> Result<CasResult, StorageError>;
    async fn delete_cas(&self, key: &[u8]) -> Result<(), StorageError>;

    /// Scan raw key-value pairs in range [start, end)
    async fn scan_raw(
        &self,
        start: &[u8],
        end: &[u8],
        limit: usize,
    ) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError>;

    /// Scan CAS key-value pairs with versions in range [start, end)
    async fn scan_cas(
        &self,
        start: &[u8],
        end: &[u8],
        limit: usize,
    ) -> Result<Vec<(Vec<u8>, Vec<u8>, u64)>, StorageError>;
}
