use async_trait::async_trait;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use crate::traits::{CerebroError, KVStore, Result};

/// A fast, in-memory Key-Value store for Working Memory and immediate state.
#[derive(Clone, Default)]
pub struct MemoryKVStore {
    data: Arc<RwLock<HashMap<String, String>>>,
}

impl MemoryKVStore {
    pub fn new() -> Self {
        Self { data: Arc::new(RwLock::new(HashMap::new())) }
    }
}

#[async_trait]
impl KVStore for MemoryKVStore {
    async fn set(&self, key: &str, value: &str) -> Result<()> {
        let mut store = self.data.write().map_err(|_| CerebroError::StorageError("Lock poisoned".into()))?;
        store.insert(key.to_string(), value.to_string());
        Ok(())
    }

    async fn get(&self, key: &str) -> Result<Option<String>> {
        let store = self.data.read().map_err(|_| CerebroError::StorageError("Lock poisoned".into()))?;
        Ok(store.get(key).cloned())
    }
}

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

    #[tokio::test]
    async fn test_set_and_get() {
        let store = MemoryKVStore::new();
        store.set("session_id", "12345").await.unwrap();
        
        let val = store.get("session_id").await.unwrap();
        assert_eq!(val, Some("12345".to_string()));

        let empty = store.get("missing").await.unwrap();
        assert_eq!(empty, None);
    }
}
