//! Synor Crypto SDK Examples for Rust
//!
//! Demonstrates quantum-resistant cryptographic operations:
//! - Hybrid Ed25519 + Dilithium3 signatures
//! - BIP-39 mnemonic generation and validation
//! - Post-quantum algorithms (Falcon, SPHINCS+)
//! - Key derivation functions

use std::env;
use synor_crypto::{
    CryptoConfig, DerivationConfig, DerivationPath, FalconVariant, Network,
    PasswordDerivationConfig, SphincsVariant, SynorCrypto,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize client
    let config = CryptoConfig {
        api_key: env::var("SYNOR_API_KEY").unwrap_or_else(|_| "your-api-key".to_string()),
        endpoint: "https://crypto.synor.io/v1".to_string(),
        timeout: 30000,
        retries: 3,
        debug: false,
        default_network: Network::Mainnet,
    };

    let crypto = SynorCrypto::new(config)?;

    // Check service health
    let healthy = crypto.health_check().await?;
    println!("Service healthy: {}\n", healthy);

    // Run examples
    mnemonic_example(&crypto).await?;
    keypair_example(&crypto).await?;
    signing_example(&crypto).await?;
    falcon_example(&crypto).await?;
    sphincs_example(&crypto).await?;
    kdf_example(&crypto).await?;
    hash_example(&crypto).await?;

    crypto.close().await?;
    Ok(())
}

async fn mnemonic_example(crypto: &SynorCrypto) -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Mnemonic Operations ===");

    // Generate a 24-word mnemonic (256-bit entropy)
    let mnemonic = crypto.mnemonic.generate(24).await?;
    println!("Generated mnemonic: {}", mnemonic.phrase);
    println!("Word count: {}", mnemonic.word_count);

    // Validate a mnemonic
    let validation = crypto.mnemonic.validate(&mnemonic.phrase).await?;
    println!("Valid: {}", validation.valid);
    if !validation.valid {
        println!("Error: {}", validation.error.unwrap_or_default());
    }

    // Convert mnemonic to seed
    let seed = crypto
        .mnemonic
        .to_seed(&mnemonic.phrase, Some("optional-passphrase"))
        .await?;
    println!("Seed (hex): {}...", &hex::encode(&seed)[..32]);

    // Word suggestions for autocomplete
    let suggestions = crypto.mnemonic.suggest_words("aban", 5).await?;
    println!("Suggestions for 'aban': {}", suggestions.join(", "));

    println!();
    Ok(())
}

async fn keypair_example(crypto: &SynorCrypto) -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Keypair Operations ===");

    // Generate a random keypair
    let keypair = crypto.keypairs.generate().await?;
    println!("Generated hybrid keypair:");
    println!(
        "  Ed25519 public key size: {} bytes",
        keypair.public_key.ed25519_bytes.len()
    );
    println!(
        "  Dilithium public key size: {} bytes",
        keypair.public_key.dilithium_bytes.len()
    );
    println!("  Total public key size: {} bytes", keypair.public_key.size);

    // Get addresses for different networks
    println!("\nAddresses:");
    println!("  Mainnet: {}", keypair.get_address(Network::Mainnet));
    println!("  Testnet: {}", keypair.get_address(Network::Testnet));
    println!("  Devnet: {}", keypair.get_address(Network::Devnet));

    // Create keypair from mnemonic (deterministic)
    let mnemonic = crypto.mnemonic.generate(24).await?;
    let keypair2 = crypto
        .keypairs
        .from_mnemonic(&mnemonic.phrase, "")
        .await?;
    let addr = keypair2.get_address(Network::Mainnet);
    println!("\nKeypair from mnemonic: {}...", &addr[..20]);

    // Derive child keypair using BIP-44 path
    let path = DerivationPath::external(0, 0); // m/44'/21337'/0'/0/0
    println!("Derivation path: {}", path);

    println!();
    Ok(())
}

async fn signing_example(crypto: &SynorCrypto) -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Hybrid Signing ===");

    // Generate keypair
    let keypair = crypto.keypairs.generate().await?;

    // Sign a message
    let message = b"Hello, quantum-resistant world!";
    let signature = crypto.signing.sign(&keypair, message).await?;

    println!("Signature created:");
    println!(
        "  Ed25519 component: {} bytes",
        signature.ed25519_bytes.len()
    );
    println!(
        "  Dilithium component: {} bytes",
        signature.dilithium_bytes.len()
    );
    println!("  Total signature size: {} bytes", signature.size);

    // Verify the signature
    let valid = crypto
        .signing
        .verify(&keypair.public_key, message, &signature)
        .await?;
    println!("\nVerification result: {}", valid);

    // Verify with tampered message fails
    let tampered_message = b"Hello, tampered message!";
    let invalid_result = crypto
        .signing
        .verify(&keypair.public_key, tampered_message, &signature)
        .await?;
    println!("Tampered message verification: {}", invalid_result);

    println!();
    Ok(())
}

async fn falcon_example(crypto: &SynorCrypto) -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Falcon Post-Quantum Signatures ===");

    // Generate Falcon-512 keypair (128-bit security)
    let falcon512 = crypto.falcon.generate(FalconVariant::Falcon512).await?;
    println!("Falcon-512 keypair:");
    println!("  Public key: {} bytes", falcon512.public_key.key_bytes.len());
    println!("  Security level: 128-bit");

    // Generate Falcon-1024 keypair (256-bit security)
    let falcon1024 = crypto.falcon.generate(FalconVariant::Falcon1024).await?;
    println!("\nFalcon-1024 keypair:");
    println!(
        "  Public key: {} bytes",
        falcon1024.public_key.key_bytes.len()
    );
    println!("  Security level: 256-bit");

    // Sign with Falcon-512
    let message = b"Post-quantum secure message";
    let signature = crypto.falcon.sign(&falcon512, message).await?;
    println!(
        "\nFalcon-512 signature: {} bytes",
        signature.signature_bytes.len()
    );

    // Verify
    let valid = crypto
        .falcon
        .verify(&falcon512.public_key.key_bytes, message, &signature)
        .await?;
    println!("Verification: {}", valid);

    println!();
    Ok(())
}

async fn sphincs_example(crypto: &SynorCrypto) -> Result<(), Box<dyn std::error::Error>> {
    println!("=== SPHINCS+ Hash-Based Signatures ===");

    // SPHINCS+ variants with different security levels
    let variants = [
        (SphincsVariant::Shake128s, 128, 7856),
        (SphincsVariant::Shake192s, 192, 16224),
        (SphincsVariant::Shake256s, 256, 29792),
    ];

    // Generate and demonstrate each variant
    for (variant, security, sig_size) in variants {
        let keypair = crypto.sphincs.generate(variant).await?;
        println!("SPHINCS+ {:?}:", variant);
        println!("  Security level: {}-bit", security);
        println!("  Expected signature size: {} bytes", sig_size);

        // Sign a message
        let message = b"Hash-based quantum security";
        let signature = crypto.sphincs.sign(&keypair, message).await?;
        println!(
            "  Actual signature size: {} bytes",
            signature.signature_bytes.len()
        );

        // Verify
        let valid = crypto
            .sphincs
            .verify(&keypair.public_key.key_bytes, message, &signature)
            .await?;
        println!("  Verification: {}\n", valid);
    }

    Ok(())
}

async fn kdf_example(crypto: &SynorCrypto) -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Key Derivation Functions ===");

    // HKDF (HMAC-based Key Derivation Function)
    let seed = b"master-secret-key-material-here";
    let hkdf_config = DerivationConfig {
        salt: b"application-salt".to_vec(),
        info: b"encryption-key".to_vec(),
        output_length: 32,
    };

    let derived_key = crypto.kdf.derive_key(seed, &hkdf_config).await?;
    println!("HKDF derived key: {}", hex::encode(&derived_key));

    // PBKDF2 (Password-Based Key Derivation Function)
    let password = b"user-password";
    let pbkdf2_config = PasswordDerivationConfig {
        salt: b"random-salt-value".to_vec(),
        iterations: 100000,
        output_length: 32,
    };

    let password_key = crypto
        .kdf
        .derive_from_password(password, &pbkdf2_config)
        .await?;
    println!("PBKDF2 derived key: {}", hex::encode(&password_key));

    println!();
    Ok(())
}

async fn hash_example(crypto: &SynorCrypto) -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Hash Functions ===");

    let data = b"Data to hash";

    // SHA3-256 (FIPS 202)
    let sha3 = crypto.hash.sha3_256(data).await?;
    println!("SHA3-256: {}", sha3.hex);

    // BLAKE3 (fast, parallel)
    let blake3 = crypto.hash.blake3(data).await?;
    println!("BLAKE3:   {}", blake3.hex);

    // Keccak-256 (Ethereum compatible)
    let keccak = crypto.hash.keccak256(data).await?;
    println!("Keccak:   {}", keccak.hex);

    println!();
    Ok(())
}
