/**
 * Synor Crypto SDK for C
 *
 * Quantum-resistant cryptographic primitives for the Synor blockchain.
 *
 * Example:
 * ```c
 * synor_crypto_config_t config = {
 *     .api_key = "your-api-key",
 *     .endpoint = "https://crypto.synor.io/v1",
 *     .timeout = 30000,
 *     .retries = 3
 * };
 *
 * synor_crypto_t* crypto = synor_crypto_create(&config);
 *
 * // Generate a mnemonic
 * synor_mnemonic_t mnemonic;
 * synor_crypto_mnemonic_generate(crypto, 24, &mnemonic);
 * printf("Backup words: %s\n", mnemonic.phrase);
 *
 * // Create keypair from mnemonic
 * synor_hybrid_keypair_t keypair;
 * synor_crypto_keypair_from_mnemonic(crypto, mnemonic.phrase, "", &keypair);
 *
 * synor_crypto_destroy(crypto);
 * ```
 */

#ifndef SYNOR_CRYPTO_H
#define SYNOR_CRYPTO_H

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

#ifdef __cplusplus
extern "C" {
#endif

/* ============================================================================
 * Constants
 * ============================================================================ */

#define SYNOR_CRYPTO_ED25519_PUBLIC_KEY_SIZE 32
#define SYNOR_CRYPTO_ED25519_SECRET_KEY_SIZE 32
#define SYNOR_CRYPTO_ED25519_SIGNATURE_SIZE 64
#define SYNOR_CRYPTO_DILITHIUM3_PUBLIC_KEY_SIZE 1952
#define SYNOR_CRYPTO_DILITHIUM3_SIGNATURE_SIZE 3293
#define SYNOR_CRYPTO_HYBRID_SIGNATURE_SIZE (64 + 3293)
#define SYNOR_CRYPTO_COIN_TYPE 0x5359
#define SYNOR_CRYPTO_MIN_PBKDF2_ITERATIONS 10000
#define SYNOR_CRYPTO_MIN_SALT_LENGTH 8
#define SYNOR_CRYPTO_DEFAULT_ENDPOINT "https://crypto.synor.io/v1"

#define SYNOR_CRYPTO_MAX_PHRASE_LEN 1024
#define SYNOR_CRYPTO_MAX_ADDRESS_LEN 128
#define SYNOR_CRYPTO_MAX_HASH_LEN 64
#define SYNOR_CRYPTO_MAX_ERROR_LEN 256

/* ============================================================================
 * Enumerations
 * ============================================================================ */

typedef enum {
    SYNOR_NETWORK_MAINNET = 0,
    SYNOR_NETWORK_TESTNET = 1,
    SYNOR_NETWORK_DEVNET = 2
} synor_network_t;

typedef enum {
    SYNOR_FALCON_512 = 0,
    SYNOR_FALCON_1024 = 1
} synor_falcon_variant_t;

typedef enum {
    SYNOR_SPHINCS_SHAKE128S = 0,
    SYNOR_SPHINCS_SHAKE192S = 1,
    SYNOR_SPHINCS_SHAKE256S = 2
} synor_sphincs_variant_t;

typedef enum {
    SYNOR_PQ_DILITHIUM3 = 0,
    SYNOR_PQ_FALCON512 = 1,
    SYNOR_PQ_FALCON1024 = 2,
    SYNOR_PQ_SPHINCS128S = 3,
    SYNOR_PQ_SPHINCS192S = 4,
    SYNOR_PQ_SPHINCS256S = 5
} synor_pq_algorithm_t;

typedef enum {
    SYNOR_ALGO_FAMILY_CLASSICAL = 0,
    SYNOR_ALGO_FAMILY_LATTICE = 1,
    SYNOR_ALGO_FAMILY_HASH_BASED = 2,
    SYNOR_ALGO_FAMILY_HYBRID = 3
} synor_algorithm_family_t;

typedef enum {
    SYNOR_OK = 0,
    SYNOR_ERROR_INVALID_PARAMS = -1,
    SYNOR_ERROR_NETWORK = -2,
    SYNOR_ERROR_AUTH = -3,
    SYNOR_ERROR_TIMEOUT = -4,
    SYNOR_ERROR_API = -5,
    SYNOR_ERROR_CLOSED = -6,
    SYNOR_ERROR_MEMORY = -7,
    SYNOR_ERROR_PARSE = -8
} synor_error_t;

/* ============================================================================
 * Configuration Types
 * ============================================================================ */

typedef struct {
    const char* api_key;
    const char* endpoint;
    uint32_t timeout;
    uint32_t retries;
    bool debug;
    synor_network_t default_network;
} synor_crypto_config_t;

typedef struct {
    uint8_t* salt;
    size_t salt_len;
    uint8_t* info;
    size_t info_len;
    uint32_t output_length;
} synor_derivation_config_t;

typedef struct {
    uint8_t* salt;
    size_t salt_len;
    uint32_t iterations;
    uint32_t output_length;
} synor_password_derivation_config_t;

typedef struct {
    uint32_t account;
    uint32_t change;
    uint32_t index;
} synor_derivation_path_t;

/* ============================================================================
 * Key Types
 * ============================================================================ */

typedef struct {
    char ed25519[88];  /* Base64 encoded */
    char dilithium[2608];  /* Base64 encoded */
} synor_hybrid_public_key_t;

typedef struct {
    char ed25519_seed[88];  /* Base64 encoded */
    char master_seed[88];   /* Base64 encoded */
} synor_secret_key_t;

typedef struct {
    synor_falcon_variant_t variant;
    uint8_t* bytes;
    size_t bytes_len;
} synor_falcon_public_key_t;

typedef struct {
    synor_falcon_variant_t variant;
    uint8_t* bytes;
    size_t bytes_len;
} synor_falcon_secret_key_t;

typedef struct {
    synor_sphincs_variant_t variant;
    uint8_t* bytes;
    size_t bytes_len;
} synor_sphincs_public_key_t;

typedef struct {
    synor_sphincs_variant_t variant;
    uint8_t* bytes;
    size_t bytes_len;
} synor_sphincs_secret_key_t;

/* ============================================================================
 * Signature Types
 * ============================================================================ */

typedef struct {
    char ed25519[88];     /* Base64 encoded */
    char dilithium[4392]; /* Base64 encoded */
} synor_hybrid_signature_t;

typedef struct {
    synor_falcon_variant_t variant;
    uint8_t* signature;
    size_t signature_len;
} synor_falcon_signature_t;

typedef struct {
    synor_sphincs_variant_t variant;
    uint8_t* signature;
    size_t signature_len;
} synor_sphincs_signature_t;

/* ============================================================================
 * Keypair Types
 * ============================================================================ */

typedef struct {
    synor_hybrid_public_key_t public_key;
    synor_secret_key_t secret_key;
    char addresses[3][SYNOR_CRYPTO_MAX_ADDRESS_LEN];  /* mainnet, testnet, devnet */
} synor_hybrid_keypair_t;

typedef struct {
    synor_falcon_variant_t variant;
    synor_falcon_public_key_t public_key;
    synor_falcon_secret_key_t secret_key;
} synor_falcon_keypair_t;

typedef struct {
    synor_sphincs_variant_t variant;
    synor_sphincs_public_key_t public_key;
    synor_sphincs_secret_key_t secret_key;
} synor_sphincs_keypair_t;

/* ============================================================================
 * Mnemonic Types
 * ============================================================================ */

typedef struct {
    char phrase[SYNOR_CRYPTO_MAX_PHRASE_LEN];
    char** words;
    size_t word_count;
    uint8_t* entropy;
    size_t entropy_len;
} synor_mnemonic_t;

typedef struct {
    bool valid;
    char error[SYNOR_CRYPTO_MAX_ERROR_LEN];
} synor_mnemonic_validation_t;

/* ============================================================================
 * Address Types
 * ============================================================================ */

typedef struct {
    char address[SYNOR_CRYPTO_MAX_ADDRESS_LEN];
    synor_network_t network;
    uint8_t pubkey_hash[32];
} synor_address_t;

/* ============================================================================
 * Hash Types
 * ============================================================================ */

typedef struct {
    char hex[SYNOR_CRYPTO_MAX_HASH_LEN + 1];
    uint8_t bytes[32];
} synor_hash256_t;

/* ============================================================================
 * Client Handle
 * ============================================================================ */

typedef struct synor_crypto_s synor_crypto_t;

/* ============================================================================
 * Client Lifecycle
 * ============================================================================ */

/**
 * Create a new Synor Crypto client.
 *
 * @param config Configuration for the client
 * @return Pointer to the client handle, or NULL on error
 */
synor_crypto_t* synor_crypto_create(const synor_crypto_config_t* config);

/**
 * Destroy a Synor Crypto client and free resources.
 *
 * @param crypto Client handle
 */
void synor_crypto_destroy(synor_crypto_t* crypto);

/**
 * Check if the client has been closed.
 *
 * @param crypto Client handle
 * @return true if closed, false otherwise
 */
bool synor_crypto_is_closed(const synor_crypto_t* crypto);

/**
 * Perform a health check on the API.
 *
 * @param crypto Client handle
 * @return SYNOR_OK if healthy, error code otherwise
 */
synor_error_t synor_crypto_health_check(synor_crypto_t* crypto);

/* ============================================================================
 * Mnemonic Operations
 * ============================================================================ */

/**
 * Generate a new mnemonic phrase.
 *
 * @param crypto Client handle
 * @param word_count Number of words (12, 15, 18, 21, or 24)
 * @param out Output mnemonic
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_mnemonic_generate(
    synor_crypto_t* crypto,
    uint32_t word_count,
    synor_mnemonic_t* out
);

/**
 * Parse an existing mnemonic phrase.
 *
 * @param crypto Client handle
 * @param phrase Mnemonic phrase
 * @param out Output mnemonic
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_mnemonic_from_phrase(
    synor_crypto_t* crypto,
    const char* phrase,
    synor_mnemonic_t* out
);

/**
 * Validate a mnemonic phrase.
 *
 * @param crypto Client handle
 * @param phrase Mnemonic phrase to validate
 * @param out Validation result
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_mnemonic_validate(
    synor_crypto_t* crypto,
    const char* phrase,
    synor_mnemonic_validation_t* out
);

/**
 * Convert a mnemonic phrase to a seed.
 *
 * @param crypto Client handle
 * @param phrase Mnemonic phrase
 * @param passphrase Optional passphrase (can be empty string)
 * @param seed Output seed buffer (must be at least 64 bytes)
 * @param seed_len Output seed length
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_mnemonic_to_seed(
    synor_crypto_t* crypto,
    const char* phrase,
    const char* passphrase,
    uint8_t* seed,
    size_t* seed_len
);

/**
 * Free mnemonic resources.
 *
 * @param mnemonic Mnemonic to free
 */
void synor_crypto_mnemonic_free(synor_mnemonic_t* mnemonic);

/* ============================================================================
 * Keypair Operations
 * ============================================================================ */

/**
 * Generate a new hybrid keypair.
 *
 * @param crypto Client handle
 * @param out Output keypair
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_keypair_generate(
    synor_crypto_t* crypto,
    synor_hybrid_keypair_t* out
);

/**
 * Create a keypair from a mnemonic phrase.
 *
 * @param crypto Client handle
 * @param phrase Mnemonic phrase
 * @param passphrase Optional passphrase (can be empty string)
 * @param out Output keypair
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_keypair_from_mnemonic(
    synor_crypto_t* crypto,
    const char* phrase,
    const char* passphrase,
    synor_hybrid_keypair_t* out
);

/**
 * Create a keypair from a seed.
 *
 * @param crypto Client handle
 * @param seed Seed bytes
 * @param seed_len Seed length
 * @param out Output keypair
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_keypair_from_seed(
    synor_crypto_t* crypto,
    const uint8_t* seed,
    size_t seed_len,
    synor_hybrid_keypair_t* out
);

/**
 * Get an address for a public key.
 *
 * @param crypto Client handle
 * @param public_key Public key
 * @param network Network type
 * @param out Output address
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_keypair_get_address(
    synor_crypto_t* crypto,
    const synor_hybrid_public_key_t* public_key,
    synor_network_t network,
    synor_address_t* out
);

/* ============================================================================
 * Signing Operations
 * ============================================================================ */

/**
 * Sign a message with a hybrid keypair.
 *
 * @param crypto Client handle
 * @param keypair Keypair for signing
 * @param message Message to sign
 * @param message_len Message length
 * @param out Output signature
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_sign(
    synor_crypto_t* crypto,
    const synor_hybrid_keypair_t* keypair,
    const uint8_t* message,
    size_t message_len,
    synor_hybrid_signature_t* out
);

/**
 * Verify a hybrid signature.
 *
 * @param crypto Client handle
 * @param public_key Public key for verification
 * @param message Original message
 * @param message_len Message length
 * @param signature Signature to verify
 * @param valid Output: true if valid, false otherwise
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_verify(
    synor_crypto_t* crypto,
    const synor_hybrid_public_key_t* public_key,
    const uint8_t* message,
    size_t message_len,
    const synor_hybrid_signature_t* signature,
    bool* valid
);

/**
 * Sign a message with Ed25519.
 *
 * @param crypto Client handle
 * @param secret_key Ed25519 secret key (32 bytes)
 * @param message Message to sign
 * @param message_len Message length
 * @param signature Output signature (64 bytes)
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_sign_ed25519(
    synor_crypto_t* crypto,
    const uint8_t* secret_key,
    const uint8_t* message,
    size_t message_len,
    uint8_t* signature
);

/* ============================================================================
 * Falcon Operations
 * ============================================================================ */

/**
 * Generate a Falcon keypair.
 *
 * @param crypto Client handle
 * @param variant Falcon variant (512 or 1024)
 * @param out Output keypair
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_falcon_generate(
    synor_crypto_t* crypto,
    synor_falcon_variant_t variant,
    synor_falcon_keypair_t* out
);

/**
 * Sign a message with Falcon.
 *
 * @param crypto Client handle
 * @param keypair Falcon keypair
 * @param message Message to sign
 * @param message_len Message length
 * @param out Output signature
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_falcon_sign(
    synor_crypto_t* crypto,
    const synor_falcon_keypair_t* keypair,
    const uint8_t* message,
    size_t message_len,
    synor_falcon_signature_t* out
);

/**
 * Verify a Falcon signature.
 *
 * @param crypto Client handle
 * @param public_key Falcon public key
 * @param public_key_len Public key length
 * @param message Original message
 * @param message_len Message length
 * @param signature Signature to verify
 * @param valid Output: true if valid, false otherwise
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_falcon_verify(
    synor_crypto_t* crypto,
    const uint8_t* public_key,
    size_t public_key_len,
    const uint8_t* message,
    size_t message_len,
    const synor_falcon_signature_t* signature,
    bool* valid
);

/**
 * Free Falcon keypair resources.
 *
 * @param keypair Keypair to free
 */
void synor_crypto_falcon_keypair_free(synor_falcon_keypair_t* keypair);

/**
 * Free Falcon signature resources.
 *
 * @param signature Signature to free
 */
void synor_crypto_falcon_signature_free(synor_falcon_signature_t* signature);

/* ============================================================================
 * SPHINCS+ Operations
 * ============================================================================ */

/**
 * Generate a SPHINCS+ keypair.
 *
 * @param crypto Client handle
 * @param variant SPHINCS+ variant
 * @param out Output keypair
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_sphincs_generate(
    synor_crypto_t* crypto,
    synor_sphincs_variant_t variant,
    synor_sphincs_keypair_t* out
);

/**
 * Sign a message with SPHINCS+.
 *
 * @param crypto Client handle
 * @param keypair SPHINCS+ keypair
 * @param message Message to sign
 * @param message_len Message length
 * @param out Output signature
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_sphincs_sign(
    synor_crypto_t* crypto,
    const synor_sphincs_keypair_t* keypair,
    const uint8_t* message,
    size_t message_len,
    synor_sphincs_signature_t* out
);

/**
 * Verify a SPHINCS+ signature.
 *
 * @param crypto Client handle
 * @param public_key SPHINCS+ public key
 * @param public_key_len Public key length
 * @param message Original message
 * @param message_len Message length
 * @param signature Signature to verify
 * @param valid Output: true if valid, false otherwise
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_sphincs_verify(
    synor_crypto_t* crypto,
    const uint8_t* public_key,
    size_t public_key_len,
    const uint8_t* message,
    size_t message_len,
    const synor_sphincs_signature_t* signature,
    bool* valid
);

/**
 * Free SPHINCS+ keypair resources.
 *
 * @param keypair Keypair to free
 */
void synor_crypto_sphincs_keypair_free(synor_sphincs_keypair_t* keypair);

/**
 * Free SPHINCS+ signature resources.
 *
 * @param signature Signature to free
 */
void synor_crypto_sphincs_signature_free(synor_sphincs_signature_t* signature);

/* ============================================================================
 * KDF Operations
 * ============================================================================ */

/**
 * Derive a key using HKDF.
 *
 * @param crypto Client handle
 * @param seed Input seed
 * @param seed_len Seed length
 * @param config Derivation configuration
 * @param key Output key buffer
 * @param key_len Output key length
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_kdf_derive(
    synor_crypto_t* crypto,
    const uint8_t* seed,
    size_t seed_len,
    const synor_derivation_config_t* config,
    uint8_t* key,
    size_t* key_len
);

/**
 * Derive a key from a password using PBKDF2.
 *
 * @param crypto Client handle
 * @param password Password bytes
 * @param password_len Password length
 * @param config Password derivation configuration
 * @param key Output key buffer
 * @param key_len Output key length
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_kdf_derive_password(
    synor_crypto_t* crypto,
    const uint8_t* password,
    size_t password_len,
    const synor_password_derivation_config_t* config,
    uint8_t* key,
    size_t* key_len
);

/* ============================================================================
 * Hash Operations
 * ============================================================================ */

/**
 * Compute SHA3-256 hash.
 *
 * @param crypto Client handle
 * @param data Input data
 * @param data_len Data length
 * @param out Output hash
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_hash_sha3_256(
    synor_crypto_t* crypto,
    const uint8_t* data,
    size_t data_len,
    synor_hash256_t* out
);

/**
 * Compute BLAKE3 hash.
 *
 * @param crypto Client handle
 * @param data Input data
 * @param data_len Data length
 * @param out Output hash
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_hash_blake3(
    synor_crypto_t* crypto,
    const uint8_t* data,
    size_t data_len,
    synor_hash256_t* out
);

/**
 * Compute Keccak-256 hash.
 *
 * @param crypto Client handle
 * @param data Input data
 * @param data_len Data length
 * @param out Output hash
 * @return SYNOR_OK on success, error code otherwise
 */
synor_error_t synor_crypto_hash_keccak256(
    synor_crypto_t* crypto,
    const uint8_t* data,
    size_t data_len,
    synor_hash256_t* out
);

/* ============================================================================
 * Utility Functions
 * ============================================================================ */

/**
 * Get the signature size for a Falcon variant.
 *
 * @param variant Falcon variant
 * @return Signature size in bytes
 */
size_t synor_crypto_falcon_signature_size(synor_falcon_variant_t variant);

/**
 * Get the public key size for a Falcon variant.
 *
 * @param variant Falcon variant
 * @return Public key size in bytes
 */
size_t synor_crypto_falcon_public_key_size(synor_falcon_variant_t variant);

/**
 * Get the signature size for a SPHINCS+ variant.
 *
 * @param variant SPHINCS+ variant
 * @return Signature size in bytes
 */
size_t synor_crypto_sphincs_signature_size(synor_sphincs_variant_t variant);

/**
 * Get the network name string.
 *
 * @param network Network type
 * @return Network name ("mainnet", "testnet", or "devnet")
 */
const char* synor_crypto_network_name(synor_network_t network);

/**
 * Get human-readable error message.
 *
 * @param error Error code
 * @return Error message string
 */
const char* synor_crypto_error_message(synor_error_t error);

/**
 * Format a derivation path as a string.
 *
 * @param path Derivation path
 * @param buffer Output buffer
 * @param buffer_size Buffer size
 * @return Number of characters written (excluding null terminator)
 */
int synor_crypto_derivation_path_format(
    const synor_derivation_path_t* path,
    char* buffer,
    size_t buffer_size
);

#ifdef __cplusplus
}
#endif

#endif /* SYNOR_CRYPTO_H */
