//! KmsManager Trait Implementations
//!
//! Implements the facade traits for KmsManager, providing
//! a stable public API while delegating to internal components.

use async_trait::async_trait;
use chrono::Utc;
use uuid::Uuid;

use crate::kms::error::{KmsClientError, KmsError, Result};
use crate::kms::facade::{
    ComponentHealth, KeyStatus, KmsHealthStatus, KmsService, KmsServiceExt, KmsStatistics,
};
use crate::kms::types::{
    KeyAlgorithm, KeyData, KeyMetadata, KeyType, KeyUsage, ProviderCredentials,
};
use crate::kms::{AuditEvent, KmsManager};

/// Implementation of the stable KmsService facade trait
///
/// This provides the public contract for KMS operations,
/// allowing internal implementation to change without breaking consumers.
#[async_trait]
impl KmsService for KmsManager {
    async fn initialize(&mut self) -> Result<()> {
        // Delegate to existing implementation
        KmsManager::initialize(self).await
    }

    async fn get_key(&self, key_id: &str) -> Result<Option<KeyData>> {
        // Delegate to existing implementation
        KmsManager::get_key(self, key_id).await
    }

    async fn store_key(&self, key: KeyData) -> Result<String> {
        // Delegate to existing implementation
        KmsManager::store_key(self, key).await
    }

    async fn delete_key(&self, key_id: &str) -> Result<bool> {
        // Delegate to existing implementation
        KmsManager::delete_key(self, key_id).await
    }

    async fn encrypt(&self, key_id: &str, plaintext: &[u8]) -> Result<Vec<u8>> {
        // Delegate to backend with audit logging
        let result = self.backend.encrypt(key_id, plaintext, None).await;

        // Log encryption attempt (best effort - don't fail on audit errors)
        let _ = match &result {
            Ok(_) => {
                self.audit
                    .log_event(AuditEvent::key_operation("encrypt", key_id))
                    .await
            }
            Err(e) => {
                self.audit
                    .log_event(AuditEvent::key_operation_failed("encrypt", key_id, e))
                    .await
            }
        };

        result
    }

    async fn decrypt(&self, key_id: &str, ciphertext: &[u8]) -> Result<Vec<u8>> {
        // Delegate to backend with audit logging
        let result = self.backend.decrypt(key_id, ciphertext, None).await;

        // Log decryption attempt (best effort - don't fail on audit errors)
        let _ = match &result {
            Ok(_) => {
                self.audit
                    .log_event(AuditEvent::key_operation("decrypt", key_id))
                    .await
            }
            Err(e) => {
                self.audit
                    .log_event(AuditEvent::key_operation_failed("decrypt", key_id, e))
                    .await
            }
        };

        result
    }

    async fn generate_key(&self, key_type: KeyType) -> Result<KeyData> {
        // Generate key data based on type
        let (algorithm, key_size) = match key_type {
            KeyType::Symmetric => (KeyAlgorithm::Aes256Gcm, 256),
            KeyType::Asymmetric => (KeyAlgorithm::Rsa4096, 4096),
            KeyType::Hmac => (KeyAlgorithm::HmacSha256, 256),
            KeyType::Kdf => (KeyAlgorithm::HkdfSha256, 256),
            KeyType::Dek => (KeyAlgorithm::Aes256Gcm, 256),
            KeyType::Kek => (KeyAlgorithm::Aes256Gcm, 256),
        };

        let key = KeyData {
            key_id: Uuid::new_v4().to_string(),
            key_type,
            algorithm,
            usage: KeyUsage::default(),
            key_size,
            key_material: generate_key_material(algorithm, key_size)?,
            metadata: KeyMetadata::default(),
            created_at: Utc::now(),
            last_accessed: None,
            expires_at: None,
            status: crate::kms::types::KeyStatus::Active,
            tags: Default::default(),
        };

        // Store the generated key
        let key_id = self.store_key(key.clone()).await?;

        // Log generation (best effort - don't fail on audit errors)
        let _ = self
            .audit
            .log_event(AuditEvent::key_generated(&key_id))
            .await;

        Ok(key)
    }

    async fn rotate_key(&self, key_id: &str) -> Result<KeyData> {
        // Get existing key
        let existing = self
            .get_key(key_id)
            .await?
            .ok_or_else(|| KmsError::KeyNotFound {
                key_id: key_id.to_string(),
            })?;

        // Generate new version
        let mut new_key = KeyData {
            key_id: format!("{}-v{}", key_id, existing.metadata.version + 1),
            key_type: existing.key_type,
            algorithm: existing.algorithm,
            usage: existing.usage.clone(),
            key_size: existing.key_size,
            key_material: generate_key_material(existing.algorithm, existing.key_size)?,
            metadata: KeyMetadata {
                version: existing.metadata.version + 1,
                ..existing.metadata.clone()
            },
            created_at: Utc::now(),
            last_accessed: None,
            expires_at: existing.expires_at,
            status: crate::kms::types::KeyStatus::Active,
            tags: existing.tags.clone(),
        };

        // Store new version
        let new_key_id = self.store_key(new_key.clone()).await?;

        // Mark old key as deprecated
        let mut old_key = existing;
        old_key.status = crate::kms::types::KeyStatus::Deactivated;
        self.backend.update_key(key_id, old_key).await?;

        // Log rotation (best effort - don't fail on audit errors)
        let _ = self
            .audit
            .log_event(AuditEvent::key_rotated(key_id, &new_key_id))
            .await;

        Ok(new_key)
    }

    async fn get_provider_credentials(
        &self,
        provider: &str,
    ) -> Result<Option<ProviderCredentials>> {
        // Delegate to existing implementation
        KmsManager::get_provider_credentials(self, provider).await
    }

    async fn store_provider_credentials(
        &self,
        provider: &str,
        credentials: ProviderCredentials,
    ) -> Result<()> {
        // Delegate to existing implementation
        KmsManager::store_provider_credentials(self, provider, credentials).await
    }

    async fn shutdown(&mut self) -> Result<()> {
        // Delegate to existing implementation
        KmsManager::shutdown(self).await
    }
}

/// Implementation of advanced/optional operations
#[async_trait]
impl KmsServiceExt for KmsManager {
    async fn health_check(&self) -> Result<KmsHealthStatus> {
        let kms_health = KmsManager::health_check(self).await?;

        Ok(KmsHealthStatus {
            backend: ComponentHealth {
                healthy: kms_health.backend.is_healthy(),
                message: Some(kms_health.backend.message),
            },
            rotation: ComponentHealth {
                healthy: kms_health.rotation.is_healthy(),
                message: Some(kms_health.rotation.message),
            },
            credentials: ComponentHealth {
                healthy: kms_health.credentials.is_healthy(),
                message: Some(kms_health.credentials.message),
            },
            overall: kms_health.overall,
        })
    }

    async fn list_keys(
        &self,
        key_type: Option<KeyType>,
        status: Option<KeyStatus>,
    ) -> Result<Vec<String>> {
        let mut filters = std::collections::HashMap::new();

        if let Some(kt) = key_type {
            filters.insert("key_type".to_string(), format!("{:?}", kt));
        }

        if let Some(s) = status {
            filters.insert("status".to_string(), format!("{:?}", s));
        }

        let filters_opt = if filters.is_empty() {
            None
        } else {
            Some(filters)
        };

        self.backend.list_keys(filters_opt).await
    }

    async fn get_statistics(&self) -> Result<KmsStatistics> {
        let all_keys = self.backend.list_keys(None).await?;

        let mut active_count = 0;
        let mut expired_count = 0;
        let mut rotation_pending = 0;

        for key_id in &all_keys {
            if let Ok(Some(key)) = self.backend.get_key(key_id).await {
                if key.status == crate::kms::types::KeyStatus::Active {
                    active_count += 1;
                }
                if let Some(expires_at) = key.expires_at {
                    if expires_at < Utc::now() {
                        expired_count += 1;
                    }
                }
            }
        }

        Ok(KmsStatistics {
            total_keys: all_keys.len(),
            active_keys: active_count,
            expired_keys: expired_count,
            rotation_pending,
        })
    }

    async fn export_key(&self, key_id: &str, wrap_key_id: &str) -> Result<Vec<u8>> {
        // Get the key to export
        let key = self
            .get_key(key_id)
            .await?
            .ok_or_else(|| KmsError::KeyNotFound {
                key_id: key_id.to_string(),
            })?;

        // Check export permission
        if !key.usage.export {
            return Err(KmsError::PermissionDenied {
                operation: "export".to_string(),
                resource: key_id.to_string(),
            });
        }

        // Serialize key data
        let key_bytes = serde_json::to_vec(&key).map_err(|e| KmsError::Serialization {
            message: e.to_string(),
        })?;

        // Wrap with the wrapping key
        let wrapped = self.encrypt(wrap_key_id, &key_bytes).await?;

        // Log export (best effort - don't fail on audit errors)
        let _ = self
            .audit
            .log_event(AuditEvent::key_exported(key_id, wrap_key_id))
            .await;

        Ok(wrapped)
    }

    async fn import_key(&self, wrapped_key: &[u8], unwrap_key_id: &str) -> Result<String> {
        // Unwrap the key
        let key_bytes = self.decrypt(unwrap_key_id, wrapped_key).await?;

        // Deserialize key data
        let key: KeyData =
            serde_json::from_slice(&key_bytes).map_err(|e| KmsError::Serialization {
                message: e.to_string(),
            })?;

        // Store the imported key
        let key_id = self.store_key(key).await?;

        // Log import (best effort - don't fail on audit errors)
        let _ = self
            .audit
            .log_event(AuditEvent::key_imported(&key_id))
            .await;

        Ok(key_id)
    }
}

/// Generate key material based on algorithm and size
fn generate_key_material(
    algorithm: KeyAlgorithm,
    key_size: u32,
) -> Result<crate::kms::types::SecretBytes> {
    use rand::RngCore;

    let byte_size = (key_size / 8) as usize;
    let mut key_material = vec![0u8; byte_size];

    rand::rng().fill_bytes(&mut key_material);

    Ok(crate::kms::types::SecretBytes::new(key_material))
}
