//! In-memory Raft storage for FlareDB
//!
//! This module provides an in-memory implementation of OpenRaft's RaftStorage trait,
//! similar to openraft-memstore but using FlareDB's type configuration.

use crate::types::{
    FlareEntry, FlareLogId, FlareNode, FlareNodeId, FlareRequest, FlareResponse,
    FlareStoredMembership, FlareTypeConfig,
};
use openraft::storage::{LogFlushed, LogState, RaftLogReader, RaftLogStorage, RaftSnapshotBuilder, RaftStateMachine, Snapshot};
use openraft::{EntryPayload, OptionalSend, RaftLogId, SnapshotMeta};
use openraft::{StorageError, StorageIOError, StoredMembership, Vote};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::fmt::Debug;
use std::io::Cursor;
use std::ops::RangeBounds;
use std::sync::Arc;
use tokio::sync::RwLock;

/// Snapshot data for FlareDB
#[derive(Debug)]
pub struct FlareSnapshot {
    pub meta: SnapshotMeta<FlareNodeId, FlareNode>,
    pub data: Vec<u8>,
}

/// State machine for FlareDB
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct FlareStateMachine {
    pub last_applied_log: Option<FlareLogId>,
    pub last_membership: FlareStoredMembership,
    /// Key-value data: (namespace_id, key) -> (value, timestamp)
    /// Used for eventual consistency (Last-Write-Wins)
    pub kv_data: BTreeMap<(u32, Vec<u8>), (Vec<u8>, u64)>,
    /// CAS data: (namespace_id, key) -> (value, version, timestamp)
    /// Used for strong consistency (Compare-And-Swap)
    pub cas_data: BTreeMap<(u32, Vec<u8>), (Vec<u8>, u64, u64)>,
}

/// In-memory storage implementing RaftStorage for FlareDB
pub struct FlareStore {
    last_purged_log_id: RwLock<Option<FlareLogId>>,
    committed: RwLock<Option<FlareLogId>>,
    /// Raft log entries stored as serialized JSON
    log: RwLock<BTreeMap<u64, String>>,
    /// State machine
    sm: RwLock<FlareStateMachine>,
    /// Current vote
    vote: RwLock<Option<Vote<FlareNodeId>>>,
    /// Snapshot counter
    snapshot_idx: RwLock<u64>,
    /// Current snapshot
    current_snapshot: RwLock<Option<FlareSnapshot>>,
}

impl FlareStore {
    /// Create a new FlareStore
    pub fn new() -> Self {
        Self {
            last_purged_log_id: RwLock::new(None),
            committed: RwLock::new(None),
            log: RwLock::new(BTreeMap::new()),
            sm: RwLock::new(FlareStateMachine::default()),
            vote: RwLock::new(None),
            snapshot_idx: RwLock::new(0),
            current_snapshot: RwLock::new(None),
        }
    }

    /// Create a new FlareStore wrapped in Arc
    pub fn new_arc() -> Arc<Self> {
        Arc::new(Self::new())
    }

    /// Get the current state machine (for testing)
    pub async fn get_state_machine(&self) -> FlareStateMachine {
        self.sm.read().await.clone()
    }

    /// Read a value from the state machine (eventual consistency)
    pub async fn read_kv(&self, namespace_id: u32, key: &[u8]) -> Option<(Vec<u8>, u64)> {
        let sm = self.sm.read().await;
        sm.kv_data.get(&(namespace_id, key.to_vec())).cloned()
    }

    /// Read a CAS value from the state machine (strong consistency)
    /// Returns (value, version, timestamp) if found
    pub async fn read_cas(&self, namespace_id: u32, key: &[u8]) -> Option<(Vec<u8>, u64, u64)> {
        let sm = self.sm.read().await;
        sm.cas_data.get(&(namespace_id, key.to_vec())).cloned()
    }

    /// Scan CAS data from the replicated state machine.
    pub async fn scan_cas(
        &self,
        namespace_id: u32,
        start_key: &[u8],
        end_key: &[u8],
        limit: usize,
    ) -> Vec<(Vec<u8>, Vec<u8>, u64, u64)> {
        let sm = self.sm.read().await;

        sm.cas_data
            .iter()
            .filter(|((ns_id, key), _)| {
                *ns_id == namespace_id
                    && key.as_slice() >= start_key
                    && (end_key.is_empty() || key.as_slice() < end_key)
            })
            .take(limit)
            .map(|((_ns_id, key), (value, version, ts))| {
                (key.clone(), value.clone(), *version, *ts)
            })
            .collect()
    }
}

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

impl RaftLogReader<FlareTypeConfig> for Arc<FlareStore> {
    async fn try_get_log_entries<RB: RangeBounds<u64> + Clone + Debug + OptionalSend>(
        &mut self,
        range: RB,
    ) -> Result<Vec<FlareEntry>, StorageError<FlareNodeId>> {
        let mut entries = vec![];
        let log = self.log.read().await;

        for (_, serialized) in log.range(range) {
            let ent: FlareEntry =
                serde_json::from_str(serialized).map_err(|e| StorageIOError::read_logs(&e))?;
            entries.push(ent);
        }

        Ok(entries)
    }
}

impl RaftSnapshotBuilder<FlareTypeConfig> for Arc<FlareStore> {
    async fn build_snapshot(&mut self) -> Result<Snapshot<FlareTypeConfig>, StorageError<FlareNodeId>> {
        let data;
        let last_applied_log;
        let last_membership;

        {
            let sm = self.sm.read().await;
            // Use bincode for state machine (handles tuple map keys)
            data = bincode::serialize(&*sm).map_err(|e| StorageIOError::read_state_machine(&e))?;
            last_applied_log = sm.last_applied_log;
            last_membership = sm.last_membership.clone();
        }

        let snapshot_idx = {
            let mut idx = self.snapshot_idx.write().await;
            *idx += 1;
            *idx
        };

        let snapshot_id = if let Some(last) = last_applied_log {
            format!("{}-{}-{}", last.leader_id, last.index, snapshot_idx)
        } else {
            format!("--{}", snapshot_idx)
        };

        let meta = SnapshotMeta {
            last_log_id: last_applied_log,
            last_membership,
            snapshot_id,
        };

        let snapshot = FlareSnapshot {
            meta: meta.clone(),
            data: data.clone(),
        };

        {
            let mut current = self.current_snapshot.write().await;
            *current = Some(snapshot);
        }

        Ok(Snapshot {
            meta,
            snapshot: Box::new(Cursor::new(data)),
        })
    }
}

impl RaftLogStorage<FlareTypeConfig> for Arc<FlareStore> {
    type LogReader = Self;

    async fn get_log_state(&mut self) -> Result<LogState<FlareTypeConfig>, StorageError<FlareNodeId>> {
        let log = self.log.read().await;
        let last_serialized = log.iter().next_back().map(|(_, ent)| ent);

        let last = match last_serialized {
            None => None,
            Some(serialized) => {
                let ent: FlareEntry =
                    serde_json::from_str(serialized).map_err(|e| StorageIOError::read_logs(&e))?;
                Some(*ent.get_log_id())
            }
        };

        let last_purged = *self.last_purged_log_id.read().await;

        let last = match last {
            None => last_purged,
            Some(x) => Some(x),
        };

        Ok(LogState {
            last_purged_log_id: last_purged,
            last_log_id: last,
        })
    }

    async fn save_vote(&mut self, vote: &Vote<FlareNodeId>) -> Result<(), StorageError<FlareNodeId>> {
        let mut v = self.vote.write().await;
        *v = Some(*vote);
        Ok(())
    }

    async fn read_vote(&mut self) -> Result<Option<Vote<FlareNodeId>>, StorageError<FlareNodeId>> {
        Ok(*self.vote.read().await)
    }

    async fn save_committed(
        &mut self,
        committed: Option<FlareLogId>,
    ) -> Result<(), StorageError<FlareNodeId>> {
        let mut c = self.committed.write().await;
        *c = committed;
        Ok(())
    }

    async fn read_committed(&mut self) -> Result<Option<FlareLogId>, StorageError<FlareNodeId>> {
        Ok(*self.committed.read().await)
    }

    async fn append<I: IntoIterator<Item = FlareEntry> + Send>(
        &mut self,
        entries: I,
        callback: LogFlushed<FlareTypeConfig>,
    ) -> Result<(), StorageError<FlareNodeId>> {
        let entries: Vec<_> = entries.into_iter().collect();
        if entries.is_empty() {
            callback.log_io_completed(Ok(()));
            return Ok(());
        }

        let mut log = self.log.write().await;
        for entry in &entries {
            let s = serde_json::to_string(entry)
                .map_err(|e| StorageIOError::write_log_entry(*entry.get_log_id(), &e))?;
            log.insert(entry.log_id.index, s);
        }

        callback.log_io_completed(Ok(()));
        Ok(())
    }

    async fn truncate(&mut self, log_id: FlareLogId) -> Result<(), StorageError<FlareNodeId>> {
        let mut log = self.log.write().await;
        let keys: Vec<_> = log.range(log_id.index..).map(|(k, _)| *k).collect();
        for key in keys {
            log.remove(&key);
        }
        Ok(())
    }

    async fn purge(&mut self, log_id: FlareLogId) -> Result<(), StorageError<FlareNodeId>> {
        {
            let mut ld = self.last_purged_log_id.write().await;
            assert!(*ld <= Some(log_id));
            *ld = Some(log_id);
        }

        {
            let mut log = self.log.write().await;
            let keys: Vec<_> = log.range(..=log_id.index).map(|(k, _)| *k).collect();
            for key in keys {
                log.remove(&key);
            }
        }

        Ok(())
    }

    async fn get_log_reader(&mut self) -> Self::LogReader {
        self.clone()
    }
}

impl RaftStateMachine<FlareTypeConfig> for Arc<FlareStore> {
    type SnapshotBuilder = Self;

    async fn applied_state(
        &mut self,
    ) -> Result<(Option<FlareLogId>, StoredMembership<FlareNodeId, FlareNode>), StorageError<FlareNodeId>>
    {
        let sm = self.sm.read().await;
        Ok((sm.last_applied_log, sm.last_membership.clone()))
    }

    async fn apply<I: IntoIterator<Item = FlareEntry> + Send>(
        &mut self,
        entries: I,
    ) -> Result<Vec<FlareResponse>, StorageError<FlareNodeId>> {
        let mut res = Vec::new();
        let mut sm = self.sm.write().await;

        for entry in entries {
            sm.last_applied_log = Some(entry.log_id);

            match &entry.payload {
                EntryPayload::Blank => {
                    res.push(FlareResponse::Ok);
                }
                EntryPayload::Normal(req) => {
                    let response = apply_request(&mut sm, req, entry.log_id.index);
                    res.push(response);
                }
                EntryPayload::Membership(mem) => {
                    sm.last_membership = StoredMembership::new(Some(entry.log_id), mem.clone());
                    res.push(FlareResponse::Ok);
                }
            }
        }

        Ok(res)
    }

    async fn get_snapshot_builder(&mut self) -> Self::SnapshotBuilder {
        self.clone()
    }

    async fn begin_receiving_snapshot(
        &mut self,
    ) -> Result<Box<Cursor<Vec<u8>>>, StorageError<FlareNodeId>> {
        Ok(Box::new(Cursor::new(Vec::new())))
    }

    async fn install_snapshot(
        &mut self,
        meta: &SnapshotMeta<FlareNodeId, FlareNode>,
        snapshot: Box<Cursor<Vec<u8>>>,
    ) -> Result<(), StorageError<FlareNodeId>> {
        let new_snapshot = FlareSnapshot {
            meta: meta.clone(),
            data: snapshot.into_inner(),
        };

        // Update state machine (using bincode to match build_snapshot)
        {
            let new_sm: FlareStateMachine = bincode::deserialize(&new_snapshot.data)
                .map_err(|e| StorageIOError::read_snapshot(Some(new_snapshot.meta.signature()), &e))?;
            let mut sm = self.sm.write().await;
            *sm = new_sm;
        }

        // Update current snapshot
        let mut current = self.current_snapshot.write().await;
        *current = Some(new_snapshot);

        Ok(())
    }

    async fn get_current_snapshot(
        &mut self,
    ) -> Result<Option<Snapshot<FlareTypeConfig>>, StorageError<FlareNodeId>> {
        let current = self.current_snapshot.read().await;
        match &*current {
            Some(snapshot) => Ok(Some(Snapshot {
                meta: snapshot.meta.clone(),
                snapshot: Box::new(Cursor::new(snapshot.data.clone())),
            })),
            None => Ok(None),
        }
    }
}

/// Apply a request to the state machine
pub fn apply_request(sm: &mut FlareStateMachine, req: &FlareRequest, index: u64) -> FlareResponse {
    match req {
        FlareRequest::KvWrite {
            namespace_id,
            key,
            value,
            ts,
        } => {
            let key_tuple = (*namespace_id, key.clone());

            // Last-Write-Wins: only apply if timestamp is newer
            let should_apply = match sm.kv_data.get(&key_tuple) {
                Some((_, existing_ts)) => *ts >= *existing_ts,
                None => true,
            };

            if should_apply {
                sm.kv_data.insert(key_tuple, (value.clone(), *ts));
            }

            FlareResponse::Applied { index }
        }
        FlareRequest::KvDelete {
            namespace_id,
            key,
            ts,
        } => {
            let key_tuple = (*namespace_id, key.clone());

            // Last-Write-Wins: only apply if timestamp is newer
            let (should_apply, existed) = match sm.kv_data.get(&key_tuple) {
                Some((_, existing_ts)) => (*ts >= *existing_ts, true),
                None => (true, false),
            };

            if should_apply {
                sm.kv_data.remove(&key_tuple);
            }

            FlareResponse::DeleteResult { existed }
        }
        FlareRequest::CasWrite {
            namespace_id,
            key,
            value,
            expected_version,
            ts,
        } => {
            let key_tuple = (*namespace_id, key.clone());

            // Get current version (0 if key doesn't exist)
            let current_version = sm
                .cas_data
                .get(&key_tuple)
                .map(|(_, v, _)| *v)
                .unwrap_or(0);

            if current_version != *expected_version {
                // Version mismatch - CAS fails
                FlareResponse::CasResult {
                    success: false,
                    current_version,
                    new_version: 0,
                }
            } else {
                // Version matches - apply CAS atomically
                let new_version = current_version + 1;
                sm.cas_data
                    .insert(key_tuple, (value.clone(), new_version, *ts));
                FlareResponse::CasResult {
                    success: true,
                    current_version,
                    new_version,
                }
            }
        }
        FlareRequest::CasDelete {
            namespace_id,
            key,
            expected_version,
            ts: _,
        } => {
            let key_tuple = (*namespace_id, key.clone());

            // Get current version (0 if key doesn't exist)
            let current_version = sm
                .cas_data
                .get(&key_tuple)
                .map(|(_, v, _)| *v)
                .unwrap_or(0);

            // If expected_version is 0, delete if exists (no version check)
            // Otherwise, only delete if version matches
            let should_delete = if *expected_version == 0 {
                current_version > 0 // Key exists
            } else {
                current_version == *expected_version
            };

            if should_delete {
                sm.cas_data.remove(&key_tuple);
                FlareResponse::CasDeleteResult {
                    success: true,
                    current_version,
                    existed: true,
                }
            } else {
                FlareResponse::CasDeleteResult {
                    success: false,
                    current_version,
                    existed: current_version > 0,
                }
            }
        }
        FlareRequest::Split {
            region_id: _,
            split_key: _,
            new_region_id,
        } => {
            // Split handling would be done at a higher level
            FlareResponse::SplitCreated {
                new_region_id: *new_region_id,
            }
        }
        FlareRequest::Noop => FlareResponse::Ok,
    }
}

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

    #[tokio::test]
    async fn test_create_store() {
        let _store = FlareStore::new_arc();
    }

    #[tokio::test]
    async fn test_apply_kv_write() {
        let mut sm = FlareStateMachine::default();
        let req = FlareRequest::KvWrite {
            namespace_id: 1,
            key: b"test_key".to_vec(),
            value: b"test_value".to_vec(),
            ts: 100,
        };

        let response = apply_request(&mut sm, &req, 1);
        assert!(matches!(response, FlareResponse::Applied { index: 1 }));

        let data = sm.kv_data.get(&(1, b"test_key".to_vec()));
        assert_eq!(data, Some(&(b"test_value".to_vec(), 100)));
    }

    #[tokio::test]
    async fn test_lww_conflict_resolution() {
        let mut sm = FlareStateMachine::default();

        // First write with ts=100
        let req1 = FlareRequest::KvWrite {
            namespace_id: 1,
            key: b"key".to_vec(),
            value: b"value1".to_vec(),
            ts: 100,
        };
        apply_request(&mut sm, &req1, 1);

        // Second write with ts=50 (older, should not apply)
        let req2 = FlareRequest::KvWrite {
            namespace_id: 1,
            key: b"key".to_vec(),
            value: b"value2".to_vec(),
            ts: 50,
        };
        apply_request(&mut sm, &req2, 2);

        // Value should still be "value1"
        let data = sm.kv_data.get(&(1, b"key".to_vec()));
        assert_eq!(data, Some(&(b"value1".to_vec(), 100)));

        // Third write with ts=200 (newer, should apply)
        let req3 = FlareRequest::KvWrite {
            namespace_id: 1,
            key: b"key".to_vec(),
            value: b"value3".to_vec(),
            ts: 200,
        };
        apply_request(&mut sm, &req3, 3);

        // Value should now be "value3"
        let data = sm.kv_data.get(&(1, b"key".to_vec()));
        assert_eq!(data, Some(&(b"value3".to_vec(), 200)));
    }

    #[tokio::test]
    async fn test_apply_cas_write_success() {
        let mut sm = FlareStateMachine::default();

        // Create new key (expected version 0)
        let req = FlareRequest::CasWrite {
            namespace_id: 1,
            key: b"cas_key".to_vec(),
            value: b"value1".to_vec(),
            expected_version: 0,
            ts: 100,
        };

        let response = apply_request(&mut sm, &req, 1);
        assert!(matches!(
            response,
            FlareResponse::CasResult {
                success: true,
                current_version: 0,
                new_version: 1,
            }
        ));

        let data = sm.cas_data.get(&(1, b"cas_key".to_vec()));
        assert_eq!(data, Some(&(b"value1".to_vec(), 1, 100)));

        // Update with expected version 1
        let req2 = FlareRequest::CasWrite {
            namespace_id: 1,
            key: b"cas_key".to_vec(),
            value: b"value2".to_vec(),
            expected_version: 1,
            ts: 200,
        };

        let response2 = apply_request(&mut sm, &req2, 2);
        assert!(matches!(
            response2,
            FlareResponse::CasResult {
                success: true,
                current_version: 1,
                new_version: 2,
            }
        ));

        let data2 = sm.cas_data.get(&(1, b"cas_key".to_vec()));
        assert_eq!(data2, Some(&(b"value2".to_vec(), 2, 200)));
    }

    #[tokio::test]
    async fn test_apply_cas_write_conflict() {
        let mut sm = FlareStateMachine::default();

        // Create key
        let req1 = FlareRequest::CasWrite {
            namespace_id: 1,
            key: b"cas_key".to_vec(),
            value: b"value1".to_vec(),
            expected_version: 0,
            ts: 100,
        };
        apply_request(&mut sm, &req1, 1);

        // Try to update with wrong version (expected 0, but actual is 1)
        let req2 = FlareRequest::CasWrite {
            namespace_id: 1,
            key: b"cas_key".to_vec(),
            value: b"value2".to_vec(),
            expected_version: 0, // Wrong! Should be 1
            ts: 200,
        };

        let response = apply_request(&mut sm, &req2, 2);
        assert!(matches!(
            response,
            FlareResponse::CasResult {
                success: false,
                current_version: 1,
                new_version: 0,
            }
        ));

        // Value should remain unchanged
        let data = sm.cas_data.get(&(1, b"cas_key".to_vec()));
        assert_eq!(data, Some(&(b"value1".to_vec(), 1, 100)));
    }

    #[tokio::test]
    async fn test_apply_kv_delete() {
        let mut sm = FlareStateMachine::default();

        // First write a value
        let req_write = FlareRequest::KvWrite {
            namespace_id: 1,
            key: b"key".to_vec(),
            value: b"value".to_vec(),
            ts: 100,
        };
        apply_request(&mut sm, &req_write, 1);

        // Delete the key
        let req_delete = FlareRequest::KvDelete {
            namespace_id: 1,
            key: b"key".to_vec(),
            ts: 200,
        };
        let response = apply_request(&mut sm, &req_delete, 2);
        assert!(matches!(response, FlareResponse::DeleteResult { existed: true }));

        // Key should be deleted
        let data = sm.kv_data.get(&(1, b"key".to_vec()));
        assert_eq!(data, None);
    }

    #[tokio::test]
    async fn test_apply_kv_delete_nonexistent() {
        let mut sm = FlareStateMachine::default();

        // Delete a non-existent key
        let req_delete = FlareRequest::KvDelete {
            namespace_id: 1,
            key: b"nonexistent".to_vec(),
            ts: 100,
        };
        let response = apply_request(&mut sm, &req_delete, 1);
        assert!(matches!(response, FlareResponse::DeleteResult { existed: false }));
    }

    #[tokio::test]
    async fn test_apply_kv_delete_lww() {
        let mut sm = FlareStateMachine::default();

        // Write with ts=200
        let req_write = FlareRequest::KvWrite {
            namespace_id: 1,
            key: b"key".to_vec(),
            value: b"value".to_vec(),
            ts: 200,
        };
        apply_request(&mut sm, &req_write, 1);

        // Try to delete with older timestamp (ts=100) - should not delete
        let req_delete = FlareRequest::KvDelete {
            namespace_id: 1,
            key: b"key".to_vec(),
            ts: 100,
        };
        apply_request(&mut sm, &req_delete, 2);

        // Key should still exist (delete was ignored due to older timestamp)
        let data = sm.kv_data.get(&(1, b"key".to_vec()));
        assert_eq!(data, Some(&(b"value".to_vec(), 200)));
    }

    #[tokio::test]
    async fn test_apply_cas_delete_success() {
        let mut sm = FlareStateMachine::default();

        // Create key with CAS
        let req_write = FlareRequest::CasWrite {
            namespace_id: 1,
            key: b"cas_key".to_vec(),
            value: b"value".to_vec(),
            expected_version: 0,
            ts: 100,
        };
        apply_request(&mut sm, &req_write, 1);

        // Delete with correct version
        let req_delete = FlareRequest::CasDelete {
            namespace_id: 1,
            key: b"cas_key".to_vec(),
            expected_version: 1,
            ts: 200,
        };
        let response = apply_request(&mut sm, &req_delete, 2);
        assert!(matches!(
            response,
            FlareResponse::CasDeleteResult {
                success: true,
                current_version: 1,
                existed: true,
            }
        ));

        // Key should be deleted
        let data = sm.cas_data.get(&(1, b"cas_key".to_vec()));
        assert_eq!(data, None);
    }

    #[tokio::test]
    async fn test_apply_cas_delete_version_mismatch() {
        let mut sm = FlareStateMachine::default();

        // Create key
        let req_write = FlareRequest::CasWrite {
            namespace_id: 1,
            key: b"cas_key".to_vec(),
            value: b"value".to_vec(),
            expected_version: 0,
            ts: 100,
        };
        apply_request(&mut sm, &req_write, 1);

        // Try to delete with wrong version
        let req_delete = FlareRequest::CasDelete {
            namespace_id: 1,
            key: b"cas_key".to_vec(),
            expected_version: 99, // Wrong version
            ts: 200,
        };
        let response = apply_request(&mut sm, &req_delete, 2);
        assert!(matches!(
            response,
            FlareResponse::CasDeleteResult {
                success: false,
                current_version: 1,
                existed: true,
            }
        ));

        // Key should still exist
        let data = sm.cas_data.get(&(1, b"cas_key".to_vec()));
        assert_eq!(data, Some(&(b"value".to_vec(), 1, 100)));
    }

    #[tokio::test]
    async fn test_apply_cas_delete_if_exists() {
        let mut sm = FlareStateMachine::default();

        // Create key
        let req_write = FlareRequest::CasWrite {
            namespace_id: 1,
            key: b"cas_key".to_vec(),
            value: b"value".to_vec(),
            expected_version: 0,
            ts: 100,
        };
        apply_request(&mut sm, &req_write, 1);

        // Delete with expected_version=0 (delete if exists)
        let req_delete = FlareRequest::CasDelete {
            namespace_id: 1,
            key: b"cas_key".to_vec(),
            expected_version: 0,
            ts: 200,
        };
        let response = apply_request(&mut sm, &req_delete, 2);
        assert!(matches!(
            response,
            FlareResponse::CasDeleteResult {
                success: true,
                current_version: 1,
                existed: true,
            }
        ));

        // Key should be deleted
        let data = sm.cas_data.get(&(1, b"cas_key".to_vec()));
        assert_eq!(data, None);
    }
}
