// Package main demonstrates the Synor Crypto SDK for Go
//
// This example covers quantum-resistant cryptographic operations:
// - Hybrid Ed25519 + Dilithium3 signatures
// - BIP-39 mnemonic generation and validation
// - Post-quantum algorithms (Falcon, SPHINCS+)
// - Key derivation functions
package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/synor/sdk-go/crypto"
)

func main() {
	// Initialize client
	config := crypto.Config{
		APIKey:         getEnv("SYNOR_API_KEY", "your-api-key"),
		Endpoint:       "https://crypto.synor.io/v1",
		Timeout:        30 * time.Second,
		Retries:        3,
		Debug:          false,
		DefaultNetwork: crypto.NetworkMainnet,
	}

	client, err := crypto.NewClient(config)
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}
	defer client.Close()

	ctx := context.Background()

	// Check service health
	healthy, err := client.HealthCheck(ctx)
	if err != nil {
		log.Printf("Health check failed: %v", err)
	} else {
		fmt.Printf("Service healthy: %v\n\n", healthy)
	}

	// Run examples
	mnemonicExample(ctx, client)
	keypairExample(ctx, client)
	signingExample(ctx, client)
	falconExample(ctx, client)
	sphincsExample(ctx, client)
	kdfExample(ctx, client)
	hashExample(ctx, client)
}

func mnemonicExample(ctx context.Context, client *crypto.Client) {
	fmt.Println("=== Mnemonic Operations ===")

	// Generate a 24-word mnemonic (256-bit entropy)
	mnemonic, err := client.Mnemonic.Generate(ctx, 24)
	if err != nil {
		log.Printf("Failed to generate mnemonic: %v", err)
		return
	}
	fmt.Printf("Generated mnemonic: %s\n", mnemonic.Phrase)
	fmt.Printf("Word count: %d\n", mnemonic.WordCount)

	// Validate a mnemonic
	validation, err := client.Mnemonic.Validate(ctx, mnemonic.Phrase)
	if err != nil {
		log.Printf("Failed to validate mnemonic: %v", err)
		return
	}
	fmt.Printf("Valid: %v\n", validation.Valid)
	if !validation.Valid {
		fmt.Printf("Error: %s\n", validation.Error)
	}

	// Convert mnemonic to seed
	seed, err := client.Mnemonic.ToSeed(ctx, mnemonic.Phrase, "optional-passphrase")
	if err != nil {
		log.Printf("Failed to convert to seed: %v", err)
		return
	}
	fmt.Printf("Seed (hex): %s...\n", fmt.Sprintf("%x", seed)[:32])

	// Word suggestions for autocomplete
	suggestions, err := client.Mnemonic.SuggestWords(ctx, "aban", 5)
	if err != nil {
		log.Printf("Failed to get suggestions: %v", err)
		return
	}
	fmt.Printf("Suggestions for 'aban': %v\n", suggestions)

	fmt.Println()
}

func keypairExample(ctx context.Context, client *crypto.Client) {
	fmt.Println("=== Keypair Operations ===")

	// Generate a random keypair
	keypair, err := client.Keypairs.Generate(ctx)
	if err != nil {
		log.Printf("Failed to generate keypair: %v", err)
		return
	}
	fmt.Println("Generated hybrid keypair:")
	fmt.Printf("  Ed25519 public key size: %d bytes\n", len(keypair.PublicKey.Ed25519Bytes))
	fmt.Printf("  Dilithium public key size: %d bytes\n", len(keypair.PublicKey.DilithiumBytes))
	fmt.Printf("  Total public key size: %d bytes\n", keypair.PublicKey.Size)

	// Get addresses for different networks
	fmt.Println("\nAddresses:")
	fmt.Printf("  Mainnet: %s\n", keypair.GetAddress(crypto.NetworkMainnet))
	fmt.Printf("  Testnet: %s\n", keypair.GetAddress(crypto.NetworkTestnet))
	fmt.Printf("  Devnet: %s\n", keypair.GetAddress(crypto.NetworkDevnet))

	// Create keypair from mnemonic (deterministic)
	mnemonic, err := client.Mnemonic.Generate(ctx, 24)
	if err != nil {
		log.Printf("Failed to generate mnemonic: %v", err)
		return
	}

	keypair2, err := client.Keypairs.FromMnemonic(ctx, mnemonic.Phrase, "")
	if err != nil {
		log.Printf("Failed to create keypair from mnemonic: %v", err)
		return
	}
	addr := keypair2.GetAddress(crypto.NetworkMainnet)
	fmt.Printf("\nKeypair from mnemonic: %s...\n", addr[:20])

	// Derive child keypair using BIP-44 path
	path := crypto.DerivationPathExternal(0, 0) // m/44'/21337'/0'/0/0
	fmt.Printf("Derivation path: %s\n", path)

	fmt.Println()
}

func signingExample(ctx context.Context, client *crypto.Client) {
	fmt.Println("=== Hybrid Signing ===")

	// Generate keypair
	keypair, err := client.Keypairs.Generate(ctx)
	if err != nil {
		log.Printf("Failed to generate keypair: %v", err)
		return
	}

	// Sign a message
	message := []byte("Hello, quantum-resistant world!")
	signature, err := client.Signing.Sign(ctx, keypair, message)
	if err != nil {
		log.Printf("Failed to sign message: %v", err)
		return
	}

	fmt.Println("Signature created:")
	fmt.Printf("  Ed25519 component: %d bytes\n", len(signature.Ed25519Bytes))
	fmt.Printf("  Dilithium component: %d bytes\n", len(signature.DilithiumBytes))
	fmt.Printf("  Total signature size: %d bytes\n", signature.Size)

	// Verify the signature
	valid, err := client.Signing.Verify(ctx, keypair.PublicKey, message, signature)
	if err != nil {
		log.Printf("Failed to verify signature: %v", err)
		return
	}
	fmt.Printf("\nVerification result: %v\n", valid)

	// Verify with tampered message fails
	tamperedMessage := []byte("Hello, tampered message!")
	invalidResult, err := client.Signing.Verify(ctx, keypair.PublicKey, tamperedMessage, signature)
	if err != nil {
		log.Printf("Failed to verify tampered signature: %v", err)
		return
	}
	fmt.Printf("Tampered message verification: %v\n", invalidResult)

	fmt.Println()
}

func falconExample(ctx context.Context, client *crypto.Client) {
	fmt.Println("=== Falcon Post-Quantum Signatures ===")

	// Generate Falcon-512 keypair (128-bit security)
	falcon512, err := client.Falcon.Generate(ctx, crypto.Falcon512)
	if err != nil {
		log.Printf("Failed to generate Falcon-512 keypair: %v", err)
		return
	}
	fmt.Println("Falcon-512 keypair:")
	fmt.Printf("  Public key: %d bytes\n", len(falcon512.PublicKey.KeyBytes))
	fmt.Println("  Security level: 128-bit")

	// Generate Falcon-1024 keypair (256-bit security)
	falcon1024, err := client.Falcon.Generate(ctx, crypto.Falcon1024)
	if err != nil {
		log.Printf("Failed to generate Falcon-1024 keypair: %v", err)
		return
	}
	fmt.Println("\nFalcon-1024 keypair:")
	fmt.Printf("  Public key: %d bytes\n", len(falcon1024.PublicKey.KeyBytes))
	fmt.Println("  Security level: 256-bit")

	// Sign with Falcon-512
	message := []byte("Post-quantum secure message")
	signature, err := client.Falcon.Sign(ctx, falcon512, message)
	if err != nil {
		log.Printf("Failed to sign with Falcon-512: %v", err)
		return
	}
	fmt.Printf("\nFalcon-512 signature: %d bytes\n", len(signature.SignatureBytes))

	// Verify
	valid, err := client.Falcon.Verify(ctx, falcon512.PublicKey.KeyBytes, message, signature)
	if err != nil {
		log.Printf("Failed to verify Falcon signature: %v", err)
		return
	}
	fmt.Printf("Verification: %v\n", valid)

	fmt.Println()
}

func sphincsExample(ctx context.Context, client *crypto.Client) {
	fmt.Println("=== SPHINCS+ Hash-Based Signatures ===")

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

	// Generate and demonstrate each variant
	for _, v := range variants {
		keypair, err := client.Sphincs.Generate(ctx, v.variant)
		if err != nil {
			log.Printf("Failed to generate SPHINCS+ keypair: %v", err)
			continue
		}
		fmt.Printf("SPHINCS+ %s:\n", v.variant)
		fmt.Printf("  Security level: %d-bit\n", v.security)
		fmt.Printf("  Expected signature size: %d bytes\n", v.sigSize)

		// Sign a message
		message := []byte("Hash-based quantum security")
		signature, err := client.Sphincs.Sign(ctx, keypair, message)
		if err != nil {
			log.Printf("Failed to sign with SPHINCS+: %v", err)
			continue
		}
		fmt.Printf("  Actual signature size: %d bytes\n", len(signature.SignatureBytes))

		// Verify
		valid, err := client.Sphincs.Verify(ctx, keypair.PublicKey.KeyBytes, message, signature)
		if err != nil {
			log.Printf("Failed to verify SPHINCS+ signature: %v", err)
			continue
		}
		fmt.Printf("  Verification: %v\n\n", valid)
	}
}

func kdfExample(ctx context.Context, client *crypto.Client) {
	fmt.Println("=== Key Derivation Functions ===")

	// HKDF (HMAC-based Key Derivation Function)
	seed := []byte("master-secret-key-material-here")
	hkdfConfig := crypto.DerivationConfig{
		Salt:         []byte("application-salt"),
		Info:         []byte("encryption-key"),
		OutputLength: 32,
	}

	derivedKey, err := client.KDF.DeriveKey(ctx, seed, hkdfConfig)
	if err != nil {
		log.Printf("Failed to derive key with HKDF: %v", err)
		return
	}
	fmt.Printf("HKDF derived key: %x\n", derivedKey)

	// PBKDF2 (Password-Based Key Derivation Function)
	password := []byte("user-password")
	pbkdf2Config := crypto.PasswordDerivationConfig{
		Salt:         []byte("random-salt-value"),
		Iterations:   100000,
		OutputLength: 32,
	}

	passwordKey, err := client.KDF.DeriveFromPassword(ctx, password, pbkdf2Config)
	if err != nil {
		log.Printf("Failed to derive key with PBKDF2: %v", err)
		return
	}
	fmt.Printf("PBKDF2 derived key: %x\n", passwordKey)

	fmt.Println()
}

func hashExample(ctx context.Context, client *crypto.Client) {
	fmt.Println("=== Hash Functions ===")

	data := []byte("Data to hash")

	// SHA3-256 (FIPS 202)
	sha3, err := client.Hash.SHA3_256(ctx, data)
	if err != nil {
		log.Printf("Failed to compute SHA3-256: %v", err)
		return
	}
	fmt.Printf("SHA3-256: %s\n", sha3.Hex)

	// BLAKE3 (fast, parallel)
	blake3, err := client.Hash.Blake3(ctx, data)
	if err != nil {
		log.Printf("Failed to compute BLAKE3: %v", err)
		return
	}
	fmt.Printf("BLAKE3:   %s\n", blake3.Hex)

	// Keccak-256 (Ethereum compatible)
	keccak, err := client.Hash.Keccak256(ctx, data)
	if err != nil {
		log.Printf("Failed to compute Keccak-256: %v", err)
		return
	}
	fmt.Printf("Keccak:   %s\n", keccak.Hex)

	fmt.Println()
}

func getEnv(key, defaultValue string) string {
	if value := os.Getenv(key); value != "" {
		return value
	}
	return defaultValue
}
