// Copyright 2021 TiKV Project Authors. Licensed under Apache-2.0.
// Modifications Copyright 2026 PingCAP, Inc.

use std::{path::Path, sync::Arc};

use engine_traits::{ALL_CFS, CfName};
use file_system::IoRateLimiter;
use kvproto::kvrpcpb::ApiVersion;

use crate::storage::kv::{BTreeEngine, Result};

/// Builds the lightweight in-memory engine used by storage unit tests.
///
/// The compatibility setters intentionally keep the old test call shape while
/// no longer constructing a RocksDB instance. Tests that require persistence,
/// encryption, or physical files must use `kvengine::test_engine` instead.
#[must_use]
pub struct TestEngineBuilder {
    cfs: Option<Vec<CfName>>,
    api_version: ApiVersion,
}

impl TestEngineBuilder {
    pub fn new() -> Self {
        Self {
            cfs: None,
            api_version: ApiVersion::V1,
        }
    }

    /// Retained for source compatibility. An in-memory engine has no path.
    pub fn path(self, _path: impl AsRef<Path>) -> Self {
        self
    }

    /// Customizes the column families available in the in-memory engine.
    pub fn cfs(mut self, cfs: impl AsRef<[CfName]>) -> Self {
        self.cfs = Some(cfs.as_ref().to_vec());
        self
    }

    /// Selects the API key layout used by projected kvengine snapshots.
    pub fn api_version(mut self, api_version: ApiVersion) -> Self {
        self.api_version = api_version;
        self
    }

    /// Retained for source compatibility. Memory reads and writes are not rate
    /// limited.
    pub fn io_rate_limiter(self, _limiter: Option<Arc<IoRateLimiter>>) -> Self {
        self
    }

    pub fn build(self) -> Result<BTreeEngine> {
        Ok(BTreeEngine::new_with_api_version(
            self.cfs.as_deref().unwrap_or(ALL_CFS),
            self.api_version,
        ))
    }

    /// RocksDB configuration is deliberately ignored by the memory backend.
    pub fn build_with_cfg(self, _config: &crate::config::DbConfig) -> Result<BTreeEngine> {
        self.build()
    }

    pub fn build_without_cache(self) -> Result<BTreeEngine> {
        self.build()
    }
}

impl Default for TestEngineBuilder {
    fn default() -> Self {
        Self::new()
    }
}

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

    use super::*;
    use crate::storage::kv::TEST_ENGINE_CFS;

    #[test]
    fn test_memory_engine_crud() {
        let mut engine = TestEngineBuilder::new()
            .cfs(TEST_ENGINE_CFS)
            .build()
            .unwrap();
        test_base_curd_options(&mut engine)
    }

    #[test]
    fn test_memory_engine_iteration() {
        let mut engine = TestEngineBuilder::new()
            .cfs(TEST_ENGINE_CFS)
            .build()
            .unwrap();
        test_linear(&mut engine);
        test_cfs_statistics(&mut engine);
    }
}
