//! Thin `ToolError`-mapped wrapper over `vault_service::KmsService`.
//!
//! Tools call these methods and use `?` — no `anyhow` conversion needed at
//! call sites. The underlying `KmsError` is mapped to `ToolError::Backend`.

use crate::protocol::ToolError;
use std::sync::Arc;
use vault_service::{DataKey, EncryptionContext, KmsService, KeySpec};

/// Shareable vault source. Construct once, wrap in `Arc`, pass to tools via
/// `Context` or directly in the tool's initialiser.
#[derive(Clone)]
pub struct VaultSource {
    inner: Arc<KmsService>,
}

impl std::fmt::Debug for VaultSource {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("VaultSource")
            .field("backend", &self.inner.get_backend_name())
            .finish()
    }
}

impl VaultSource {
    pub fn new(service: KmsService) -> Self {
        Self { inner: Arc::new(service) }
    }

    pub fn from_arc(service: Arc<KmsService>) -> Self {
        Self { inner: service }
    }

    /// Encrypt `plaintext` under `context`.
    pub async fn encrypt(
        &self,
        plaintext: &[u8],
        context: &EncryptionContext,
    ) -> Result<Vec<u8>, ToolError> {
        self.inner
            .encrypt(plaintext, context)
            .await
            .map_err(|e| ToolError::Backend(anyhow::anyhow!("vault encrypt: {e}")))
    }

    /// Decrypt `ciphertext` under `context`.
    pub async fn decrypt(
        &self,
        ciphertext: &[u8],
        context: &EncryptionContext,
    ) -> Result<Vec<u8>, ToolError> {
        self.inner
            .decrypt(ciphertext, context)
            .await
            .map_err(|e| ToolError::Backend(anyhow::anyhow!("vault decrypt: {e}")))
    }

    /// Generate a new data key for `key_spec`.
    pub async fn generate_data_key(&self, key_spec: &KeySpec) -> Result<DataKey, ToolError> {
        self.inner
            .generate_data_key(key_spec)
            .await
            .map_err(|e| ToolError::Backend(anyhow::anyhow!("vault generate_data_key: {e}")))
    }

    /// Returns `Ok(true)` when the vault backend is reachable.
    pub async fn health(&self) -> Result<bool, ToolError> {
        self.inner
            .health_check()
            .await
            .map_err(|e| ToolError::Backend(anyhow::anyhow!("vault health: {e}")))
    }

    /// Backend name (e.g. `"age"`, `"aws-kms"`, …).
    pub fn backend_name(&self) -> String {
        self.inner.get_backend_name()
    }
}

// No unit tests here — KmsService requires a real backend (age keys, AWS, …).
// Integration tests live in the vault-service crate itself.
