/*
 * NOSTR Core Library - Utilities
 *
 * General utility functions used across multiple NIPs
 */

#ifndef NOSTR_UTILS_H
#define NOSTR_UTILS_H

#include <stddef.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

// =============================================================================
// UTILITY FUNCTIONS
// =============================================================================

// Convert bytes to hexadecimal string
void nostr_bytes_to_hex(const unsigned char *bytes, size_t len, char *hex);

// Convert hexadecimal string to bytes
int nostr_hex_to_bytes(const char *hex, unsigned char *bytes, size_t len);

// Base64 encoding function 
size_t base64_encode(const unsigned char *data, size_t len, char *output,
                     size_t output_size);

// Base64 decoding function
size_t base64_decode(const char *input, unsigned char *output);


// =============================================================================
// CORE CRYPTO FUNCTIONS
// =============================================================================

// Initialize crypto subsystem
int nostr_crypto_init(void);

// Cleanup crypto subsystem
void nostr_crypto_cleanup(void);

// SHA-256 hash function
int nostr_sha256(const unsigned char *data, size_t len, unsigned char *hash);

// =============================================================================
// STREAMING SHA-256 FUNCTIONS
// =============================================================================

// SHA-256 streaming context
typedef struct {
    uint32_t state[8];      // Current hash state
    unsigned char buffer[64]; // Input buffer for incomplete blocks
    uint64_t bitlen;        // Total bits processed
    size_t buflen;          // Current buffer length
} nostr_sha256_ctx_t;

// Initialize SHA-256 streaming context
int nostr_sha256_init(nostr_sha256_ctx_t* ctx);

// Update SHA-256 context with new data
int nostr_sha256_update(nostr_sha256_ctx_t* ctx, const unsigned char* data, size_t len);

// Finalize SHA-256 and output hash
int nostr_sha256_final(nostr_sha256_ctx_t* ctx, unsigned char* hash);

// Stream SHA-256 hash of a file
int nostr_sha256_file_stream(const char* filename, unsigned char* hash);

// HMAC-SHA256
int nostr_hmac_sha256(const unsigned char *key, size_t key_len,
                      const unsigned char *data, size_t data_len,
                      unsigned char *output);

// HMAC-SHA512
int nostr_hmac_sha512(const unsigned char *key, size_t key_len,
                      const unsigned char *data, size_t data_len,
                      unsigned char *output);

// PBKDF2 with HMAC-SHA512
int nostr_pbkdf2_hmac_sha512(const unsigned char *password, size_t password_len,
                             const unsigned char *salt, size_t salt_len,
                             int iterations, unsigned char *output,
                             size_t output_len);

// SHA-512 implementation (for testing)
int nostr_sha512(const unsigned char *data, size_t len, unsigned char *hash);

// =============================================================================
// SECP256K1 ELLIPTIC CURVE FUNCTIONS
// =============================================================================

// Verify private key is valid
int nostr_ec_private_key_verify(const unsigned char *private_key);

// Generate public key from private key
int nostr_ec_public_key_from_private_key(const unsigned char *private_key,
                                         unsigned char *public_key);

// Sign data with ECDSA
int nostr_ec_sign(const unsigned char *private_key, const unsigned char *hash,
                  unsigned char *signature);

// RFC 6979 deterministic nonce generation
int nostr_rfc6979_generate_k(const unsigned char *private_key,
                             const unsigned char *message_hash,
                             unsigned char *k_out);

int nostr_schnorr_sign(const unsigned char* private_key,
                       const unsigned char* hash,
                       unsigned char* signature);


// =============================================================================
// HKDF KEY DERIVATION FUNCTIONS
// =============================================================================

// HKDF Extract step
int nostr_hkdf_extract(const unsigned char *salt, size_t salt_len,
                       const unsigned char *ikm, size_t ikm_len,
                       unsigned char *prk);

// HKDF Expand step
int nostr_hkdf_expand(const unsigned char *prk, size_t prk_len,
                      const unsigned char *info, size_t info_len,
                      unsigned char *okm, size_t okm_len);

// HKDF (Extract + Expand)
int nostr_hkdf(const unsigned char *salt, size_t salt_len,
               const unsigned char *ikm, size_t ikm_len,
               const unsigned char *info, size_t info_len, unsigned char *okm,
               size_t okm_len);

// ECDH shared secret computation (for debugging)
int ecdh_shared_secret(const unsigned char *private_key,
                       const unsigned char *public_key_x,
                       unsigned char *shared_secret);




// =============================================================================
// BIP39 MNEMONIC FUNCTIONS
// =============================================================================

// Generate mnemonic from entropy
int nostr_bip39_mnemonic_from_bytes(const unsigned char *entropy,
                                    size_t entropy_len, char *mnemonic);

// Validate mnemonic
int nostr_bip39_mnemonic_validate(const char *mnemonic);

// Convert mnemonic to seed
int nostr_bip39_mnemonic_to_seed(const char *mnemonic, const char *passphrase,
                                 unsigned char *seed, size_t seed_len);

// =============================================================================
// BIP32 HD WALLET FUNCTIONS
// =============================================================================

typedef struct {
  unsigned char private_key[32];
  unsigned char public_key[33];
  unsigned char chain_code[32];
  uint32_t depth;
  uint32_t parent_fingerprint;
  uint32_t child_number;
} nostr_hd_key_t;

// Create master key from seed
int nostr_bip32_key_from_seed(const unsigned char *seed, size_t seed_len,
                              nostr_hd_key_t *master_key);

// Derive child key from parent
int nostr_bip32_derive_child(const nostr_hd_key_t *parent_key,
                             uint32_t child_number, nostr_hd_key_t *child_key);

// Derive key from path
int nostr_bip32_derive_path(const nostr_hd_key_t *master_key,
                            const uint32_t *path, size_t path_len,
                            nostr_hd_key_t *derived_key);

#ifdef __cplusplus
}
#endif

#endif // NOSTR_UTILS_H
