// Copyright (c) Subzero Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//! Tests for keyring functionality.
//!
//! Note: These tests use the new keyring terminology. The test file is named
//! wallet_tests.rs for backward compatibility but tests the keyring module.

#[cfg(test)]
mod tests {
    use ed25519_dalek::SigningKey;
    use rialo_cdk::keyring::{InMemoryKeyringProvider, Keyring, KeyringProvider};

    #[tokio::test]
    async fn test_keyring_creation() {
        let provider = InMemoryKeyringProvider::new();
        let keyring = provider
            .create("test_keyring", "password123")
            .await
            .unwrap();

        assert_eq!(keyring.name, "test_keyring");
        assert!(provider.exists("test_keyring").await.unwrap());
        // Check that default keypairs were created
        assert!(!keyring.keypairs.is_empty());
    }

    #[tokio::test]
    async fn test_keyring_loading() {
        let provider = InMemoryKeyringProvider::new();
        let created = provider
            .create("test_keyring", "password123")
            .await
            .unwrap();
        let loaded = provider.load("test_keyring", "password123").await.unwrap();

        assert_eq!(created.pubkey_string(), loaded.pubkey_string());
        // Check keypairs were loaded correctly
        assert_eq!(created.keypairs.len(), loaded.keypairs.len());
    }

    #[tokio::test]
    async fn test_keyring_signing() {
        let keyring = Keyring::new_empty("test_keyring");

        let message = b"Test message";
        let signature = keyring.sign(message);

        assert!(keyring.verify_signature(message, &signature));
    }

    #[tokio::test]
    async fn test_keyring_encryption() {
        let password = "secure_password";
        let keypair = SigningKey::generate(&mut rand::rngs::OsRng);

        let encrypted =
            rialo_cdk::keyring::encryption::encrypt_keypair(&keypair, password).unwrap();
        let decrypted =
            rialo_cdk::keyring::encryption::decrypt_keypair(&encrypted, password).unwrap();

        assert_eq!(
            keypair.verifying_key().as_bytes(),
            decrypted.verifying_key().as_bytes()
        );
    }

    #[tokio::test]
    async fn test_multiple_keypairs() {
        let provider = InMemoryKeyringProvider::new();
        let keyring_name = "multi_keypair_keyring";
        provider.create(keyring_name, "password123").await.unwrap();

        // Add a new keypair to the keyring
        let keypairs_before = provider.list_keypairs(keyring_name).await.unwrap();
        let initial_count = keypairs_before.len();

        // Call derive_keypair with correct parameters (keyring_name, keypair_index, password)
        provider
            .derive_keypair(keyring_name, 1, "password123")
            .await
            .unwrap();

        // Verify keypair was added
        let keypairs_after = provider.list_keypairs(keyring_name).await.unwrap();
        assert_eq!(keypairs_after.len(), initial_count + 1);

        // Ensure keypairs have different keys
        let (_, pubkey0) = &keypairs_after[0];
        let (_, pubkey1) = &keypairs_after[1];
        assert_ne!(pubkey0, pubkey1);
    }

    #[tokio::test]
    async fn test_keypair_listing() {
        let provider = InMemoryKeyringProvider::new();
        let keyring_name = "list_keypair_keyring";
        provider.create(keyring_name, "password123").await.unwrap();

        // Get keypairs without password
        let keypairs = provider.list_keypairs(keyring_name).await.unwrap();

        // Get keyring to check against
        let keyring = provider.load(keyring_name, "password123").await.unwrap();

        // Verify keypair listing works
        assert_eq!(keypairs.len(), keyring.keypairs.len());

        // Verify keypair public keys match
        for (keypair_index, pubkey) in keypairs.iter() {
            let keyring_keypair = keyring.get_keypair(*keypair_index).unwrap();
            assert_eq!(pubkey.to_string(), keyring_keypair.pubkey_string());
        }
    }
}
