/**
 * Synor ZK SDK for C
 *
 * Zero-Knowledge proof systems for ZK-Rollups and privacy.
 */

#ifndef SYNOR_ZK_H
#define SYNOR_ZK_H

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

#ifdef __cplusplus
extern "C" {
#endif

/* ============================================================================
 * Opaque Types
 * ============================================================================ */

typedef struct synor_zk_client synor_zk_client_t;
typedef struct synor_zk_proof synor_zk_proof_t;
typedef struct synor_zk_verification_key synor_zk_verification_key_t;
typedef struct synor_zk_proving_key synor_zk_proving_key_t;
typedef struct synor_zk_batch synor_zk_batch_t;

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

/** Proof system backends */
typedef enum {
    SYNOR_ZK_PROOF_SYSTEM_GROTH16 = 0,  /**< Smallest proofs (~192 bytes), fastest verification */
    SYNOR_ZK_PROOF_SYSTEM_PLONK = 1,    /**< Universal trusted setup, medium proofs (~512 bytes) */
    SYNOR_ZK_PROOF_SYSTEM_STARK = 2     /**< No trusted setup, largest proofs (~50KB) */
} synor_zk_proof_system_t;

/** Circuit types for different operations */
typedef enum {
    SYNOR_ZK_CIRCUIT_TRANSFER = 0,  /**< Single transfer between accounts */
    SYNOR_ZK_CIRCUIT_BATCH = 1,     /**< Batch of multiple transfers */
    SYNOR_ZK_CIRCUIT_DEPOSIT = 2,   /**< Deposit from L1 to L2 */
    SYNOR_ZK_CIRCUIT_WITHDRAW = 3   /**< Withdrawal from L2 to L1 */
} synor_zk_circuit_type_t;

/** Rollup state */
typedef enum {
    SYNOR_ZK_ROLLUP_STATE_ACTIVE = 0,
    SYNOR_ZK_ROLLUP_STATE_PAUSED = 1,
    SYNOR_ZK_ROLLUP_STATE_FINALIZING = 2,
    SYNOR_ZK_ROLLUP_STATE_FINALIZED = 3
} synor_zk_rollup_state_t;

/** Proof status */
typedef enum {
    SYNOR_ZK_PROOF_STATUS_GENERATING = 0,
    SYNOR_ZK_PROOF_STATUS_COMPLETED = 1,
    SYNOR_ZK_PROOF_STATUS_FAILED = 2,
    SYNOR_ZK_PROOF_STATUS_VERIFIED = 3
} synor_zk_proof_status_t;

/** Error codes */
typedef enum {
    SYNOR_ZK_OK = 0,
    SYNOR_ZK_ERROR_INVALID_ARGUMENT = 1,
    SYNOR_ZK_ERROR_NETWORK = 2,
    SYNOR_ZK_ERROR_AUTH = 3,
    SYNOR_ZK_ERROR_NOT_FOUND = 4,
    SYNOR_ZK_ERROR_TIMEOUT = 5,
    SYNOR_ZK_ERROR_INTERNAL = 6,
    SYNOR_ZK_ERROR_CLIENT_CLOSED = 7,
    SYNOR_ZK_ERROR_PROOF_INVALID = 8,
    SYNOR_ZK_ERROR_CIRCUIT_ERROR = 9
} synor_zk_error_t;

/* ============================================================================
 * Structures
 * ============================================================================ */

/** SDK configuration */
typedef struct {
    const char* api_key;
    const char* endpoint;           /**< Default: "https://zk.synor.io/v1" */
    const char* ws_endpoint;        /**< Default: "wss://zk.synor.io/v1/ws" */
    uint32_t timeout_ms;            /**< Default: 60000 */
    uint32_t retries;               /**< Default: 3 */
    synor_zk_proof_system_t default_proof_system;  /**< Default: GROTH16 */
    bool debug;                     /**< Default: false */
} synor_zk_config_t;

/** Zero-knowledge proof */
typedef struct {
    char id[64];
    synor_zk_proof_system_t system;
    synor_zk_circuit_type_t circuit_type;
    uint8_t* data;
    size_t data_len;
    char** public_inputs;
    size_t public_inputs_count;
    size_t size;
    uint64_t generation_time_ms;
    uint64_t created_at;
} synor_zk_proof_info_t;

/** Verification result */
typedef struct {
    bool valid;
    uint64_t verification_time_ms;
    char* error;
} synor_zk_verification_result_t;

/** Account state */
typedef struct {
    char address[64];
    char balance[32];
    uint64_t nonce;
    char pubkey_hash[66];
} synor_zk_account_state_t;

/** Transfer operation */
typedef struct {
    char from[64];
    char to[64];
    char amount[32];
    char fee[32];
    uint64_t nonce;
    char* signature;  /**< Optional */
} synor_zk_transfer_t;

/** Deposit operation */
typedef struct {
    char l1_tx_hash[66];
    char recipient[64];
    char amount[32];
    char* token;  /**< Optional */
} synor_zk_deposit_t;

/** Withdrawal operation */
typedef struct {
    char sender[64];
    char recipient[64];
    char amount[32];
    char* token;  /**< Optional */
    uint64_t nonce;
    char* signature;  /**< Optional */
} synor_zk_withdrawal_t;

/** Rollup statistics */
typedef struct {
    uint64_t current_batch;
    uint64_t total_transactions;
    uint64_t total_proofs;
    uint64_t avg_proof_time_ms;
    char state_root[66];
    uint64_t account_count;
    char tvl[32];
} synor_zk_rollup_stats_t;

/** Proof request */
typedef struct {
    synor_zk_circuit_type_t circuit_type;
    char** public_inputs;
    size_t public_inputs_count;
    char** private_inputs;
    size_t private_inputs_count;
    synor_zk_proof_system_t* system;  /**< Optional, uses default if NULL */
} synor_zk_proof_request_t;

/** Merkle proof */
typedef struct {
    char leaf[66];
    char** path;
    size_t path_len;
    uint8_t* indices;
    size_t indices_len;
    char root[66];
} synor_zk_merkle_proof_t;

/** Ceremony contribution */
typedef struct {
    char contributor_id[64];
    char hash[66];
    uint64_t timestamp;
    bool verified;
} synor_zk_ceremony_contribution_t;

/** Trusted setup ceremony */
typedef struct {
    char id[64];
    synor_zk_circuit_type_t circuit_type;
    synor_zk_proof_system_t system;
    size_t contribution_count;
    char latest_hash[66];
    bool complete;
    synor_zk_ceremony_contribution_t* contributions;
    size_t contributions_count;
} synor_zk_trusted_setup_t;

/** Proof system characteristics */
typedef struct {
    const char* name;
    size_t proof_size;
    uint32_t verification_time_ms;
    bool trusted_setup;
    bool universal;
} synor_zk_proof_system_info_t;

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

/**
 * Create a new ZK SDK client
 *
 * @param config Configuration options
 * @return New client handle, or NULL on error
 */
synor_zk_client_t* synor_zk_client_new(const synor_zk_config_t* config);

/**
 * Close and free a client
 *
 * @param client Client to close
 */
void synor_zk_client_free(synor_zk_client_t* client);

/**
 * Check if client is closed
 *
 * @param client Client handle
 * @return true if closed
 */
bool synor_zk_client_is_closed(const synor_zk_client_t* client);

/**
 * Health check
 *
 * @param client Client handle
 * @param healthy Output parameter for health status
 * @return Error code
 */
synor_zk_error_t synor_zk_health_check(synor_zk_client_t* client, bool* healthy);

/* ============================================================================
 * Proof Operations
 * ============================================================================ */

/**
 * Generate a zero-knowledge proof
 *
 * @param client Client handle
 * @param request Proof request parameters
 * @param proof Output parameter for generated proof
 * @return Error code
 */
synor_zk_error_t synor_zk_proof_generate(
    synor_zk_client_t* client,
    const synor_zk_proof_request_t* request,
    synor_zk_proof_t** proof
);

/**
 * Verify a proof
 *
 * @param client Client handle
 * @param proof Proof to verify
 * @param result Output parameter for verification result
 * @return Error code
 */
synor_zk_error_t synor_zk_proof_verify(
    synor_zk_client_t* client,
    const synor_zk_proof_t* proof,
    synor_zk_verification_result_t* result
);

/**
 * Get a proof by ID
 *
 * @param client Client handle
 * @param proof_id Proof identifier
 * @param proof Output parameter for proof
 * @return Error code
 */
synor_zk_error_t synor_zk_proof_get(
    synor_zk_client_t* client,
    const char* proof_id,
    synor_zk_proof_t** proof
);

/**
 * Free a proof
 */
void synor_zk_proof_free(synor_zk_proof_t* proof);

/**
 * Get proof info
 */
synor_zk_error_t synor_zk_proof_get_info(
    const synor_zk_proof_t* proof,
    synor_zk_proof_info_t* info
);

/* ============================================================================
 * Circuit Operations
 * ============================================================================ */

/**
 * Get verification key for a circuit
 */
synor_zk_error_t synor_zk_circuit_get_vk(
    synor_zk_client_t* client,
    synor_zk_circuit_type_t circuit_type,
    synor_zk_proof_system_t system,
    synor_zk_verification_key_t** vk
);

/**
 * Get proving key for a circuit
 */
synor_zk_error_t synor_zk_circuit_get_pk(
    synor_zk_client_t* client,
    synor_zk_circuit_type_t circuit_type,
    synor_zk_proof_system_t system,
    synor_zk_proving_key_t** pk
);

/**
 * Free verification key
 */
void synor_zk_verification_key_free(synor_zk_verification_key_t* vk);

/**
 * Free proving key
 */
void synor_zk_proving_key_free(synor_zk_proving_key_t* pk);

/* ============================================================================
 * Rollup Operations
 * ============================================================================ */

/**
 * Get rollup statistics
 */
synor_zk_error_t synor_zk_rollup_get_stats(
    synor_zk_client_t* client,
    synor_zk_rollup_stats_t* stats
);

/**
 * Get current batch
 */
synor_zk_error_t synor_zk_rollup_get_current_batch(
    synor_zk_client_t* client,
    synor_zk_batch_t** batch
);

/**
 * Get batch by number
 */
synor_zk_error_t synor_zk_rollup_get_batch(
    synor_zk_client_t* client,
    uint64_t batch_number,
    synor_zk_batch_t** batch
);

/**
 * Submit a transfer
 */
synor_zk_error_t synor_zk_rollup_submit_transfer(
    synor_zk_client_t* client,
    const synor_zk_transfer_t* transfer,
    char* tx_id,
    size_t tx_id_len
);

/**
 * Submit a deposit
 */
synor_zk_error_t synor_zk_rollup_submit_deposit(
    synor_zk_client_t* client,
    const synor_zk_deposit_t* deposit,
    char* tx_id,
    size_t tx_id_len
);

/**
 * Submit a withdrawal
 */
synor_zk_error_t synor_zk_rollup_submit_withdrawal(
    synor_zk_client_t* client,
    const synor_zk_withdrawal_t* withdrawal,
    char* tx_id,
    size_t tx_id_len
);

/**
 * Finalize current batch
 */
synor_zk_error_t synor_zk_rollup_finalize_batch(
    synor_zk_client_t* client,
    synor_zk_batch_t** batch
);

/**
 * Free batch
 */
void synor_zk_batch_free(synor_zk_batch_t* batch);

/* ============================================================================
 * State Operations
 * ============================================================================ */

/**
 * Get current state root
 */
synor_zk_error_t synor_zk_state_get_root(
    synor_zk_client_t* client,
    char* root,
    size_t root_len
);

/**
 * Get account state
 */
synor_zk_error_t synor_zk_state_get_account(
    synor_zk_client_t* client,
    const char* address,
    synor_zk_account_state_t* account
);

/**
 * Get merkle proof for account inclusion
 */
synor_zk_error_t synor_zk_state_get_merkle_proof(
    synor_zk_client_t* client,
    const char* address,
    synor_zk_merkle_proof_t* proof
);

/**
 * Verify merkle proof
 */
synor_zk_error_t synor_zk_state_verify_merkle_proof(
    synor_zk_client_t* client,
    const synor_zk_merkle_proof_t* proof,
    bool* valid
);

/**
 * Free merkle proof
 */
void synor_zk_merkle_proof_free(synor_zk_merkle_proof_t* proof);

/* ============================================================================
 * Ceremony Operations
 * ============================================================================ */

/**
 * Get ceremony status
 */
synor_zk_error_t synor_zk_ceremony_get_status(
    synor_zk_client_t* client,
    synor_zk_circuit_type_t circuit_type,
    synor_zk_proof_system_t system,
    synor_zk_trusted_setup_t* setup
);

/**
 * Contribute to ceremony
 */
synor_zk_error_t synor_zk_ceremony_contribute(
    synor_zk_client_t* client,
    synor_zk_circuit_type_t circuit_type,
    const uint8_t* entropy,
    size_t entropy_len,
    synor_zk_proof_system_t system,
    synor_zk_ceremony_contribution_t* contribution
);

/**
 * Verify a contribution
 */
synor_zk_error_t synor_zk_ceremony_verify_contribution(
    synor_zk_client_t* client,
    synor_zk_circuit_type_t circuit_type,
    const char* contribution_hash,
    bool* valid
);

/**
 * Free trusted setup
 */
void synor_zk_trusted_setup_free(synor_zk_trusted_setup_t* setup);

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

/**
 * Get proof system info
 */
synor_zk_proof_system_info_t synor_zk_get_proof_system_info(synor_zk_proof_system_t system);

/**
 * Get error message
 */
const char* synor_zk_error_message(synor_zk_error_t error);

/**
 * Free verification result
 */
void synor_zk_verification_result_free(synor_zk_verification_result_t* result);

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

#define SYNOR_ZK_MAX_BATCH_SIZE 1000
#define SYNOR_ZK_STATE_TREE_DEPTH 32
#define SYNOR_ZK_PROOF_EXPIRY_BLOCKS 100

#ifdef __cplusplus
}
#endif

#endif /* SYNOR_ZK_H */
