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

import {
  SynorCrypto,
  CryptoConfig,
  Network,
  FalconVariant,
  SphincsVariant,
  DerivationConfig,
  PasswordDerivationConfig,
  DerivationPath,
} from '../src/crypto';

async function main() {
  // Initialize client
  const config: CryptoConfig = {
    apiKey: process.env.SYNOR_API_KEY || 'your-api-key',
    endpoint: 'https://crypto.synor.io/v1',
    timeout: 30000,
    retries: 3,
    debug: false,
    defaultNetwork: Network.Mainnet,
  };

  const crypto = new SynorCrypto(config);

  try {
    // Check service health
    const healthy = await crypto.healthCheck();
    console.log(`Service healthy: ${healthy}\n`);

    // Example 1: Mnemonic operations
    await mnemonicExample(crypto);

    // Example 2: Keypair generation
    await keypairExample(crypto);

    // Example 3: Hybrid signing
    await signingExample(crypto);

    // Example 4: Falcon post-quantum signatures
    await falconExample(crypto);

    // Example 5: SPHINCS+ post-quantum signatures
    await sphincsExample(crypto);

    // Example 6: Key derivation
    await kdfExample(crypto);

    // Example 7: Hashing
    await hashExample(crypto);
  } finally {
    crypto.close();
  }
}

/**
 * Mnemonic generation and validation
 */
async function mnemonicExample(crypto: SynorCrypto): Promise<void> {
  console.log('=== Mnemonic Operations ===');

  // Generate a 24-word mnemonic (256-bit entropy)
  const mnemonic = await crypto.mnemonic.generate(24);
  console.log(`Generated mnemonic: ${mnemonic.phrase}`);
  console.log(`Word count: ${mnemonic.wordCount}`);

  // Validate a mnemonic
  const validation = await crypto.mnemonic.validate(mnemonic.phrase);
  console.log(`Valid: ${validation.valid}`);
  if (!validation.valid) {
    console.log(`Error: ${validation.error}`);
  }

  // Convert mnemonic to seed
  const seed = await crypto.mnemonic.toSeed(mnemonic.phrase, 'optional-passphrase');
  console.log(`Seed (hex): ${Buffer.from(seed).toString('hex').slice(0, 32)}...`);

  // Word suggestions for autocomplete
  const suggestions = await crypto.mnemonic.suggestWords('aban', 5);
  console.log(`Suggestions for "aban": ${suggestions.join(', ')}`);

  console.log('');
}

/**
 * Keypair generation and address derivation
 */
async function keypairExample(crypto: SynorCrypto): Promise<void> {
  console.log('=== Keypair Operations ===');

  // Generate a random keypair
  const keypair = await crypto.keypairs.generate();
  console.log('Generated hybrid keypair:');
  console.log(`  Ed25519 public key size: ${keypair.publicKey.ed25519Bytes.length} bytes`);
  console.log(`  Dilithium public key size: ${keypair.publicKey.dilithiumBytes.length} bytes`);
  console.log(`  Total public key size: ${keypair.publicKey.size} bytes`);

  // Get addresses for different networks
  console.log('\nAddresses:');
  console.log(`  Mainnet: ${keypair.getAddress(Network.Mainnet)}`);
  console.log(`  Testnet: ${keypair.getAddress(Network.Testnet)}`);
  console.log(`  Devnet: ${keypair.getAddress(Network.Devnet)}`);

  // Create keypair from mnemonic (deterministic)
  const mnemonic = await crypto.mnemonic.generate(24);
  const keypair2 = await crypto.keypairs.fromMnemonic(mnemonic.phrase, '');
  console.log(`\nKeypair from mnemonic: ${keypair2.getAddress(Network.Mainnet).slice(0, 20)}...`);

  // Derive child keypair using BIP-44 path
  const path = DerivationPath.external(0, 0); // m/44'/21337'/0'/0/0
  console.log(`Derivation path: ${path.toString()}`);

  console.log('');
}

/**
 * Hybrid signature operations (Ed25519 + Dilithium3)
 */
async function signingExample(crypto: SynorCrypto): Promise<void> {
  console.log('=== Hybrid Signing ===');

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

  // Sign a message
  const message = Buffer.from('Hello, quantum-resistant world!');
  const signature = await crypto.signing.sign(keypair, message);

  console.log('Signature created:');
  console.log(`  Ed25519 component: ${signature.ed25519Bytes.length} bytes`);
  console.log(`  Dilithium component: ${signature.dilithiumBytes.length} bytes`);
  console.log(`  Total signature size: ${signature.size} bytes`);

  // Verify the signature
  const valid = await crypto.signing.verify(keypair.publicKey, message, signature);
  console.log(`\nVerification result: ${valid}`);

  // Verify with tampered message fails
  const tamperedMessage = Buffer.from('Hello, tampered message!');
  const invalidResult = await crypto.signing.verify(keypair.publicKey, tamperedMessage, signature);
  console.log(`Tampered message verification: ${invalidResult}`);

  console.log('');
}

/**
 * Falcon post-quantum signature example
 */
async function falconExample(crypto: SynorCrypto): Promise<void> {
  console.log('=== Falcon Post-Quantum Signatures ===');

  // Generate Falcon-512 keypair (128-bit security)
  const falcon512 = await crypto.falcon.generate(FalconVariant.Falcon512);
  console.log('Falcon-512 keypair:');
  console.log(`  Public key: ${falcon512.publicKey.bytes.length} bytes`);
  console.log(`  Security level: 128-bit`);

  // Generate Falcon-1024 keypair (256-bit security)
  const falcon1024 = await crypto.falcon.generate(FalconVariant.Falcon1024);
  console.log('\nFalcon-1024 keypair:');
  console.log(`  Public key: ${falcon1024.publicKey.bytes.length} bytes`);
  console.log(`  Security level: 256-bit`);

  // Sign with Falcon-512
  const message = Buffer.from('Post-quantum secure message');
  const signature = await crypto.falcon.sign(falcon512, message);
  console.log(`\nFalcon-512 signature: ${signature.signatureBytes.length} bytes`);

  // Verify
  const valid = await crypto.falcon.verify(
    falcon512.publicKey.bytes,
    message,
    signature
  );
  console.log(`Verification: ${valid}`);

  console.log('');
}

/**
 * SPHINCS+ post-quantum signature example (hash-based)
 */
async function sphincsExample(crypto: SynorCrypto): Promise<void> {
  console.log('=== SPHINCS+ Hash-Based Signatures ===');

  // SPHINCS+ variants with different security levels
  const variants = [
    { variant: SphincsVariant.Shake128s, security: 128, sigSize: 7856 },
    { variant: SphincsVariant.Shake192s, security: 192, sigSize: 16224 },
    { variant: SphincsVariant.Shake256s, security: 256, sigSize: 29792 },
  ];

  // Generate and demonstrate each variant
  for (const { variant, security, sigSize } of variants) {
    const keypair = await crypto.sphincs.generate(variant);
    console.log(`SPHINCS+ ${variant}:`);
    console.log(`  Security level: ${security}-bit`);
    console.log(`  Expected signature size: ${sigSize} bytes`);

    // Sign a message
    const message = Buffer.from('Hash-based quantum security');
    const signature = await crypto.sphincs.sign(keypair, message);
    console.log(`  Actual signature size: ${signature.signatureBytes.length} bytes`);

    // Verify
    const valid = await crypto.sphincs.verify(
      keypair.publicKey.bytes,
      message,
      signature
    );
    console.log(`  Verification: ${valid}\n`);
  }
}

/**
 * Key derivation functions
 */
async function kdfExample(crypto: SynorCrypto): Promise<void> {
  console.log('=== Key Derivation Functions ===');

  // HKDF (HMAC-based Key Derivation Function)
  const seed = Buffer.from('master-secret-key-material-here');
  const hkdfConfig: DerivationConfig = {
    salt: Buffer.from('application-salt'),
    info: Buffer.from('encryption-key'),
    outputLength: 32,
  };

  const derivedKey = await crypto.kdf.deriveKey(seed, hkdfConfig);
  console.log(`HKDF derived key: ${Buffer.from(derivedKey).toString('hex')}`);

  // PBKDF2 (Password-Based Key Derivation Function)
  const password = Buffer.from('user-password');
  const pbkdf2Config: PasswordDerivationConfig = {
    salt: Buffer.from('random-salt-value'),
    iterations: 100000,
    outputLength: 32,
  };

  const passwordKey = await crypto.kdf.deriveFromPassword(password, pbkdf2Config);
  console.log(`PBKDF2 derived key: ${Buffer.from(passwordKey).toString('hex')}`);

  console.log('');
}

/**
 * Cryptographic hash functions
 */
async function hashExample(crypto: SynorCrypto): Promise<void> {
  console.log('=== Hash Functions ===');

  const data = Buffer.from('Data to hash');

  // SHA3-256 (FIPS 202)
  const sha3 = await crypto.hash.sha3_256(data);
  console.log(`SHA3-256: ${sha3.hex}`);

  // BLAKE3 (fast, parallel)
  const blake3 = await crypto.hash.blake3(data);
  console.log(`BLAKE3:   ${blake3.hex}`);

  // Keccak-256 (Ethereum compatible)
  const keccak = await crypto.hash.keccak256(data);
  console.log(`Keccak:   ${keccak.hex}`);

  console.log('');
}

// Run examples
main().catch(console.error);
