/**
 * @file ibc.h
 * @brief Synor IBC SDK for C
 *
 * Inter-Blockchain Communication (IBC) protocol for cross-chain interoperability.
 */

#ifndef SYNOR_IBC_H
#define SYNOR_IBC_H

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

#ifdef __cplusplus
extern "C" {
#endif

/* Error codes */
typedef enum {
    SYNOR_IBC_OK = 0,
    SYNOR_IBC_ERROR_CLIENT_CLOSED = -1,
    SYNOR_IBC_ERROR_HTTP = -2,
    SYNOR_IBC_ERROR_NETWORK = -3,
    SYNOR_IBC_ERROR_INVALID_PARAM = -4,
    SYNOR_IBC_ERROR_TIMEOUT = -5,
    SYNOR_IBC_ERROR_JSON = -6,
    SYNOR_IBC_ERROR_ALLOCATION = -7
} synor_ibc_error_t;

/* Enums */
typedef enum {
    SYNOR_IBC_CLIENT_TYPE_TENDERMINT,
    SYNOR_IBC_CLIENT_TYPE_SOLO_MACHINE,
    SYNOR_IBC_CLIENT_TYPE_LOCALHOST,
    SYNOR_IBC_CLIENT_TYPE_WASM
} synor_ibc_client_type_t;

typedef enum {
    SYNOR_IBC_CONNECTION_STATE_UNINITIALIZED,
    SYNOR_IBC_CONNECTION_STATE_INIT,
    SYNOR_IBC_CONNECTION_STATE_TRYOPEN,
    SYNOR_IBC_CONNECTION_STATE_OPEN
} synor_ibc_connection_state_t;

typedef enum {
    SYNOR_IBC_CHANNEL_ORDER_UNORDERED,
    SYNOR_IBC_CHANNEL_ORDER_ORDERED
} synor_ibc_channel_order_t;

typedef enum {
    SYNOR_IBC_CHANNEL_STATE_UNINITIALIZED,
    SYNOR_IBC_CHANNEL_STATE_INIT,
    SYNOR_IBC_CHANNEL_STATE_TRYOPEN,
    SYNOR_IBC_CHANNEL_STATE_OPEN,
    SYNOR_IBC_CHANNEL_STATE_CLOSED
} synor_ibc_channel_state_t;

typedef enum {
    SYNOR_IBC_SWAP_STATE_PENDING,
    SYNOR_IBC_SWAP_STATE_LOCKED,
    SYNOR_IBC_SWAP_STATE_COMPLETED,
    SYNOR_IBC_SWAP_STATE_REFUNDED,
    SYNOR_IBC_SWAP_STATE_EXPIRED,
    SYNOR_IBC_SWAP_STATE_CANCELLED
} synor_ibc_swap_state_t;

/* Opaque handle types */
typedef struct synor_ibc_client synor_ibc_client_t;
typedef struct synor_ibc_light_client synor_ibc_light_client_t;
typedef struct synor_ibc_connections synor_ibc_connections_t;
typedef struct synor_ibc_channels synor_ibc_channels_t;
typedef struct synor_ibc_transfer synor_ibc_transfer_t;
typedef struct synor_ibc_swaps synor_ibc_swaps_t;

/* Configuration */
typedef struct {
    const char* api_key;
    const char* endpoint;        /* Default: "https://ibc.synor.io/v1" */
    const char* ws_endpoint;     /* Default: "wss://ibc.synor.io/v1/ws" */
    uint32_t timeout_ms;         /* Default: 30000 */
    uint32_t retries;            /* Default: 3 */
    const char* chain_id;        /* Default: "synor-1" */
    bool debug;                  /* Default: false */
} synor_ibc_config_t;

/* Data types */
typedef struct {
    uint64_t revision_number;
    uint64_t revision_height;
} synor_ibc_height_t;

typedef struct {
    char* id;
} synor_ibc_chain_id_t;

typedef struct {
    char* identifier;
    char** features;
    size_t features_count;
} synor_ibc_version_t;

typedef struct {
    char* id;
} synor_ibc_client_id_t;

typedef struct {
    int numerator;
    int denominator;
} synor_ibc_trust_level_t;

typedef struct {
    char* chain_id;
    synor_ibc_trust_level_t trust_level;
    uint64_t trusting_period;
    uint64_t unbonding_period;
    uint64_t max_clock_drift;
    synor_ibc_height_t latest_height;
    synor_ibc_height_t* frozen_height;  /* NULL if not frozen */
} synor_ibc_client_state_t;

typedef struct {
    char* id;
} synor_ibc_connection_id_t;

typedef struct {
    char* id;
} synor_ibc_port_id_t;

typedef struct {
    char* id;
} synor_ibc_channel_id_t;

typedef struct {
    synor_ibc_height_t height;
    uint64_t timestamp;
} synor_ibc_timeout_t;

typedef struct {
    char* denom;
    char* amount;
    char* sender;
    char* receiver;
    char* memo;
} synor_ibc_fungible_token_packet_data_t;

typedef struct {
    char* id;
} synor_ibc_swap_id_t;

typedef struct {
    uint8_t* hash;
    size_t hash_len;
} synor_ibc_hashlock_t;

typedef struct {
    uint64_t expiry;
} synor_ibc_timelock_t;

typedef struct {
    synor_ibc_swap_id_t swap_id;
    synor_ibc_swap_state_t state;
    char* initiator_htlc_json;
    char* responder_htlc_json;  /* NULL if not set */
} synor_ibc_atomic_swap_t;

typedef struct {
    char* transaction_hash;
    char* sequence;
} synor_ibc_transfer_result_t;

/* Create light client params */
typedef struct {
    synor_ibc_client_type_t client_type;
    synor_ibc_client_state_t client_state;
    const char* consensus_state_json;
} synor_ibc_create_client_params_t;

/* Open connection params */
typedef struct {
    synor_ibc_client_id_t client_id;
    synor_ibc_client_id_t counterparty_client_id;
} synor_ibc_open_connection_params_t;

/* Open channel params */
typedef struct {
    synor_ibc_port_id_t port_id;
    synor_ibc_channel_order_t ordering;
    synor_ibc_connection_id_t connection_id;
    synor_ibc_port_id_t counterparty_port;
    const char* version;
} synor_ibc_open_channel_params_t;

/* Transfer params */
typedef struct {
    const char* source_port;
    const char* source_channel;
    const char* denom;
    const char* amount;
    const char* sender;
    const char* receiver;
    synor_ibc_timeout_t* timeout;  /* NULL for no timeout */
    const char* memo;              /* NULL if not set */
} synor_ibc_transfer_params_t;

/* Swap initiate params */
typedef struct {
    const char* responder;
    const char* initiator_asset_json;
    const char* responder_asset_json;
} synor_ibc_swap_initiate_params_t;

/* Client lifecycle */
synor_ibc_error_t synor_ibc_create(synor_ibc_client_t** client, const synor_ibc_config_t* config);
void synor_ibc_destroy(synor_ibc_client_t* client);
bool synor_ibc_is_closed(const synor_ibc_client_t* client);
void synor_ibc_close(synor_ibc_client_t* client);

/* Chain operations */
synor_ibc_error_t synor_ibc_get_chain_info(synor_ibc_client_t* client, char** result_json);
synor_ibc_error_t synor_ibc_get_height(synor_ibc_client_t* client, synor_ibc_height_t* height);
synor_ibc_error_t synor_ibc_health_check(synor_ibc_client_t* client, bool* healthy);

/* Sub-clients */
synor_ibc_light_client_t* synor_ibc_clients(synor_ibc_client_t* client);
synor_ibc_connections_t* synor_ibc_connections(synor_ibc_client_t* client);
synor_ibc_channels_t* synor_ibc_channels(synor_ibc_client_t* client);
synor_ibc_transfer_t* synor_ibc_transfer(synor_ibc_client_t* client);
synor_ibc_swaps_t* synor_ibc_swaps(synor_ibc_client_t* client);

/* Light client operations */
synor_ibc_error_t synor_ibc_light_client_create(synor_ibc_light_client_t* lc,
                                                 const synor_ibc_create_client_params_t* params,
                                                 synor_ibc_client_id_t** result);
synor_ibc_error_t synor_ibc_light_client_get_state(synor_ibc_light_client_t* lc,
                                                    const synor_ibc_client_id_t* client_id,
                                                    synor_ibc_client_state_t** state);
synor_ibc_error_t synor_ibc_light_client_list(synor_ibc_light_client_t* lc,
                                               char** result_json);

/* Connection operations */
synor_ibc_error_t synor_ibc_connections_open_init(synor_ibc_connections_t* conn,
                                                   const synor_ibc_open_connection_params_t* params,
                                                   synor_ibc_connection_id_t** result);
synor_ibc_error_t synor_ibc_connections_get(synor_ibc_connections_t* conn,
                                             const synor_ibc_connection_id_t* connection_id,
                                             char** result_json);
synor_ibc_error_t synor_ibc_connections_list(synor_ibc_connections_t* conn, char** result_json);

/* Channel operations */
synor_ibc_error_t synor_ibc_channels_bind_port(synor_ibc_channels_t* ch,
                                                const synor_ibc_port_id_t* port_id,
                                                const char* module);
synor_ibc_error_t synor_ibc_channels_open_init(synor_ibc_channels_t* ch,
                                                const synor_ibc_open_channel_params_t* params,
                                                synor_ibc_channel_id_t** result);
synor_ibc_error_t synor_ibc_channels_get(synor_ibc_channels_t* ch,
                                          const synor_ibc_port_id_t* port_id,
                                          const synor_ibc_channel_id_t* channel_id,
                                          char** result_json);
synor_ibc_error_t synor_ibc_channels_list(synor_ibc_channels_t* ch, char** result_json);

/* Transfer operations (ICS-20) */
synor_ibc_error_t synor_ibc_transfer_send(synor_ibc_transfer_t* tr,
                                           const synor_ibc_transfer_params_t* params,
                                           synor_ibc_transfer_result_t** result);
synor_ibc_error_t synor_ibc_transfer_get_denom_trace(synor_ibc_transfer_t* tr,
                                                      const char* ibc_denom,
                                                      char** result_json);

/* Swap operations (HTLC) */
synor_ibc_error_t synor_ibc_swaps_initiate(synor_ibc_swaps_t* sw,
                                            const synor_ibc_swap_initiate_params_t* params,
                                            char** result_json);
synor_ibc_error_t synor_ibc_swaps_lock(synor_ibc_swaps_t* sw,
                                        const synor_ibc_swap_id_t* swap_id);
synor_ibc_error_t synor_ibc_swaps_respond(synor_ibc_swaps_t* sw,
                                           const synor_ibc_swap_id_t* swap_id,
                                           const char* asset_json,
                                           char** result_json);
synor_ibc_error_t synor_ibc_swaps_claim(synor_ibc_swaps_t* sw,
                                         const synor_ibc_swap_id_t* swap_id,
                                         const uint8_t* secret, size_t secret_len,
                                         char** result_json);
synor_ibc_error_t synor_ibc_swaps_refund(synor_ibc_swaps_t* sw,
                                          const synor_ibc_swap_id_t* swap_id,
                                          char** result_json);
synor_ibc_error_t synor_ibc_swaps_get(synor_ibc_swaps_t* sw,
                                       const synor_ibc_swap_id_t* swap_id,
                                       synor_ibc_atomic_swap_t** swap);
synor_ibc_error_t synor_ibc_swaps_list_active(synor_ibc_swaps_t* sw,
                                               synor_ibc_atomic_swap_t** swaps,
                                               size_t* count);

/* Memory management */
void synor_ibc_free_string(char* str);
void synor_ibc_free_height(synor_ibc_height_t* height);
void synor_ibc_free_client_id(synor_ibc_client_id_t* client_id);
void synor_ibc_free_client_state(synor_ibc_client_state_t* state);
void synor_ibc_free_connection_id(synor_ibc_connection_id_t* connection_id);
void synor_ibc_free_port_id(synor_ibc_port_id_t* port_id);
void synor_ibc_free_channel_id(synor_ibc_channel_id_t* channel_id);
void synor_ibc_free_swap_id(synor_ibc_swap_id_t* swap_id);
void synor_ibc_free_atomic_swap(synor_ibc_atomic_swap_t* swap);
void synor_ibc_free_atomic_swaps(synor_ibc_atomic_swap_t* swaps, size_t count);
void synor_ibc_free_transfer_result(synor_ibc_transfer_result_t* result);
void synor_ibc_free_version(synor_ibc_version_t* version);

#ifdef __cplusplus
}
#endif

#endif /* SYNOR_IBC_H */
