//! Store operation helpers with timeout protection (P5.1 Security Hardening).
//!
//! Wraps all store.get()/put() operations with a 5-second timeout to prevent
//! slow database operations from blocking the entire request.

use tokio::time::{timeout, Duration};
use tracing::error;

use crate::error::ApiError;

/// Wrapper for store.get() with 5s timeout.
///
/// # Arguments
/// * `store` - The KV store to query
/// * `key` - The key to retrieve (must be AsRef<[u8]> + Debug for logging)
///
/// # Returns
/// * `Ok(Some(value))` - Key found, value returned
/// * `Ok(None)` - Key not found
/// * `Err(ApiError::Timeout)` - Operation exceeded 5s timeout
/// * `Err(ApiError::Storage)` - Store operation failed
///
/// # Metrics
/// Increments `stemedb_operation_timeouts_total{operation="store_get"}` on timeout.
pub async fn store_get_with_timeout<S, K>(store: &S, key: &K) -> Result<Option<Vec<u8>>, ApiError>
where
    S: stemedb_storage::KVStore,
    K: AsRef<[u8]> + std::fmt::Debug,
{
    timeout(Duration::from_secs(5), store.get(key.as_ref()))
        .await
        .map_err(|_| {
            error!(key = ?key, "Store get operation timed out after 5s");
            metrics::counter!("stemedb_operation_timeouts_total", "operation" => "store_get")
                .increment(1);
            ApiError::Timeout("Store get operation exceeded 5s timeout".to_string())
        })?
        .map_err(ApiError::from)
}

/// Wrapper for store.put() with 5s timeout.
///
/// # Arguments
/// * `store` - The KV store to write to
/// * `key` - The key to write (must be AsRef<[u8]> + Debug for logging)
/// * `value` - The value to write
///
/// # Returns
/// * `Ok(())` - Write succeeded
/// * `Err(ApiError::Timeout)` - Operation exceeded 5s timeout
/// * `Err(ApiError::Storage)` - Store operation failed
///
/// # Metrics
/// Increments `stemedb_operation_timeouts_total{operation="store_put"}` on timeout.
pub async fn store_put_with_timeout<S, K, V>(store: &S, key: &K, value: &V) -> Result<(), ApiError>
where
    S: stemedb_storage::KVStore,
    K: AsRef<[u8]> + std::fmt::Debug,
    V: AsRef<[u8]>,
{
    timeout(Duration::from_secs(5), store.put(key.as_ref(), value.as_ref()))
        .await
        .map_err(|_| {
            error!(key = ?key, "Store put operation timed out after 5s");
            metrics::counter!("stemedb_operation_timeouts_total", "operation" => "store_put")
                .increment(1);
            ApiError::Timeout("Store put operation exceeded 5s timeout".to_string())
        })?
        .map_err(ApiError::from)
}
