#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <new>
#include <ostream>

struct InfBuf {
  uint8_t *ptr;
  uint32_t len;
};

struct InfSlice {
  const uint8_t *ptr;
  uint32_t len;
};

// Opaque struct for VaultContext
typedef struct VaultContext VaultContext;

extern "C" {

const char *infusion_err();

void infusion_free(InfBuf buf);

/**
 * Creates a new VaultContext instance.
 * Returns a pointer to the context (handle), or NULL on failure.
 * The caller is responsible for freeing this context using infusion_free_vault.
 */
VaultContext *infusion_new(InfSlice config_json);

/**
 * Frees a VaultContext instance created by infusion_new.
 */
void infusion_free_vault(VaultContext *ctx);

int32_t infusion_seal(const VaultContext *ctx, InfSlice policy_id,
                      InfSlice meta, InfSlice plaintext, InfBuf *out_frame,
                      uint8_t (*out_cid)[32]);

int32_t infusion_open(const VaultContext *ctx, InfSlice frame,
                      InfSlice cap_token, InfBuf *out_plaintext);

int32_t infusion_verify(InfSlice frame, uint8_t (*out_cid)[32], int32_t *out_ok,
                        int32_t *out_reason);

int32_t infusion_transfer(const uint8_t (*_item_cid)[32],
                          const uint8_t (*_new_owner_pub)[32],
                          InfBuf *out_frame);

int32_t infusion_cap_issue(const VaultContext *ctx,
                           const uint8_t (*scope_cid)[32], uint32_t rights,
                           uint64_t exp_ts, const uint8_t (*delegated_pub)[32],
                           InfBuf *out_cap);

int32_t infusion_cap_verify(InfSlice cap_token,
                            const uint8_t (*requester_pub)[32],
                            int32_t *out_ok);

int32_t infusion_open_with_requester(const VaultContext *ctx, InfSlice frame,
                                     InfSlice cap_token,
                                     const uint8_t *requester_pub,
                                     InfBuf *out_plaintext);

int32_t infusion_derive_key(const VaultContext *ctx, InfSlice context_info,
                            uint8_t (*out_key)[32]);

/**
 * Generates a mnemonic phrase (BIP-39).
 * \param word_count 12 or 24.
 * \param out_phrase Pointer to receive a C-string.
 * Note: The returned string is allocated by Rust and generally leaks in v1.2
 * unless we add a specific free function.
 */
int32_t infusion_mnemonic_generate(uint32_t word_count, char **out_phrase);

/**
 * Restores keys from mnemonic and returns initialization JSON.
 * Returns a C-string (JSON) that must be passed to `infusion_new`.
 * Note: The returned string is allocated by Rust and leaks in v1.2.
 */
const char *infusion_mnemonic_restore(InfSlice phrase);

/**
 * Computes a blind index (HMAC-SHA256) for a term using a key derived from the
 * vault context.
 * \param ctx Active vault context.
 * \param term The term to index.
 * \param out_hash Pointer to 32-byte buffer to receive the hash.
 */
int32_t infusion_blind_index(const VaultContext *ctx, InfSlice term,
                             uint8_t (*out_hash)[32]);

} // extern "C"
