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

#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdlib>
#include <synor/crypto.hpp>

using namespace synor::crypto;

// Helper function to convert bytes to hex string
std::string bytes_to_hex(const std::vector<uint8_t>& data, size_t max_len = 0) {
    std::stringstream ss;
    size_t len = max_len > 0 && max_len < data.size() ? max_len : data.size();
    for (size_t i = 0; i < len; ++i) {
        ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(data[i]);
    }
    if (max_len > 0 && max_len < data.size()) {
        ss << "...";
    }
    return ss.str();
}

void mnemonic_example(SynorCrypto& crypto) {
    std::cout << "=== Mnemonic Operations ===" << std::endl;

    // Generate a 24-word mnemonic (256-bit entropy)
    auto mnemonic = crypto.mnemonic().generate(24);
    std::cout << "Generated mnemonic: " << mnemonic.phrase() << std::endl;
    std::cout << "Word count: " << mnemonic.word_count() << std::endl;

    // Validate a mnemonic
    auto validation = crypto.mnemonic().validate(mnemonic.phrase());
    std::cout << "Valid: " << (validation.is_valid() ? "true" : "false") << std::endl;
    if (!validation.is_valid()) {
        std::cout << "Error: " << validation.error() << std::endl;
    }

    // Convert mnemonic to seed
    auto seed = crypto.mnemonic().to_seed(mnemonic.phrase(), "optional-passphrase");
    std::cout << "Seed (hex): " << bytes_to_hex(seed, 16) << std::endl;

    // Word suggestions for autocomplete
    auto suggestions = crypto.mnemonic().suggest_words("aban", 5);
    std::cout << "Suggestions for 'aban': ";
    for (size_t i = 0; i < suggestions.size(); ++i) {
        std::cout << suggestions[i] << (i < suggestions.size() - 1 ? ", " : "");
    }
    std::cout << std::endl << std::endl;
}

void keypair_example(SynorCrypto& crypto) {
    std::cout << "=== Keypair Operations ===" << std::endl;

    // Generate a random keypair
    auto keypair = crypto.keypairs().generate();
    std::cout << "Generated hybrid keypair:" << std::endl;
    std::cout << "  Ed25519 public key size: " << keypair.public_key().ed25519_bytes().size() << " bytes" << std::endl;
    std::cout << "  Dilithium public key size: " << keypair.public_key().dilithium_bytes().size() << " bytes" << std::endl;
    std::cout << "  Total public key size: " << keypair.public_key().size() << " bytes" << std::endl;

    // Get addresses for different networks
    std::cout << "\nAddresses:" << std::endl;
    std::cout << "  Mainnet: " << keypair.get_address(Network::Mainnet) << std::endl;
    std::cout << "  Testnet: " << keypair.get_address(Network::Testnet) << std::endl;
    std::cout << "  Devnet: " << keypair.get_address(Network::Devnet) << std::endl;

    // Create keypair from mnemonic (deterministic)
    auto mnemonic = crypto.mnemonic().generate(24);
    auto keypair2 = crypto.keypairs().from_mnemonic(mnemonic.phrase(), "");
    auto addr = keypair2.get_address(Network::Mainnet);
    std::cout << "\nKeypair from mnemonic: " << addr.substr(0, 20) << "..." << std::endl;

    // Derive child keypair using BIP-44 path
    auto path = DerivationPath::external(0, 0); // m/44'/21337'/0'/0/0
    std::cout << "Derivation path: " << path.to_string() << std::endl;

    std::cout << std::endl;
}

void signing_example(SynorCrypto& crypto) {
    std::cout << "=== Hybrid Signing ===" << std::endl;

    // Generate keypair
    auto keypair = crypto.keypairs().generate();

    // Sign a message
    std::string message_str = "Hello, quantum-resistant world!";
    std::vector<uint8_t> message(message_str.begin(), message_str.end());
    auto signature = crypto.signing().sign(keypair, message);

    std::cout << "Signature created:" << std::endl;
    std::cout << "  Ed25519 component: " << signature.ed25519_bytes().size() << " bytes" << std::endl;
    std::cout << "  Dilithium component: " << signature.dilithium_bytes().size() << " bytes" << std::endl;
    std::cout << "  Total signature size: " << signature.size() << " bytes" << std::endl;

    // Verify the signature
    bool valid = crypto.signing().verify(keypair.public_key(), message, signature);
    std::cout << "\nVerification result: " << (valid ? "true" : "false") << std::endl;

    // Verify with tampered message fails
    std::string tampered_str = "Hello, tampered message!";
    std::vector<uint8_t> tampered_message(tampered_str.begin(), tampered_str.end());
    bool invalid_result = crypto.signing().verify(keypair.public_key(), tampered_message, signature);
    std::cout << "Tampered message verification: " << (invalid_result ? "true" : "false") << std::endl;

    std::cout << std::endl;
}

void falcon_example(SynorCrypto& crypto) {
    std::cout << "=== Falcon Post-Quantum Signatures ===" << std::endl;

    // Generate Falcon-512 keypair (128-bit security)
    auto falcon512 = crypto.falcon().generate(FalconVariant::Falcon512);
    std::cout << "Falcon-512 keypair:" << std::endl;
    std::cout << "  Public key: " << falcon512.public_key().key_bytes().size() << " bytes" << std::endl;
    std::cout << "  Security level: 128-bit" << std::endl;

    // Generate Falcon-1024 keypair (256-bit security)
    auto falcon1024 = crypto.falcon().generate(FalconVariant::Falcon1024);
    std::cout << "\nFalcon-1024 keypair:" << std::endl;
    std::cout << "  Public key: " << falcon1024.public_key().key_bytes().size() << " bytes" << std::endl;
    std::cout << "  Security level: 256-bit" << std::endl;

    // Sign with Falcon-512
    std::string message_str = "Post-quantum secure message";
    std::vector<uint8_t> message(message_str.begin(), message_str.end());
    auto signature = crypto.falcon().sign(falcon512, message);
    std::cout << "\nFalcon-512 signature: " << signature.signature_bytes().size() << " bytes" << std::endl;

    // Verify
    bool valid = crypto.falcon().verify(falcon512.public_key().key_bytes(), message, signature);
    std::cout << "Verification: " << (valid ? "true" : "false") << std::endl;

    std::cout << std::endl;
}

void sphincs_example(SynorCrypto& crypto) {
    std::cout << "=== SPHINCS+ Hash-Based Signatures ===" << std::endl;

    // SPHINCS+ variants with different security levels
    struct VariantInfo {
        SphincsVariant variant;
        int security;
        int sig_size;
        std::string name;
    };

    std::vector<VariantInfo> variants = {
        {SphincsVariant::Shake128s, 128, 7856, "SHAKE128S"},
        {SphincsVariant::Shake192s, 192, 16224, "SHAKE192S"},
        {SphincsVariant::Shake256s, 256, 29792, "SHAKE256S"},
    };

    std::string message_str = "Hash-based quantum security";
    std::vector<uint8_t> message(message_str.begin(), message_str.end());

    for (const auto& v : variants) {
        auto keypair = crypto.sphincs().generate(v.variant);
        std::cout << "SPHINCS+ " << v.name << ":" << std::endl;
        std::cout << "  Security level: " << v.security << "-bit" << std::endl;
        std::cout << "  Expected signature size: " << v.sig_size << " bytes" << std::endl;

        // Sign a message
        auto signature = crypto.sphincs().sign(keypair, message);
        std::cout << "  Actual signature size: " << signature.signature_bytes().size() << " bytes" << std::endl;

        // Verify
        bool valid = crypto.sphincs().verify(keypair.public_key().key_bytes(), message, signature);
        std::cout << "  Verification: " << (valid ? "true" : "false") << std::endl << std::endl;
    }
}

void kdf_example(SynorCrypto& crypto) {
    std::cout << "=== Key Derivation Functions ===" << std::endl;

    // HKDF (HMAC-based Key Derivation Function)
    std::string seed_str = "master-secret-key-material-here";
    std::vector<uint8_t> seed(seed_str.begin(), seed_str.end());

    std::string salt_str = "application-salt";
    std::string info_str = "encryption-key";

    DerivationConfig hkdf_config{
        .salt = std::vector<uint8_t>(salt_str.begin(), salt_str.end()),
        .info = std::vector<uint8_t>(info_str.begin(), info_str.end()),
        .output_length = 32
    };

    auto derived_key = crypto.kdf().derive_key(seed, hkdf_config);
    std::cout << "HKDF derived key: " << bytes_to_hex(derived_key) << std::endl;

    // PBKDF2 (Password-Based Key Derivation Function)
    std::string password_str = "user-password";
    std::vector<uint8_t> password(password_str.begin(), password_str.end());

    std::string pbkdf2_salt_str = "random-salt-value";

    PasswordDerivationConfig pbkdf2_config{
        .salt = std::vector<uint8_t>(pbkdf2_salt_str.begin(), pbkdf2_salt_str.end()),
        .iterations = 100000,
        .output_length = 32
    };

    auto password_key = crypto.kdf().derive_from_password(password, pbkdf2_config);
    std::cout << "PBKDF2 derived key: " << bytes_to_hex(password_key) << std::endl;

    std::cout << std::endl;
}

void hash_example(SynorCrypto& crypto) {
    std::cout << "=== Hash Functions ===" << std::endl;

    std::string data_str = "Data to hash";
    std::vector<uint8_t> data(data_str.begin(), data_str.end());

    // SHA3-256 (FIPS 202)
    auto sha3 = crypto.hash().sha3_256(data);
    std::cout << "SHA3-256: " << sha3.hex() << std::endl;

    // BLAKE3 (fast, parallel)
    auto blake3 = crypto.hash().blake3(data);
    std::cout << "BLAKE3:   " << blake3.hex() << std::endl;

    // Keccak-256 (Ethereum compatible)
    auto keccak = crypto.hash().keccak256(data);
    std::cout << "Keccak:   " << keccak.hex() << std::endl;

    std::cout << std::endl;
}

int main(int argc, char** argv) {
    // Initialize client
    const char* api_key = std::getenv("SYNOR_API_KEY");
    CryptoConfig config{
        .api_key = api_key ? api_key : "your-api-key",
        .endpoint = "https://crypto.synor.io/v1",
        .timeout = std::chrono::seconds(30),
        .retries = 3,
        .debug = false,
        .default_network = Network::Mainnet
    };

    SynorCrypto crypto(config);

    try {
        // Check service health
        bool healthy = crypto.health_check();
        std::cout << "Service healthy: " << (healthy ? "true" : "false") << std::endl << std::endl;

        // Run examples
        mnemonic_example(crypto);
        keypair_example(crypto);
        signing_example(crypto);
        falcon_example(crypto);
        sphincs_example(crypto);
        kdf_example(crypto);
        hash_example(crypto);
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}
