//! Native backend for kvstore using sled
//!
//! # Runtime Requirement
//!
#![cfg(not(target_arch = "wasm32"))]
//! **A Tokio runtime must be running to use this backend.**
//! This library does not start or manage a runtime; it assumes that all async methods are called from within an existing Tokio runtime context (e.g., via `#[tokio::main]` or `tokio::test`).
//!
//! All blocking I/O is offloaded using `tokio::task::spawn_blocking`.
//!
//! # Example
//!

//! Native backend for kvstore using sled
//! Only compiled for non-wasm32 targets

#[cfg(not(target_arch = "wasm32"))]
use crate::traits::KVStore;
#[cfg(not(target_arch = "wasm32"))]
use crate::error::{KVError, Result};
#[cfg(not(target_arch = "wasm32"))]
use async_trait::async_trait;
#[cfg(not(target_arch = "wasm32"))]
use sled::Db;
#[cfg(not(target_arch = "wasm32"))]
use std::sync::Arc;

#[derive(Clone)]
pub struct NativeStore {
    db: Arc<Db>,
}

impl NativeStore {
    pub fn open(path: &str) -> Result<Self> {
        let db = sled::open(path).map_err(|e| KVError::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))?;
        Ok(Self { db: Arc::new(db) })
    }
}

#[async_trait]
#[async_trait]
impl KVStore for NativeStore {
    async fn get(&self, key: &str) -> Result<Option<Vec<u8>>> {
        let db = self.db.clone();
        let key = key.to_owned();
        tokio::task::spawn_blocking(move || {
            db.get(&key)
                .map_err(|e| KVError::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))
                .map(|opt| opt.map(|ivec| ivec.to_vec()))
        })
        .await
        .map_err(|e| KVError::Other(format!("Join error: {e}")))?
    }
    async fn set(&self, key: &str, value: &[u8]) -> Result<()> {
        let db = self.db.clone();
        let key = key.to_owned();
        let value = value.to_vec();
        tokio::task::spawn_blocking(move || {
            db.insert(&key, value)
                .map_err(|e| KVError::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))?;
            db.flush().map_err(|e| KVError::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))?;
            Ok(())
        })
        .await
        .map_err(|e| KVError::Other(format!("Join error: {e}")))?
    }
    async fn remove(&self, key: &str) -> Result<()> {
        let db = self.db.clone();
        let key = key.to_owned();
        tokio::task::spawn_blocking(move || {
            db.remove(&key)
                .map_err(|e| KVError::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))?;
            db.flush().map_err(|e| KVError::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))?;
            Ok(())
        })
        .await
        .map_err(|e| KVError::Other(format!("Join error: {e}")))?
    }
    async fn contains_key(&self, key: &str) -> Result<bool> {
        let db = self.db.clone();
        let key = key.to_owned();
        tokio::task::spawn_blocking(move || {
            Ok(db.contains_key(&key)
                .map_err(|e| KVError::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))?)
        })
        .await
        .map_err(|e| KVError::Other(format!("Join error: {e}")))?
    }

    async fn keys(&self) -> Result<Vec<String>> {
        let db = self.db.clone();
        tokio::task::spawn_blocking(move || {
            let mut keys = Vec::new();
            for result in db.iter() {
                let (key, _) = result.map_err(|e| KVError::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))?;
                keys.push(String::from_utf8_lossy(&key).to_string());
            }
            Ok(keys)
        })
        .await
        .map_err(|e| KVError::Other(format!("Join error: {e}")))?
    }

    async fn clear(&self) -> Result<()> {
        let db = self.db.clone();
        tokio::task::spawn_blocking(move || {
            db.clear().map_err(|e| KVError::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))?;
            db.flush().map_err(|e| KVError::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))?;
            Ok(())
        })
        .await
        .map_err(|e| KVError::Other(format!("Join error: {e}")))?
    }
}
