use std::str::FromStr;

use vault_service::{
    service::KmsService,
    types::{EncryptionContext, KeySpec, KmsBackendConfig},
};

/// Test encryption context
#[tokio::test]
async fn test_encryption_context() {
    let mut ctx = EncryptionContext::new();
    ctx.add("environment", "test");
    ctx.add("service", "integration-test");

    assert_eq!(ctx.context.len(), 2);
    assert_eq!(ctx.context.get("environment").unwrap(), "test");

    let ctx_str = ctx.to_string();
    assert!(ctx_str.contains("environment=test"));
    assert!(ctx_str.contains("service=integration-test"));

    let parsed = EncryptionContext::from_str(&ctx_str).unwrap();
    assert_eq!(parsed.context.len(), 2);
}

/// Test key spec sizes
#[test]
fn test_key_spec_sizes() {
    assert_eq!(KeySpec::Aes128.key_size(), 16);
    assert_eq!(KeySpec::Aes256.key_size(), 32);
    assert_eq!(KeySpec::Rsa2048.key_size(), 256);
    assert_eq!(KeySpec::Rsa4096.key_size(), 512);
}

// /// Test Vault backend initialization (requires Vault running)
// #[tokio::test]
// #[ignore] // Ignore by default, run with --ignored flag when Vault is
// available async fn test_vault_backend_init() {
//     let config = KmsBackendConfig::Vault {
//         address: "http://localhost:8200".to_string(),
//         token: std::env::var("VAULT_TOKEN").expect("VAULT_TOKEN not set"),
//         mount_point: "transit".to_string(),
//         namespace: None,
//         auto_renew_token: false,
//     };
//
//     let service = KmsService::new(config).await;
//     assert!(service.is_ok(), "Failed to initialize Vault backend");
//
//     let service = service.unwrap();
//     assert_eq!(service.get_backend_name(), "vault");
// }

// AWS KMS backend not yet implemented
// Test AWS KMS backend initialization (requires AWS credentials)
// #[tokio::test]
// #[ignore] // Ignore by default, run with --ignored flag when AWS is
// configured async fn test_aws_kms_backend_init() {
// let key_id = std::env::var("AWS_KMS_KEY_ID").expect("AWS_KMS_KEY_ID not
// set");
//
// let config = KmsBackendConfig::AwsKms {
// region: "us-east-1".to_string(),
// key_id,
// assume_role: None,
// };
//
// let service = KmsService::new(config).await;
// assert!(service.is_ok(), "Failed to initialize AWS KMS backend");
//
// let service = service.unwrap();
// assert_eq!(service.get_backend_name(), "aws-kms");
// }

// /// Test encryption and decryption round-trip with Vault
// #[tokio::test]
// #[ignore] // Requires Vault
// async fn test_vault_encrypt_decrypt_roundtrip() {
//     let config = KmsBackendConfig::Vault {
//         address: "http://localhost:8200".to_string(),
//         token: std::env::var("VAULT_TOKEN").expect("VAULT_TOKEN not set"),
//         mount_point: "transit".to_string(),
//         namespace: None,
//         auto_renew_token: false,
//     };
//
//     let service = KmsService::new(config).await.unwrap();
//
//     let plaintext = b"Hello, Vault KMS!";
//     let mut context = EncryptionContext::new();
//     context.add("test", "integration");
//
//     // Encrypt
//     let ciphertext = service.encrypt(plaintext, &context).await.unwrap();
//     assert!(!ciphertext.is_empty());
//     assert_ne!(ciphertext, plaintext);
//
//     // Decrypt
//     let decrypted = service.decrypt(&ciphertext, &context).await.unwrap();
//     assert_eq!(decrypted, plaintext);
// }
//
// /// Test encryption and decryption round-trip with AWS KMS
// #[tokio::test]
// #[ignore] // Requires AWS KMS
// async fn test_aws_kms_encrypt_decrypt_roundtrip() {
//     let key_id = std::env::var("AWS_KMS_KEY_ID").expect("AWS_KMS_KEY_ID not
// set");
//
//     let config = KmsBackendConfig::AwsKms {
//         region: "us-east-1".to_string(),
//         key_id,
//         assume_role: None,
//     };
//
//     let service = KmsService::new(config).await.unwrap();
//
//     let plaintext = b"Hello, AWS KMS!";
//     let mut context = EncryptionContext::new();
//     context.add("test", "integration");
//
//     // Encrypt
//     let ciphertext = service.encrypt(plaintext, &context).await.unwrap();
//     assert!(!ciphertext.is_empty());
//     assert_ne!(ciphertext, plaintext);
//
//     // Decrypt
//     let decrypted = service.decrypt(&ciphertext, &context).await.unwrap();
//     assert_eq!(decrypted, plaintext);
// }
//
// /// Test data key generation with AWS KMS
// #[tokio::test]
// #[ignore] // Requires AWS KMS
// async fn test_aws_kms_generate_data_key() {
//     let key_id = std::env::var("AWS_KMS_KEY_ID").expect("AWS_KMS_KEY_ID not
// set");
//
//     let config = KmsBackendConfig::AwsKms {
//         region: "us-east-1".to_string(),
//         key_id,
//         assume_role: None,
//     };
//
//     let service = KmsService::new(config).await.unwrap();
//
//     // Generate AES-256 data key
//     let data_key =
// service.generate_data_key(&KeySpec::Aes256).await.unwrap();
//
//     assert_eq!(data_key.plaintext.len(), 32); // 256 bits = 32 bytes
//     assert!(!data_key.ciphertext.is_empty());
//     assert!(!data_key.key_id.is_empty());
// }
//
// /// Test envelope encryption with AWS KMS
// #[tokio::test]
// #[ignore] // Requires AWS KMS
// async fn test_aws_kms_envelope_encryption() {
//     let key_id = std::env::var("AWS_KMS_KEY_ID").expect("AWS_KMS_KEY_ID not
// set");
//
//     let config = KmsBackendConfig::AwsKms {
//         region: "us-east-1".to_string(),
//         key_id,
//         assume_role: None,
//     };
//
//     let service = KmsService::new(config).await.unwrap();
//
//     let plaintext = b"Hello, envelope encryption!";
//
//     // Envelope encrypt
//     let envelope_ciphertext =
// service.envelope_encrypt(plaintext).await.unwrap();     assert!(!
// envelope_ciphertext.is_empty());
//
//     // Envelope decrypt
//     let decrypted =
// service.envelope_decrypt(&envelope_ciphertext).await.unwrap();     assert_eq!
// (decrypted, plaintext); }

/// Test health check
#[tokio::test]
#[ignore] // Requires backend
async fn test_health_check() {
    let config = KmsBackendConfig::Rustyvault {
        server_url: "http://localhost:8200".to_string(),
        token: std::env::var("RUSTYVAULT_TOKEN").ok(),
        mount_point: "transit".to_string(),
        key_name: "test-key".to_string(),
        tls_verify: false,
    };

    let service = KmsService::new(config).await.unwrap();
    let healthy = service.health_check().await.unwrap();
    assert!(healthy);
}

/// Test operations counter
#[tokio::test]
async fn test_operations_counter() {
    // Use a mock or test config
    let config = KmsBackendConfig::Rustyvault {
        server_url: "http://localhost:8200".to_string(),
        token: Some("test-token".to_string()),
        mount_point: "transit".to_string(),
        key_name: "test-key".to_string(),
        tls_verify: false,
    };

    if let Ok(service) = KmsService::new(config).await {
        let initial_count = service.get_operations_count().await;
        assert_eq!(initial_count, 0);
        // get_uptime() returns u64, always >= 0 by type
        let _uptime = service.get_uptime();
    }
}

/// Test context-based encryption (ensures context is enforced)
#[tokio::test]
#[ignore] // Requires backend
async fn test_context_enforcement() {
    let config = KmsBackendConfig::Rustyvault {
        server_url: "http://localhost:8200".to_string(),
        token: std::env::var("RUSTYVAULT_TOKEN").ok(),
        mount_point: "transit".to_string(),
        key_name: "test-key".to_string(),
        tls_verify: false,
    };

    let service = KmsService::new(config).await.unwrap();

    let plaintext = b"Context-sensitive data";

    let mut encrypt_context = EncryptionContext::new();
    encrypt_context.add("purpose", "testing");
    encrypt_context.add("level", "critical");

    // Encrypt with context
    let ciphertext = service.encrypt(plaintext, &encrypt_context).await.unwrap();

    // Try to decrypt with wrong context (should fail)
    let mut wrong_context = EncryptionContext::new();
    wrong_context.add("purpose", "wrong");

    let _result = service.decrypt(&ciphertext, &wrong_context).await;
    // Note: Vault enforces context, so this should fail
    // AWS KMS also enforces context when AAD is used
}

/// Performance test: measure encryption throughput
#[tokio::test]
#[ignore] // Performance test, run manually
async fn test_encryption_performance() {
    let config = KmsBackendConfig::Rustyvault {
        server_url: "http://localhost:8200".to_string(),
        token: std::env::var("RUSTYVAULT_TOKEN").ok(),
        mount_point: "transit".to_string(),
        key_name: "test-key".to_string(),
        tls_verify: false,
    };

    let service = KmsService::new(config).await.unwrap();

    let plaintext = b"Performance test data";
    let context = EncryptionContext::new();

    let iterations = 100;
    let start = std::time::Instant::now();

    for _ in 0..iterations {
        let _ = service.encrypt(plaintext, &context).await.unwrap();
    }

    let elapsed = start.elapsed();
    let ops_per_sec = iterations as f64 / elapsed.as_secs_f64();

    println!(
        "Encryption throughput: {:.2} ops/sec ({} iterations in {:.2}s)",
        ops_per_sec,
        iterations,
        elapsed.as_secs_f64()
    );
}
