//! Encryption service for securing sensitive data

use anyhow::{Result, anyhow};
use ring::aead::{AES_256_GCM, LessSafeKey, UnboundKey, Nonce, NONCE_LEN};
use ring::rand::{SecureRandom, SystemRandom};
use ring::pbkdf2;
use ring::digest::{Context, SHA256};
use serde::{Serialize, Deserialize};
use std::sync::{Arc, RwLock};
use std::collections::HashMap;
use base64::{Engine as _, engine::general_purpose};
use keyring::{Entry, Error as KeyringError};
use std::time::{SystemTime, UNIX_EPOCH};
use tokio::fs;
use uuid::Uuid;

use crate::types::EncryptionConfig;

/// Encrypted data structure
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EncryptedData {
    pub data: String,        // Base64 encoded encrypted data
    pub nonce: String,       // Base64 encoded nonce
    pub algorithm: String,
    pub version: String,
    pub timestamp: Option<String>,
}

/// Embedded encryption data for vectors
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EncryptedEmbedding {
    pub data: Vec<f32>,
    pub dimension: usize,
    pub embedding_type: String,
    pub algorithm: String,
    pub timestamp: String,
}

/// Key derivation result
#[derive(Debug, Clone)]
pub struct DerivedKey {
    pub key: Vec<u8>,
    pub salt: String,
}

/// Encryption service for handling data encryption and decryption
pub struct EncryptionService {
    config: EncryptionConfig,
    main_key: RwLock<Arc<LessSafeKey>>,
    embedding_key: RwLock<Arc<LessSafeKey>>,
    sync_key: RwLock<Arc<LessSafeKey>>,
    rng: SystemRandom,
    service_name: String,
    key_name: String,
    base_path: String,
    initialized: RwLock<bool>,
}

impl EncryptionService {
    /// Create a new encryption service
    pub async fn new(config: &EncryptionConfig, base_path: &str) -> Result<Self> {
        let service = Self {
            config: config.clone(),
            base_path: base_path.to_string(),
            main_key: RwLock::new(Arc::new(Self::create_dummy_key()?)),
            embedding_key: RwLock::new(Arc::new(Self::create_dummy_key()?)),
            sync_key: RwLock::new(Arc::new(Self::create_dummy_key()?)),
            rng: SystemRandom::new(),
            service_name: "cloudops-storage-service".to_string(),
            key_name: "encryption-key".to_string(),
            initialized: RwLock::new(false),
        };
        
        Ok(service)
    }
    
    /// Initialize the encryption service with OS keychain integration
    pub async fn initialize(&self) -> Result<()> {
        match self.get_or_create_keys().await {
            Ok((main_key, embedding_key, sync_key)) => {
                *self.main_key.write().unwrap() = Arc::new(main_key);
                *self.embedding_key.write().unwrap() = Arc::new(embedding_key);
                *self.sync_key.write().unwrap() = Arc::new(sync_key);
                *self.initialized.write().unwrap() = true;
                println!("✅ EncryptionService initialized with OS Keychain integration");
                Ok(())
            }
            Err(e) => {
                eprintln!("❌ Failed to initialize EncryptionService: {}", e);
                Err(anyhow!("Failed to initialize encryption service: {}", e))
            }
        }
    }
    
    /// Get existing keys from OS Keychain or create new ones
    async fn get_or_create_keys(&self) -> Result<(LessSafeKey, LessSafeKey, LessSafeKey)> {
        let main_key = self.get_or_create_key("main").await?;
        let embedding_key = self.get_or_create_key("embedding").await?;
        let sync_key = self.get_or_create_key("sync").await?;
        
        Ok((main_key, embedding_key, sync_key))
    }
    
    /// Get existing key from OS Keychain or create new one
    async fn get_or_create_key(&self, key_type: &str) -> Result<LessSafeKey> {
        let key_name = format!("{}-{}", self.key_name, key_type);

        // First try to get from keychain
        match self.get_key_from_keychain(&key_name).await {
            Ok(key_bytes) => {
                if key_bytes.len() == 32 {
                    println!("🔑 Retrieved existing {} key from OS Keychain", key_type);
                    return Self::create_key_from_bytes(&key_bytes);
                }
            }
            Err(_) => {
                // Key doesn't exist or access failed, try backup file
                if let Ok(key_bytes) = self.get_key_from_backup_file(key_type).await {
                    if key_bytes.len() == 32 {
                        println!("🔑 Retrieved {} key from backup file", key_type);
                        // Restore to keychain for future use
                        let _ = self.store_key_in_keychain(&key_name, &key_bytes).await;
                        return Self::create_key_from_bytes(&key_bytes);
                    }
                }
            }
        }

        // Create new key
        let key_bytes = Self::generate_key()?;

        // Store in keychain (primary)
        if let Err(e) = self.store_key_in_keychain(&key_name, &key_bytes).await {
            eprintln!("⚠️ Keychain storage failed for {}: {}. Using session-only key.", key_type, e);
        } else {
            println!("🔑 Created new {} key and stored in OS Keychain", key_type);
        }

        // Store backup file (secondary)
        if let Err(e) = self.store_key_backup_file(key_type, &key_bytes).await {
            eprintln!("⚠️ Backup file storage failed for {}: {}", key_type, e);
        } else {
            println!("💾 Backed up {} key to file", key_type);
        }
        
        Self::create_key_from_bytes(&key_bytes)
    }
    
    /// Get key from OS keychain
    async fn get_key_from_keychain(&self, key_name: &str) -> Result<Vec<u8>> {
        let entry = Entry::new(&self.service_name, key_name)?;
        let key_b64 = entry.get_password()?;
        let key_bytes = general_purpose::STANDARD.decode(key_b64)?;
        Ok(key_bytes)
    }
    
    /// Store key in OS keychain
    async fn store_key_in_keychain(&self, key_name: &str, key_bytes: &[u8]) -> Result<()> {
        let entry = Entry::new(&self.service_name, key_name)?;
        let key_b64 = general_purpose::STANDARD.encode(key_bytes);
        entry.set_password(&key_b64)?;
        Ok(())
    }

    /// Get the backup directory path
    fn get_backup_keys_dir(&self) -> std::path::PathBuf {
        std::path::PathBuf::from(&self.base_path).join("keys")
    }

    /// Store key in backup file
    async fn store_key_backup_file(&self, key_type: &str, key_bytes: &[u8]) -> Result<()> {
        let keys_dir = self.get_backup_keys_dir();
        tokio::fs::create_dir_all(&keys_dir).await?;

        let key_file = keys_dir.join(format!("{}_key.enc", key_type));
        let key_b64 = general_purpose::STANDARD.encode(key_bytes);

        tokio::fs::write(&key_file, key_b64).await?;
        Ok(())
    }

    /// Get key from backup file
    async fn get_key_from_backup_file(&self, key_type: &str) -> Result<Vec<u8>> {
        let keys_dir = self.get_backup_keys_dir();
        let key_file = keys_dir.join(format!("{}_key.enc", key_type));

        if !key_file.exists() {
            return Err(anyhow!("Backup key file not found"));
        }

        let key_b64 = tokio::fs::read_to_string(&key_file).await?;
        let key_bytes = general_purpose::STANDARD.decode(key_b64.trim())?;
        Ok(key_bytes)
    }
    
    /// Create a LessSafeKey from bytes
    fn create_key_from_bytes(key_bytes: &[u8]) -> Result<LessSafeKey> {
        let unbound_key = UnboundKey::new(&AES_256_GCM, key_bytes)
            .map_err(|_| anyhow!("Failed to create encryption key"))?;
        Ok(LessSafeKey::new(unbound_key))
    }
    
    /// Create a dummy key for initialization
    fn create_dummy_key() -> Result<LessSafeKey> {
        let key_bytes = Self::generate_key()?;
        Self::create_key_from_bytes(&key_bytes)
    }
    
    /// Generate a secure 256-bit key
    fn generate_key() -> Result<[u8; 32]> {
        let rng = SystemRandom::new();
        let mut key_bytes = [0u8; 32];
        rng.fill(&mut key_bytes)
            .map_err(|_| anyhow!("Failed to generate random key"))?;
        Ok(key_bytes)
    }
    
    /// Encrypt content using main key (Business Architecture API)
    pub async fn encrypt_content(&self, content: &str) -> Result<String> {
        if !self.config.enable_content_encryption {
            return Ok(content.to_string());
        }
        
        self.ensure_initialized()?;
        let main_key = self.main_key.read().unwrap().clone();
        let encrypted = self.encrypt_with_key(content.as_bytes(), &main_key).await?;
        Ok(encrypted)
    }
    
    /// Decrypt content using main key (Business Architecture API)
    pub async fn decrypt_content(&self, encrypted_content: &str) -> Result<String> {
        if !self.config.enable_content_encryption {
            return Ok(encrypted_content.to_string());
        }
        
        self.ensure_initialized()?;
        let main_key = self.main_key.read().unwrap().clone();
        
        // First try Node.js compatible base64 format
        if let Ok(decrypted_bytes) = self.decrypt_with_key_base64(encrypted_content, &main_key).await {
            return String::from_utf8(decrypted_bytes)
                .map_err(|e| anyhow!("Invalid UTF-8 in decrypted content: {}", e));
        }
        
        // Fallback: Try legacy JSON format
        if let Ok(encrypted_data) = serde_json::from_str::<EncryptedData>(encrypted_content) {
            let decrypted_bytes = self.decrypt_with_key(&encrypted_data, &main_key).await?;
            String::from_utf8(decrypted_bytes).map_err(|e| anyhow!("Invalid UTF-8 in decrypted content: {}", e))
        } else {
            // If both fail, assume it's plain text
            Ok(encrypted_content.to_string())
        }
    }
    
    /// Legacy method for backward compatibility
    pub async fn encrypt(&self, plaintext: &str) -> Result<String> {
        self.encrypt_content(plaintext).await
    }
    
    /// Legacy method for backward compatibility
    pub async fn decrypt(&self, encrypted_data: &str) -> Result<String> {
        self.decrypt_content(encrypted_data).await
    }
    
    /// Synchronous encrypt method (Node.js API compatibility)
    /// Business Architecture API - matches Node.js encrypt(plaintext) exactly
    pub fn encrypt_sync(&self, plaintext: &str) -> Result<String> {
        if !self.config.enable_content_encryption {
            return Ok(plaintext.to_string());
        }
        
        self.ensure_initialized()?;
        let main_key = self.main_key.read().unwrap().clone();
        
        // Use synchronous encryption (ring operations are actually sync)
        self.encrypt_with_key_sync(plaintext.as_bytes(), &main_key)
    }
    
    /// Synchronous decrypt method (Node.js API compatibility) 
    /// Business Architecture API - matches Node.js decrypt(encryptedData) exactly
    pub fn decrypt_sync(&self, encrypted_content: &str) -> Result<String> {
        if !self.config.enable_content_encryption {
            return Ok(encrypted_content.to_string());
        }
        
        self.ensure_initialized()?;
        let main_key = self.main_key.read().unwrap().clone();
        
        // First try Node.js compatible base64 format
        if let Ok(decrypted_bytes) = self.decrypt_with_key_base64_sync(encrypted_content, &main_key) {
            return String::from_utf8(decrypted_bytes)
                .map_err(|e| anyhow!("Invalid UTF-8 in decrypted content: {}", e));
        }
        
        // Fallback: Try legacy JSON format
        if let Ok(encrypted_data) = serde_json::from_str::<EncryptedData>(encrypted_content) {
            let decrypted_bytes = self.decrypt_with_key_sync(&encrypted_data, &main_key)?;
            String::from_utf8(decrypted_bytes).map_err(|e| anyhow!("Invalid UTF-8 in decrypted content: {}", e))
        } else {
            // If both fail, assume it's plain text
            Ok(encrypted_content.to_string())
        }
    }
    
    /// Encrypt metadata if encryption is enabled
    pub async fn encrypt_metadata(&self, metadata: &serde_json::Value) -> Result<serde_json::Value> {
        if !self.config.enable_metadata_encryption {
            return Ok(metadata.clone());
        }
        
        let metadata_str = serde_json::to_string(metadata)?;
        let encrypted = self.encrypt(&metadata_str).await?;
        
        let mut result = serde_json::json!({});
        result["_encrypted_metadata"] = serde_json::Value::String(encrypted); // Direct base64 string, not JSON wrapped
        result["_encrypted"] = serde_json::Value::Bool(true);
        
        Ok(result)
    }
    
    /// Decrypt metadata if it's encrypted
    pub async fn decrypt_metadata(&self, metadata: &serde_json::Value) -> Result<serde_json::Value> {
        if !self.config.enable_metadata_encryption {
            return Ok(metadata.clone());
        }
        
        if let Some(encrypted_str) = metadata.get("_encrypted_metadata") {
            if let Some(encrypted_str) = encrypted_str.as_str() {
                let decrypted_str = self.decrypt(encrypted_str).await?; // Use decrypt method which handles both formats
                let decrypted_metadata: serde_json::Value = serde_json::from_str(&decrypted_str)?;
                return Ok(decrypted_metadata);
            }
        }
        
        // If not encrypted, return as-is
        Ok(metadata.clone())
    }
    
    /// Encrypt embedding vectors using specialized embedding key
    pub async fn encrypt_embedding(&self, embedding: &[f32]) -> Result<String> {
        self.ensure_initialized()?;
        
        // Convert embedding array to JSON with metadata
        let embedding_data = EncryptedEmbedding {
            data: embedding.to_vec(),
            dimension: embedding.len(),
            embedding_type: "float32".to_string(),
            algorithm: self.config.algorithm.clone(),
            timestamp: SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap()
                .as_secs()
                .to_string(),
        };
        
        let embedding_json = serde_json::to_string(&embedding_data)?;
        let embedding_key = self.embedding_key.read().unwrap().clone();
        let encrypted = self.encrypt_with_key(embedding_json.as_bytes(), &embedding_key).await?;
        
        Ok(encrypted)
    }
    
    /// Decrypt embedding vectors using specialized embedding key
    pub async fn decrypt_embedding(&self, encrypted_embedding: &str) -> Result<Vec<f32>> {
        self.ensure_initialized()?;
        
        let encrypted_data: EncryptedData = serde_json::from_str(encrypted_embedding)?;
        let embedding_key = self.embedding_key.read().unwrap().clone();
        let decrypted_bytes = self.decrypt_with_key(&encrypted_data, &embedding_key).await?;
        let decrypted_str = String::from_utf8(decrypted_bytes)?;
        let embedding_data: EncryptedEmbedding = serde_json::from_str(&decrypted_str)?;
        
        Ok(embedding_data.data)
    }
    
    /// Encrypt data for sync (backup) operations
    pub async fn encrypt_for_sync(&self, data: &serde_json::Value) -> Result<String> {
        self.ensure_initialized()?;
        
        let data_str = serde_json::to_string(data)?;
        let sync_key = self.sync_key.read().unwrap().clone();
        let encrypted = self.encrypt_with_key(data_str.as_bytes(), &sync_key).await?;
        
        Ok(encrypted)
    }
    
    /// Decrypt data from sync operations
    pub async fn decrypt_from_sync(&self, encrypted_data: &str) -> Result<serde_json::Value> {
        self.ensure_initialized()?;
        let sync_key = self.sync_key.read().unwrap().clone();
        
        // First try Node.js compatible base64 format
        if let Ok(decrypted_bytes) = self.decrypt_with_key_base64(encrypted_data, &sync_key).await {
            let decrypted_str = String::from_utf8(decrypted_bytes)?;
            let data: serde_json::Value = serde_json::from_str(&decrypted_str)?;
            return Ok(data);
        }
        
        // Fallback: Try legacy JSON format
        let encrypted: EncryptedData = serde_json::from_str(encrypted_data)?;
        let decrypted_bytes = self.decrypt_with_key(&encrypted, &sync_key).await?;
        let decrypted_str = String::from_utf8(decrypted_bytes)?;
        let data: serde_json::Value = serde_json::from_str(&decrypted_str)?;
        
        Ok(data)
    }
    
    /// Low-level encrypt function using specified key
    async fn encrypt_with_key(&self, data: &[u8], key: &LessSafeKey) -> Result<String> {
        // Generate random IV for each encryption
        let mut nonce_bytes = [0u8; NONCE_LEN];
        self.rng.fill(&mut nonce_bytes)
            .map_err(|_| anyhow!("Failed to generate nonce"))?;
        
        let nonce = Nonce::assume_unique_for_key(nonce_bytes);
        
        let mut in_out = data.to_vec();
        key.seal_in_place_append_tag(nonce, ring::aead::Aad::empty(), &mut in_out)
            .map_err(|_| anyhow!("Failed to encrypt data"))?;
        
        // Node.js format: IV + encrypted_data + auth_tag (already appended by seal_in_place_append_tag)
        // The auth tag is already appended to in_out by ring, so we just combine IV + encrypted_data_with_tag
        let mut combined = Vec::new();
        combined.extend_from_slice(&nonce_bytes); // IV first
        combined.extend_from_slice(&in_out);      // encrypted_data + auth_tag
        
        // Return as base64 (Node.js compatible format)
        Ok(general_purpose::STANDARD.encode(&combined))
    }
    
    /// Low-level decrypt function for Node.js compatible base64 format
    async fn decrypt_with_key_base64(&self, encrypted_base64: &str, key: &LessSafeKey) -> Result<Vec<u8>> {
        // Decode from base64
        let combined = general_purpose::STANDARD.decode(encrypted_base64)
            .map_err(|e| anyhow!("Failed to decode base64 encrypted data: {}", e))?;
        
        if combined.len() < NONCE_LEN + 16 { // minimum: IV + some data + auth tag (16 bytes)
            return Err(anyhow!("Invalid encrypted data format"));
        }
        
        // Extract components (Node.js format: IV + encrypted_data + auth_tag)
        let nonce_bytes = &combined[0..NONCE_LEN];
        let mut encrypted_with_tag = combined[NONCE_LEN..].to_vec();
        
        let mut nonce_array = [0u8; NONCE_LEN];
        nonce_array.copy_from_slice(nonce_bytes);
        let nonce = Nonce::assume_unique_for_key(nonce_array);
        
        let plaintext = key.open_in_place(nonce, ring::aead::Aad::empty(), &mut encrypted_with_tag)
            .map_err(|_| anyhow!("Failed to decrypt data"))?;
        
        Ok(plaintext.to_vec())
    }

    /// Low-level decrypt function using specified key (legacy JSON format)
    async fn decrypt_with_key(&self, encrypted: &EncryptedData, key: &LessSafeKey) -> Result<Vec<u8>> {
        let encrypted_data = general_purpose::STANDARD.decode(&encrypted.data)
            .map_err(|e| anyhow!("Failed to decode encrypted data: {}", e))?;
        
        let nonce_bytes = general_purpose::STANDARD.decode(&encrypted.nonce)
            .map_err(|e| anyhow!("Failed to decode nonce: {}", e))?;
        
        if nonce_bytes.len() != NONCE_LEN {
            return Err(anyhow!("Invalid nonce length"));
        }
        
        let mut nonce_array = [0u8; NONCE_LEN];
        nonce_array.copy_from_slice(&nonce_bytes);
        let nonce = Nonce::assume_unique_for_key(nonce_array);
        
        let mut in_out = encrypted_data;
        let plaintext = key.open_in_place(nonce, ring::aead::Aad::empty(), &mut in_out)
            .map_err(|_| anyhow!("Failed to decrypt data"))?;
        
        Ok(plaintext.to_vec())
    }
    
    /// Derive key from password using PBKDF2
    pub async fn derive_key_from_password(&self, password: &str, salt: Option<&str>) -> Result<DerivedKey> {
        let salt_bytes = if let Some(salt) = salt {
            hex::decode(salt)?
        } else {
            let mut salt_bytes = [0u8; 16];
            self.rng.fill(&mut salt_bytes).map_err(|e| anyhow::anyhow!("Failed to generate salt: {}", e))?;
            salt_bytes.to_vec()
        };
        
        let mut key_bytes = [0u8; 32];
        pbkdf2::derive(
            pbkdf2::PBKDF2_HMAC_SHA256,
            std::num::NonZeroU32::new(100_000).unwrap(),
            &salt_bytes,
            password.as_bytes(),
            &mut key_bytes,
        );
        
        Ok(DerivedKey {
            key: key_bytes.to_vec(),
            salt: hex::encode(&salt_bytes),
        })
    }
    
    /// Hash data using SHA-256
    pub fn hash(&self, data: &[u8]) -> String {
        let mut context = Context::new(&SHA256);
        context.update(data);
        let digest = context.finish();
        hex::encode(digest.as_ref())
    }
    
    /// Generate secure random ID
    pub fn generate_secure_id(&self, length: Option<usize>) -> Result<String> {
        let len = length.unwrap_or(32);
        let mut bytes = vec![0u8; len];
        self.rng.fill(&mut bytes).map_err(|e| anyhow::anyhow!("Failed to generate secure ID: {}", e))?;
        Ok(hex::encode(&bytes))
    }
    
    /// Encrypt and encode file
    pub async fn encrypt_file(&self, file_path: &str) -> Result<String> {
        self.ensure_initialized()?;
        
        let file_data = fs::read(file_path).await?;
        let file_value = serde_json::json!({
            "data": general_purpose::STANDARD.encode(&file_data),
            "filename": std::path::Path::new(file_path)
                .file_name()
                .and_then(|s| s.to_str())
                .unwrap_or("unknown"),
            "size": file_data.len(),
            "timestamp": SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap()
                .as_secs()
        });
        
        self.encrypt_for_sync(&file_value).await
    }
    
    /// Decrypt and save file
    pub async fn decrypt_file(&self, encrypted_data: &str, output_path: &str) -> Result<bool> {
        self.ensure_initialized()?;
        
        let decrypted_value = self.decrypt_from_sync(encrypted_data).await?;
        
        if let Some(data_b64) = decrypted_value.get("data").and_then(|v| v.as_str()) {
            let file_data = general_purpose::STANDARD.decode(data_b64)?;
            fs::write(output_path, file_data).await?;
            Ok(true)
        } else {
            Err(anyhow!("Invalid file data format"))
        }
    }
    
    /// Shutdown the service
    pub async fn shutdown(&self) -> Result<()> {
        // Any cleanup logic here
        Ok(())
    }
    
    /// Check if content encryption is enabled
    pub fn is_content_encryption_enabled(&self) -> bool {
        self.config.enable_content_encryption
    }
    
    /// Check if metadata encryption is enabled
    pub fn is_metadata_encryption_enabled(&self) -> bool {
        self.config.enable_metadata_encryption
    }
    
    /// Check if embedding encryption is enabled
    pub fn is_embedding_encryption_enabled(&self) -> bool {
        self.config.enable_embedding_encryption
    }
    
    /// Check if encryption is properly initialized
    pub fn is_initialized(&self) -> bool {
        *self.initialized.read().unwrap()
    }
    
    /// Get encryption status for health checks
    pub fn get_status(&self) -> HashMap<String, serde_json::Value> {
        let mut status = HashMap::new();
        status.insert("initialized".to_string(), serde_json::Value::Bool(self.is_initialized()));
        status.insert("algorithm".to_string(), serde_json::Value::String("aes-256-gcm".to_string()));
        status.insert("key_length".to_string(), serde_json::Value::Number(serde_json::Number::from(256)));
        status.insert("keychain_service".to_string(), serde_json::Value::String(self.service_name.clone()));
        status.insert("content_encryption".to_string(), serde_json::Value::Bool(self.config.enable_content_encryption));
        status.insert("metadata_encryption".to_string(), serde_json::Value::Bool(self.config.enable_metadata_encryption));
        status.insert("embedding_encryption".to_string(), serde_json::Value::Bool(self.config.enable_embedding_encryption));
        status
    }
    
    /// Ensure service is initialized
    fn ensure_initialized(&self) -> Result<()> {
        if !*self.initialized.read().unwrap() {
            return Err(anyhow!("Encryption service must be initialized before use"));
        }
        Ok(())
    }
    
    // ============ SYNCHRONOUS HELPER METHODS (Node.js API compatibility) ============
    
    /// Synchronous encrypt with key (Node.js compatible)
    fn encrypt_with_key_sync(&self, data: &[u8], key: &LessSafeKey) -> Result<String> {
        // Generate random IV for each encryption (Node.js uses 12 bytes for GCM)
        let mut nonce_bytes = [0u8; NONCE_LEN];
        self.rng.fill(&mut nonce_bytes)
            .map_err(|_| anyhow!("Failed to generate nonce"))?;
        
        let nonce = Nonce::assume_unique_for_key(nonce_bytes);
        
        let mut in_out = data.to_vec();
        key.seal_in_place_append_tag(nonce, ring::aead::Aad::empty(), &mut in_out)
            .map_err(|_| anyhow!("Failed to encrypt data"))?;
        
        // Node.js format: IV + encrypted_data + auth_tag (already appended by seal_in_place_append_tag)
        let mut combined = Vec::new();
        combined.extend_from_slice(&nonce_bytes); // IV first
        combined.extend_from_slice(&in_out);      // encrypted_data + auth_tag
        
        // Return as base64 (Node.js compatible format)
        Ok(general_purpose::STANDARD.encode(&combined))
    }
    
    /// Synchronous decrypt with key base64 (Node.js compatible)
    fn decrypt_with_key_base64_sync(&self, encrypted_base64: &str, key: &LessSafeKey) -> Result<Vec<u8>> {
        // Decode from base64
        let combined = general_purpose::STANDARD.decode(encrypted_base64)
            .map_err(|e| anyhow!("Failed to decode base64 encrypted data: {}", e))?;
        
        if combined.len() < NONCE_LEN + 16 { // minimum: IV + some data + auth tag (16 bytes)
            return Err(anyhow!("Invalid encrypted data format"));
        }
        
        // Extract components (Node.js format: IV + encrypted_data + auth_tag)
        let nonce_bytes = &combined[0..NONCE_LEN];
        let mut encrypted_with_tag = combined[NONCE_LEN..].to_vec();
        
        let mut nonce_array = [0u8; NONCE_LEN];
        nonce_array.copy_from_slice(nonce_bytes);
        let nonce = Nonce::assume_unique_for_key(nonce_array);
        
        let plaintext = key.open_in_place(nonce, ring::aead::Aad::empty(), &mut encrypted_with_tag)
            .map_err(|_| anyhow!("Failed to decrypt data"))?;
        
        Ok(plaintext.to_vec())
    }
    
    /// Synchronous decrypt with key (legacy JSON format)
    fn decrypt_with_key_sync(&self, encrypted: &EncryptedData, key: &LessSafeKey) -> Result<Vec<u8>> {
        let encrypted_data = general_purpose::STANDARD.decode(&encrypted.data)
            .map_err(|e| anyhow!("Failed to decode encrypted data: {}", e))?;
        
        let nonce_bytes = general_purpose::STANDARD.decode(&encrypted.nonce)
            .map_err(|e| anyhow!("Failed to decode nonce: {}", e))?;
        
        if nonce_bytes.len() != NONCE_LEN {
            return Err(anyhow!("Invalid nonce length"));
        }
        
        let mut nonce_array = [0u8; NONCE_LEN];
        nonce_array.copy_from_slice(&nonce_bytes);
        let nonce = Nonce::assume_unique_for_key(nonce_array);
        
        let mut in_out = encrypted_data;
        let plaintext = key.open_in_place(nonce, ring::aead::Aad::empty(), &mut in_out)
            .map_err(|_| anyhow!("Failed to decrypt data"))?;
        
        Ok(plaintext.to_vec())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[tokio::test]
    async fn test_content_encryption() {
        let config = EncryptionConfig {
            enable_content_encryption: true,
            ..Default::default()
        };
        
        let mut service = EncryptionService::new(&config, "./test").await.unwrap();
        service.initialize().await.unwrap();
        
        let original = "Hello, World!";
        
        let encrypted = service.encrypt_content(original).await.unwrap();
        assert_ne!(encrypted, original);
        
        let decrypted = service.decrypt_content(&encrypted).await.unwrap();
        assert_eq!(decrypted, original);
    }
    
    #[tokio::test]
    async fn test_metadata_encryption() {
        let config = EncryptionConfig {
            enable_metadata_encryption: true,
            ..Default::default()
        };
        
        let mut service = EncryptionService::new(&config, "./test").await.unwrap();
        service.initialize().await.unwrap();
        
        let original = serde_json::json!({"key": "value", "number": 42});
        
        let encrypted = service.encrypt_metadata(&original).await.unwrap();
        assert!(encrypted.get("_encrypted_metadata").is_some());
        
        let decrypted = service.decrypt_metadata(&encrypted).await.unwrap();
        assert_eq!(decrypted, original);
    }
    
    #[tokio::test]
    async fn test_embedding_encryption() {
        let config = EncryptionConfig {
            enable_embedding_encryption: true,
            ..Default::default()
        };
        
        let mut service = EncryptionService::new(&config, "./test").await.unwrap();
        service.initialize().await.unwrap();
        
        let original_embedding = vec![0.1, 0.2, 0.3, 0.4, 0.5];
        
        let encrypted = service.encrypt_embedding(&original_embedding).await.unwrap();
        assert!(!encrypted.is_empty());
        
        let decrypted = service.decrypt_embedding(&encrypted).await.unwrap();
        assert_eq!(decrypted, original_embedding);
    }
    
    #[tokio::test]
    async fn test_sync_encryption() {
        let config = EncryptionConfig {
            enable_content_encryption: true,
            ..Default::default()
        };
        
        let mut service = EncryptionService::new(&config, "./test").await.unwrap();
        service.initialize().await.unwrap();
        
        let original = serde_json::json!({"test": "data", "number": 123});
        
        let encrypted = service.encrypt_for_sync(&original).await.unwrap();
        assert!(!encrypted.is_empty());
        
        let decrypted = service.decrypt_from_sync(&encrypted).await.unwrap();
        assert_eq!(decrypted, original);
    }
    
    #[tokio::test]
    async fn test_key_derivation() {
        let config = EncryptionConfig::default();
        let service = EncryptionService::new(&config, "./test").await.unwrap();
        
        let password = "test_password_123";
        let result = service.derive_key_from_password(password, None).await.unwrap();
        
        assert_eq!(result.key.len(), 32);
        assert!(!result.salt.is_empty());
        
        // Test with same salt
        let result2 = service.derive_key_from_password(password, Some(&result.salt)).await.unwrap();
        assert_eq!(result.key, result2.key);
    }
    
    #[tokio::test]
    async fn test_hashing() {
        let config = EncryptionConfig::default();
        let service = EncryptionService::new(&config, "./test").await.unwrap();
        
        let data = b"Hello, World!";
        let hash1 = service.hash(data);
        let hash2 = service.hash(data);
        
        assert_eq!(hash1, hash2);
        assert_eq!(hash1.len(), 64); // SHA-256 produces 32 bytes = 64 hex chars
    }
    
    #[tokio::test]
    async fn test_secure_id_generation() {
        let config = EncryptionConfig::default();
        let service = EncryptionService::new(&config, "./test").await.unwrap();
        
        let id1 = service.generate_secure_id(None).unwrap();
        let id2 = service.generate_secure_id(Some(16)).unwrap();
        
        assert_eq!(id1.len(), 64); // 32 bytes = 64 hex chars
        assert_eq!(id2.len(), 32); // 16 bytes = 32 hex chars
        assert_ne!(id1, id2);
    }
    
    #[tokio::test]
    async fn test_disabled_encryption() {
        let config = EncryptionConfig {
            enable_content_encryption: false,
            enable_metadata_encryption: false,
            enable_embedding_encryption: false,
            ..Default::default()
        };
        
        let service = EncryptionService::new(&config, "./test").await.unwrap();
        
        let content = "Hello, World!";
        let encrypted_content = service.encrypt_content(content).await.unwrap();
        assert_eq!(encrypted_content, content);
        
        let metadata = serde_json::json!({"key": "value"});
        let encrypted_metadata = service.encrypt_metadata(&metadata).await.unwrap();
        assert_eq!(encrypted_metadata, metadata);
    }
    
    #[tokio::test]
    async fn test_service_status() {
        let config = EncryptionConfig {
            enable_content_encryption: true,
            enable_metadata_encryption: true,
            ..Default::default()
        };
        
        let mut service = EncryptionService::new(&config, "./test").await.unwrap();
        
        let status = service.get_status();
        assert_eq!(status.get("initialized"), Some(&serde_json::Value::Bool(false)));
        
        service.initialize().await.unwrap();
        let status = service.get_status();
        assert_eq!(status.get("initialized"), Some(&serde_json::Value::Bool(true)));
        assert_eq!(status.get("algorithm"), Some(&serde_json::Value::String("aes-256-gcm".to_string())));
    }
}