// nucleic_protocol.h — flat C ABI of NucleicProtocolC.dll (docs/WINDOWS_PORT.md §6).
//
// Contract: every string crossing the boundary is UTF-8 JSON. Strings returned by the DLL are
// owned by the caller and must be released with np_free(). Callback strings are borrowed only
// for the duration of the call and must be copied. Callbacks from every handle fire on one
// dedicated DLL thread; the C# side marshals to its dispatcher.
//
// All entry points are implemented. Golden CBOR↔JSON fixtures live in fixtures/protocol-abi/.

#ifndef NUCLEIC_PROTOCOL_H
#define NUCLEIC_PROTOCOL_H

#ifdef __cplusplus
extern "C" {
#endif

typedef struct np_handle np_handle;
typedef struct np_proj np_proj;

// host_msg_json: one HostMsg, JSON-encoded (wire form is CBOR; the DLL bridges).
typedef void (*np_event_cb)(void* ctx, const char* host_msg_json);
// state_json: connect/disconnect/transport/pairing state changes and errors.
typedef void (*np_state_cb)(void* ctx, const char* state_json);

// Integer results: accepted work is 0; failures are stable negative values. Network and Noise
// outcomes are asynchronous and arrive through np_state_cb.
enum np_result {
    NP_OK = 0,
    NP_INVALID_ARGUMENT = -1,
    NP_INVALID_STATE = -2,
    NP_DECODE_ERROR = -3,
    NP_UNSUPPORTED = -4
};

// config_json:
//   {identityDir, hostKeyPins?: {hostID: base64StaticKey}, deviceID?, deviceLabel?,
//    scopeClaim?: "view"|"approve"|"control", channel?: "local"|"canary"|"beta"|"rc"|"release"}
// The DLL persists device-identity.raw, device-id.txt, and host-key-pins.json in identityDir.
np_handle*  np_client_create(const char* config_json);
// Replacing/unregistering callbacks drains this handle's prior callback context first.
void        np_client_set_callbacks(np_handle*, np_event_cb, np_state_cb, void* ctx);
// rendezvous_json: {host?: "127.0.0.1", port, localPSK} (psk is accepted as an alias).
int         np_client_connect_local(np_handle*, const char* rendezvous_json);
// endpoint_json:
//   LAN/tailnet: {transport,host,port,hostID? or hostStaticKey?,psk?}
//   relay:       {transport:"relay",relayURL?,membershipToken,hostID? or hostStaticKey?,psk?}
// relayURL defaults to the production relay.
// hostStaticKey/psk are base64. Omit psk for pinned-key reconnect.
int         np_client_connect_remote(np_handle*, const char* endpoint_json);
int         np_client_pair(np_handle*, const char* pairing_code);
int         np_client_send_intent(np_handle*, const char* client_msg_json);
// Destroys the handle and is a callback barrier: no callback using ctx runs after this returns.
void        np_client_close(np_handle*);

// Release any string returned by this library. NULL is accepted.
void        np_free(const char*);

np_proj*    np_projection_create(void);
// Returns {"version":1,"sessionID"?:...,"splices":[
//   {"start":uint,"deleteCount":uint,"items":[renderItem,...]}
// ]}. Irrelevant HostMsgs return an empty splices array. Caller frees with np_free.
const char* np_projection_apply(np_proj*, const char* host_msg_json);
void        np_projection_free(np_proj*);

#ifdef __cplusplus
}
#endif

#endif  // NUCLEIC_PROTOCOL_H
