/**
 * 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <synor/crypto.h>

// Helper function to print hex
void print_hex(const uint8_t* data, size_t len, size_t max_len) {
    size_t print_len = len < max_len ? len : max_len;
    for (size_t i = 0; i < print_len; i++) {
        printf("%02x", data[i]);
    }
    if (len > max_len) {
        printf("...");
    }
}

void mnemonic_example(synor_crypto_t* crypto) {
    printf("=== Mnemonic Operations ===\n");

    synor_error_t err;
    synor_mnemonic_t* mnemonic = NULL;

    // Generate a 24-word mnemonic (256-bit entropy)
    err = synor_mnemonic_generate(crypto, 24, &mnemonic);
    if (err != SYNOR_OK) {
        fprintf(stderr, "Failed to generate mnemonic: %s\n", synor_error_string(err));
        return;
    }

    printf("Generated mnemonic: %s\n", synor_mnemonic_get_phrase(mnemonic));
    printf("Word count: %d\n", synor_mnemonic_get_word_count(mnemonic));

    // Validate a mnemonic
    synor_validation_result_t validation;
    err = synor_mnemonic_validate(crypto, synor_mnemonic_get_phrase(mnemonic), &validation);
    if (err == SYNOR_OK) {
        printf("Valid: %s\n", validation.is_valid ? "true" : "false");
        if (!validation.is_valid && validation.error) {
            printf("Error: %s\n", validation.error);
        }
    }

    // Convert mnemonic to seed
    uint8_t seed[64];
    size_t seed_len;
    err = synor_mnemonic_to_seed(crypto, synor_mnemonic_get_phrase(mnemonic),
                                  "optional-passphrase", seed, &seed_len);
    if (err == SYNOR_OK) {
        printf("Seed (hex): ");
        print_hex(seed, seed_len, 16);
        printf("\n");
    }

    // Word suggestions for autocomplete
    char** suggestions;
    size_t suggestion_count;
    err = synor_mnemonic_suggest_words(crypto, "aban", 5, &suggestions, &suggestion_count);
    if (err == SYNOR_OK) {
        printf("Suggestions for 'aban': ");
        for (size_t i = 0; i < suggestion_count; i++) {
            printf("%s%s", suggestions[i], i < suggestion_count - 1 ? ", " : "");
        }
        printf("\n");
        synor_string_array_free(suggestions, suggestion_count);
    }

    synor_mnemonic_free(mnemonic);
    printf("\n");
}

void keypair_example(synor_crypto_t* crypto) {
    printf("=== Keypair Operations ===\n");

    synor_error_t err;
    synor_hybrid_keypair_t* keypair = NULL;

    // Generate a random keypair
    err = synor_keypair_generate(crypto, &keypair);
    if (err != SYNOR_OK) {
        fprintf(stderr, "Failed to generate keypair: %s\n", synor_error_string(err));
        return;
    }

    printf("Generated hybrid keypair:\n");
    printf("  Ed25519 public key size: %zu bytes\n",
           synor_keypair_get_ed25519_pubkey_size(keypair));
    printf("  Dilithium public key size: %zu bytes\n",
           synor_keypair_get_dilithium_pubkey_size(keypair));
    printf("  Total public key size: %zu bytes\n",
           synor_keypair_get_pubkey_size(keypair));

    // Get addresses for different networks
    char address[128];
    printf("\nAddresses:\n");

    synor_keypair_get_address(keypair, SYNOR_NETWORK_MAINNET, address, sizeof(address));
    printf("  Mainnet: %s\n", address);

    synor_keypair_get_address(keypair, SYNOR_NETWORK_TESTNET, address, sizeof(address));
    printf("  Testnet: %s\n", address);

    synor_keypair_get_address(keypair, SYNOR_NETWORK_DEVNET, address, sizeof(address));
    printf("  Devnet: %s\n", address);

    // Create keypair from mnemonic (deterministic)
    synor_mnemonic_t* mnemonic = NULL;
    synor_mnemonic_generate(crypto, 24, &mnemonic);

    synor_hybrid_keypair_t* keypair2 = NULL;
    err = synor_keypair_from_mnemonic(crypto, synor_mnemonic_get_phrase(mnemonic), "", &keypair2);
    if (err == SYNOR_OK) {
        synor_keypair_get_address(keypair2, SYNOR_NETWORK_MAINNET, address, sizeof(address));
        printf("\nKeypair from mnemonic: %.20s...\n", address);
        synor_keypair_free(keypair2);
    }

    // Derive child keypair using BIP-44 path
    printf("Derivation path: m/44'/21337'/0'/0/0\n");

    synor_mnemonic_free(mnemonic);
    synor_keypair_free(keypair);
    printf("\n");
}

void signing_example(synor_crypto_t* crypto) {
    printf("=== Hybrid Signing ===\n");

    synor_error_t err;
    synor_hybrid_keypair_t* keypair = NULL;

    // Generate keypair
    err = synor_keypair_generate(crypto, &keypair);
    if (err != SYNOR_OK) {
        fprintf(stderr, "Failed to generate keypair\n");
        return;
    }

    // Sign a message
    const char* message = "Hello, quantum-resistant world!";
    synor_hybrid_signature_t* signature = NULL;

    err = synor_sign(crypto, keypair, (const uint8_t*)message, strlen(message), &signature);
    if (err != SYNOR_OK) {
        fprintf(stderr, "Failed to sign message\n");
        synor_keypair_free(keypair);
        return;
    }

    printf("Signature created:\n");
    printf("  Ed25519 component: %zu bytes\n", synor_signature_get_ed25519_size(signature));
    printf("  Dilithium component: %zu bytes\n", synor_signature_get_dilithium_size(signature));
    printf("  Total signature size: %zu bytes\n", synor_signature_get_size(signature));

    // Verify the signature
    bool valid;
    err = synor_verify(crypto, keypair, (const uint8_t*)message, strlen(message), signature, &valid);
    printf("\nVerification result: %s\n", valid ? "true" : "false");

    // Verify with tampered message fails
    const char* tampered = "Hello, tampered message!";
    err = synor_verify(crypto, keypair, (const uint8_t*)tampered, strlen(tampered), signature, &valid);
    printf("Tampered message verification: %s\n", valid ? "true" : "false");

    synor_signature_free(signature);
    synor_keypair_free(keypair);
    printf("\n");
}

void falcon_example(synor_crypto_t* crypto) {
    printf("=== Falcon Post-Quantum Signatures ===\n");

    synor_error_t err;

    // Generate Falcon-512 keypair (128-bit security)
    synor_falcon_keypair_t* falcon512 = NULL;
    err = synor_falcon_generate(crypto, SYNOR_FALCON_512, &falcon512);
    if (err == SYNOR_OK) {
        printf("Falcon-512 keypair:\n");
        printf("  Public key: %zu bytes\n", synor_falcon_get_pubkey_size(falcon512));
        printf("  Security level: 128-bit\n");
    }

    // Generate Falcon-1024 keypair (256-bit security)
    synor_falcon_keypair_t* falcon1024 = NULL;
    err = synor_falcon_generate(crypto, SYNOR_FALCON_1024, &falcon1024);
    if (err == SYNOR_OK) {
        printf("\nFalcon-1024 keypair:\n");
        printf("  Public key: %zu bytes\n", synor_falcon_get_pubkey_size(falcon1024));
        printf("  Security level: 256-bit\n");
    }

    // Sign with Falcon-512
    const char* message = "Post-quantum secure message";
    synor_falcon_signature_t* signature = NULL;

    err = synor_falcon_sign(crypto, falcon512, (const uint8_t*)message, strlen(message), &signature);
    if (err == SYNOR_OK) {
        printf("\nFalcon-512 signature: %zu bytes\n", synor_falcon_signature_size(signature));

        // Verify
        bool valid;
        err = synor_falcon_verify(crypto, falcon512, (const uint8_t*)message, strlen(message),
                                   signature, &valid);
        printf("Verification: %s\n", valid ? "true" : "false");
        synor_falcon_signature_free(signature);
    }

    synor_falcon_keypair_free(falcon512);
    synor_falcon_keypair_free(falcon1024);
    printf("\n");
}

void sphincs_example(synor_crypto_t* crypto) {
    printf("=== SPHINCS+ Hash-Based Signatures ===\n");

    synor_error_t err;

    // SPHINCS+ variants with different security levels
    struct {
        synor_sphincs_variant_t variant;
        int security;
        int sig_size;
        const char* name;
    } variants[] = {
        {SYNOR_SPHINCS_SHAKE128S, 128, 7856, "SHAKE128S"},
        {SYNOR_SPHINCS_SHAKE192S, 192, 16224, "SHAKE192S"},
        {SYNOR_SPHINCS_SHAKE256S, 256, 29792, "SHAKE256S"},
    };

    const char* message = "Hash-based quantum security";

    for (int i = 0; i < 3; i++) {
        synor_sphincs_keypair_t* keypair = NULL;
        err = synor_sphincs_generate(crypto, variants[i].variant, &keypair);
        if (err != SYNOR_OK) continue;

        printf("SPHINCS+ %s:\n", variants[i].name);
        printf("  Security level: %d-bit\n", variants[i].security);
        printf("  Expected signature size: %d bytes\n", variants[i].sig_size);

        // Sign a message
        synor_sphincs_signature_t* signature = NULL;
        err = synor_sphincs_sign(crypto, keypair, (const uint8_t*)message, strlen(message), &signature);
        if (err == SYNOR_OK) {
            printf("  Actual signature size: %zu bytes\n", synor_sphincs_signature_size(signature));

            // Verify
            bool valid;
            synor_sphincs_verify(crypto, keypair, (const uint8_t*)message, strlen(message),
                                  signature, &valid);
            printf("  Verification: %s\n\n", valid ? "true" : "false");
            synor_sphincs_signature_free(signature);
        }

        synor_sphincs_keypair_free(keypair);
    }
}

void kdf_example(synor_crypto_t* crypto) {
    printf("=== Key Derivation Functions ===\n");

    synor_error_t err;

    // HKDF (HMAC-based Key Derivation Function)
    const char* seed = "master-secret-key-material-here";
    const char* salt = "application-salt";
    const char* info = "encryption-key";

    uint8_t derived_key[32];
    synor_derivation_config_t hkdf_config = {
        .salt = (const uint8_t*)salt,
        .salt_len = strlen(salt),
        .info = (const uint8_t*)info,
        .info_len = strlen(info),
        .output_length = 32
    };

    err = synor_kdf_derive(crypto, (const uint8_t*)seed, strlen(seed), &hkdf_config,
                           derived_key, sizeof(derived_key));
    if (err == SYNOR_OK) {
        printf("HKDF derived key: ");
        print_hex(derived_key, 32, 32);
        printf("\n");
    }

    // PBKDF2 (Password-Based Key Derivation Function)
    const char* password = "user-password";
    const char* pbkdf2_salt = "random-salt-value";

    uint8_t password_key[32];
    synor_password_config_t pbkdf2_config = {
        .salt = (const uint8_t*)pbkdf2_salt,
        .salt_len = strlen(pbkdf2_salt),
        .iterations = 100000,
        .output_length = 32
    };

    err = synor_kdf_derive_password(crypto, (const uint8_t*)password, strlen(password),
                                     &pbkdf2_config, password_key, sizeof(password_key));
    if (err == SYNOR_OK) {
        printf("PBKDF2 derived key: ");
        print_hex(password_key, 32, 32);
        printf("\n");
    }

    printf("\n");
}

void hash_example(synor_crypto_t* crypto) {
    printf("=== Hash Functions ===\n");

    synor_error_t err;
    const char* data = "Data to hash";
    uint8_t hash[32];

    // SHA3-256 (FIPS 202)
    err = synor_hash_sha3_256(crypto, (const uint8_t*)data, strlen(data), hash);
    if (err == SYNOR_OK) {
        printf("SHA3-256: ");
        print_hex(hash, 32, 32);
        printf("\n");
    }

    // BLAKE3 (fast, parallel)
    err = synor_hash_blake3(crypto, (const uint8_t*)data, strlen(data), hash);
    if (err == SYNOR_OK) {
        printf("BLAKE3:   ");
        print_hex(hash, 32, 32);
        printf("\n");
    }

    // Keccak-256 (Ethereum compatible)
    err = synor_hash_keccak256(crypto, (const uint8_t*)data, strlen(data), hash);
    if (err == SYNOR_OK) {
        printf("Keccak:   ");
        print_hex(hash, 32, 32);
        printf("\n");
    }

    printf("\n");
}

int main(int argc, char** argv) {
    synor_error_t err;

    // Initialize client
    synor_crypto_config_t config = {
        .api_key = getenv("SYNOR_API_KEY") ? getenv("SYNOR_API_KEY") : "your-api-key",
        .endpoint = "https://crypto.synor.io/v1",
        .timeout_ms = 30000,
        .retries = 3,
        .debug = false,
        .default_network = SYNOR_NETWORK_MAINNET
    };

    synor_crypto_t* crypto = NULL;
    err = synor_crypto_init(&config, &crypto);
    if (err != SYNOR_OK) {
        fprintf(stderr, "Failed to initialize crypto client: %s\n", synor_error_string(err));
        return 1;
    }

    // Check service health
    bool healthy;
    err = synor_crypto_health_check(crypto, &healthy);
    printf("Service healthy: %s\n\n", healthy ? "true" : "false");

    // Run examples
    mnemonic_example(crypto);
    keypair_example(crypto);
    signing_example(crypto);
    falcon_example(crypto);
    sphincs_example(crypto);
    kdf_example(crypto);
    hash_example(crypto);

    // Cleanup
    synor_crypto_free(crypto);

    return 0;
}
