package io.synor.examples

import io.synor.crypto.*
import io.synor.crypto.types.*
import kotlinx.coroutines.runBlocking

/**
 * Synor Crypto SDK Examples for Kotlin
 *
 * Demonstrates quantum-resistant cryptographic operations:
 * - Hybrid Ed25519 + Dilithium3 signatures
 * - BIP-39 mnemonic generation and validation
 * - Post-quantum algorithms (Falcon, SPHINCS+)
 * - Key derivation functions
 */
fun main() = runBlocking {
    // Initialize client
    val config = CryptoConfig(
        apiKey = System.getenv("SYNOR_API_KEY") ?: "your-api-key",
        endpoint = "https://crypto.synor.io/v1",
        timeout = 30_000,
        retries = 3,
        debug = false,
        defaultNetwork = Network.MAINNET
    )

    val crypto = SynorCrypto(config)

    try {
        // Check service health
        val healthy = crypto.healthCheck()
        println("Service healthy: $healthy\n")

        // Run examples
        mnemonicExample(crypto)
        keypairExample(crypto)
        signingExample(crypto)
        falconExample(crypto)
        sphincsExample(crypto)
        kdfExample(crypto)
        hashExample(crypto)
    } finally {
        crypto.close()
    }
}

suspend fun mnemonicExample(crypto: SynorCrypto) {
    println("=== Mnemonic Operations ===")

    // Generate a 24-word mnemonic (256-bit entropy)
    val mnemonic = crypto.mnemonic.generate(24)
    println("Generated mnemonic: ${mnemonic.phrase}")
    println("Word count: ${mnemonic.wordCount}")

    // Validate a mnemonic
    val validation = crypto.mnemonic.validate(mnemonic.phrase)
    println("Valid: ${validation.isValid}")
    if (!validation.isValid) {
        println("Error: ${validation.error}")
    }

    // Convert mnemonic to seed
    val seed = crypto.mnemonic.toSeed(mnemonic.phrase, "optional-passphrase")
    println("Seed (hex): ${seed.toHex().take(32)}...")

    // Word suggestions for autocomplete
    val suggestions = crypto.mnemonic.suggestWords("aban", limit = 5)
    println("Suggestions for 'aban': ${suggestions.joinToString(", ")}")

    println()
}

suspend fun keypairExample(crypto: SynorCrypto) {
    println("=== Keypair Operations ===")

    // Generate a random keypair
    val keypair = crypto.keypairs.generate()
    println("Generated hybrid keypair:")
    println("  Ed25519 public key size: ${keypair.publicKey.ed25519Bytes.size} bytes")
    println("  Dilithium public key size: ${keypair.publicKey.dilithiumBytes.size} bytes")
    println("  Total public key size: ${keypair.publicKey.size} bytes")

    // Get addresses for different networks
    println("\nAddresses:")
    println("  Mainnet: ${keypair.getAddress(Network.MAINNET)}")
    println("  Testnet: ${keypair.getAddress(Network.TESTNET)}")
    println("  Devnet: ${keypair.getAddress(Network.DEVNET)}")

    // Create keypair from mnemonic (deterministic)
    val mnemonic = crypto.mnemonic.generate(24)
    val keypair2 = crypto.keypairs.fromMnemonic(mnemonic.phrase, "")
    val addr = keypair2.getAddress(Network.MAINNET)
    println("\nKeypair from mnemonic: ${addr.take(20)}...")

    // Derive child keypair using BIP-44 path
    val path = DerivationPath.external(0, 0) // m/44'/21337'/0'/0/0
    println("Derivation path: $path")

    println()
}

suspend fun signingExample(crypto: SynorCrypto) {
    println("=== Hybrid Signing ===")

    // Generate keypair
    val keypair = crypto.keypairs.generate()

    // Sign a message
    val message = "Hello, quantum-resistant world!".toByteArray()
    val signature = crypto.signing.sign(keypair, message)

    println("Signature created:")
    println("  Ed25519 component: ${signature.ed25519Bytes.size} bytes")
    println("  Dilithium component: ${signature.dilithiumBytes.size} bytes")
    println("  Total signature size: ${signature.size} bytes")

    // Verify the signature
    val valid = crypto.signing.verify(keypair.publicKey, message, signature)
    println("\nVerification result: $valid")

    // Verify with tampered message fails
    val tamperedMessage = "Hello, tampered message!".toByteArray()
    val invalidResult = crypto.signing.verify(keypair.publicKey, tamperedMessage, signature)
    println("Tampered message verification: $invalidResult")

    println()
}

suspend fun falconExample(crypto: SynorCrypto) {
    println("=== Falcon Post-Quantum Signatures ===")

    // Generate Falcon-512 keypair (128-bit security)
    val falcon512 = crypto.falcon.generate(FalconVariant.FALCON512)
    println("Falcon-512 keypair:")
    println("  Public key: ${falcon512.publicKey.keyBytes.size} bytes")
    println("  Security level: 128-bit")

    // Generate Falcon-1024 keypair (256-bit security)
    val falcon1024 = crypto.falcon.generate(FalconVariant.FALCON1024)
    println("\nFalcon-1024 keypair:")
    println("  Public key: ${falcon1024.publicKey.keyBytes.size} bytes")
    println("  Security level: 256-bit")

    // Sign with Falcon-512
    val message = "Post-quantum secure message".toByteArray()
    val signature = crypto.falcon.sign(falcon512, message)
    println("\nFalcon-512 signature: ${signature.signatureBytes.size} bytes")

    // Verify
    val valid = crypto.falcon.verify(falcon512.publicKey.keyBytes, message, signature)
    println("Verification: $valid")

    println()
}

suspend fun sphincsExample(crypto: SynorCrypto) {
    println("=== SPHINCS+ Hash-Based Signatures ===")

    // SPHINCS+ variants with different security levels
    val variants = listOf(
        Triple(SphincsVariant.SHAKE128S, 128, 7856),
        Triple(SphincsVariant.SHAKE192S, 192, 16224),
        Triple(SphincsVariant.SHAKE256S, 256, 29792)
    )

    // Generate and demonstrate each variant
    for ((variant, security, sigSize) in variants) {
        val keypair = crypto.sphincs.generate(variant)
        println("SPHINCS+ $variant:")
        println("  Security level: $security-bit")
        println("  Expected signature size: $sigSize bytes")

        // Sign a message
        val message = "Hash-based quantum security".toByteArray()
        val signature = crypto.sphincs.sign(keypair, message)
        println("  Actual signature size: ${signature.signatureBytes.size} bytes")

        // Verify
        val valid = crypto.sphincs.verify(keypair.publicKey.keyBytes, message, signature)
        println("  Verification: $valid\n")
    }
}

suspend fun kdfExample(crypto: SynorCrypto) {
    println("=== Key Derivation Functions ===")

    // HKDF (HMAC-based Key Derivation Function)
    val seed = "master-secret-key-material-here".toByteArray()
    val hkdfConfig = DerivationConfig(
        salt = "application-salt".toByteArray(),
        info = "encryption-key".toByteArray(),
        outputLength = 32
    )

    val derivedKey = crypto.kdf.deriveKey(seed, hkdfConfig)
    println("HKDF derived key: ${derivedKey.toHex()}")

    // PBKDF2 (Password-Based Key Derivation Function)
    val password = "user-password".toByteArray()
    val pbkdf2Config = PasswordDerivationConfig(
        salt = "random-salt-value".toByteArray(),
        iterations = 100_000,
        outputLength = 32
    )

    val passwordKey = crypto.kdf.deriveFromPassword(password, pbkdf2Config)
    println("PBKDF2 derived key: ${passwordKey.toHex()}")

    println()
}

suspend fun hashExample(crypto: SynorCrypto) {
    println("=== Hash Functions ===")

    val data = "Data to hash".toByteArray()

    // SHA3-256 (FIPS 202)
    val sha3 = crypto.hash.sha3_256(data)
    println("SHA3-256: ${sha3.hex}")

    // BLAKE3 (fast, parallel)
    val blake3 = crypto.hash.blake3(data)
    println("BLAKE3:   ${blake3.hex}")

    // Keccak-256 (Ethereum compatible)
    val keccak = crypto.hash.keccak256(data)
    println("Keccak:   ${keccak.hex}")

    println()
}

// Extension function to convert ByteArray to hex string
fun ByteArray.toHex(): String = joinToString("") { "%02x".format(it) }
