#ifndef OPEN_WING_CONFIG_H
#define OPEN_WING_CONFIG_H

#include <stddef.h>

#define OW_MAX_NAME_LEN 128
#define OW_MAX_ABOUT_LEN 512
#define OW_MAX_URL_LEN 256
#define OW_MAX_KEY_LEN 256
#define OW_MAX_MODEL_LEN 128
#define OW_MAX_SIGNER_MODE_LEN 32
#define OW_MAX_SIGNER_SOCKET_LEN 128
#define OW_MAX_SIGNER_ROLE_LEN 32
#define OW_MAX_SIGNER_HOST_LEN 128
#define OW_MAX_SIGNER_AUTH_HEX_LEN 65

#define OW_MAX_STRANGER_RESPONSE_LEN 512

typedef struct {
    char nsec[OW_MAX_KEY_LEN];
    unsigned char private_key[32];
    unsigned char public_key[32];
    char public_key_hex[65];
} agent_keys_t;

typedef enum {
    DM_PROTOCOL_NIP04 = 0,
    DM_PROTOCOL_NIP17 = 1,
    DM_PROTOCOL_BOTH = 2
} dm_protocol_t;

typedef struct {
    char pubkey[65];
} admin_config_t;

typedef struct {
    char provider[32];
    char api_key[OW_MAX_KEY_LEN];
    char model[OW_MAX_MODEL_LEN];
    char base_url[OW_MAX_URL_LEN];
    int max_tokens;
    double temperature;
} llm_config_t;

typedef struct {
    int enabled;
    int timeout_seconds;
    int max_output_bytes;
    char working_directory[OW_MAX_URL_LEN];
} shell_tools_config_t;

typedef struct {
    int enabled;
    int max_turns;
    int trigger_max_turns;
    int api_default_max_turns;
    int api_max_turns_ceiling;
    int stall_repeat_threshold;
    int max_context_bytes;
    int local_http_fetch_default_timeout_seconds;
    int local_http_fetch_max_timeout_seconds;
    shell_tools_config_t shell;
    int blossom_max_upload_bytes;
    int blossom_max_download_bytes;
} tools_config_t;

typedef struct {
    int kind;
    char* content;
    char* tags_json;  // JSON array string for tags, optional
} startup_event_t;

typedef struct {
    int kind;
    char* d_tag;
    char* content;
} encrypted_event_t;

typedef struct {
    int enabled;
    int tools_enabled;
} security_tier_config_t;

typedef struct {
    int verify_signatures;
    char stranger_response[OW_MAX_STRANGER_RESPONSE_LEN];
    security_tier_config_t admin;
    security_tier_config_t wot;
    security_tier_config_t stranger;
} security_config_t;

typedef struct {
    int enabled;
    int track_kind_0;
    int track_kind_3;
    int track_kind_10002;
    int track_kind_1;
    int kind_1_limit;
} admin_context_config_t;

typedef struct {
    int enabled;
    int max_active;
    int cooldown_seconds;
    int llm_rate_limit_per_minute;
    int template_rate_limit_per_minute;
} triggers_config_t;

typedef struct {
    int enabled;
    int port;
    char bind_address[OW_MAX_URL_LEN];
} api_config_t;

typedef struct {
    int enabled;
    char** mint_urls;
    int mint_count;
    char unit[16];
    int auto_load;
    int mint_timeout_seconds;
} cashu_wallet_config_t;

/* Signer provider configuration.
 *
 * mode selects how signing/encryption operations are routed:
 *   "local"           - raw 32-byte key held in cfg.keys.private_key (default,
 *                       backward compatible, output-equivalent to legacy path).
 *   "nsigner_unix"    - delegate to a running n_signer over an AF_UNIX abstract
 *                       socket. The agent process holds no nsec.
 *   "nsigner_tcp"     - delegate to a running n_signer over TCP (host:port).
 *                       Requires auth_privkey_hex for the kind-27235 auth envelope.
 *   "nsigner_serial"  - delegate to a running n_signer over a USB CDC-ACM serial
 *                       device (e.g. /dev/ttyACM0). The agent process holds no nsec.
 *   "nsigner_fds"     - delegate to a running n_signer over a pre-connected fd
 *                       pair (read_fd, write_fd). CLI/runtime-only: the fds cannot
 *                       be persisted to genesis and must be supplied via --signer-fds
 *                       at boot. Intended for qrexec-style fd-passing deployments.
 *   "nsigner_qrexec"  - delegate to a running n_signer in another Qubes OS qube
 *                       via qrexec (spawns `qrexec-client-vm <target_qube>
 *                       <service_name>`). No network; hypervisor-vouched caller
 *                       identity. The agent process holds no nsec.
 *
 * Missing signer block behaves as mode="local" using keys.nsec.
 * In any nsigner_* mode, keys.nsec is optional and ignored; the agent pubkey
 * is learned from the signer via nostr_signer_get_public_key().
 */
typedef struct {
    char mode[OW_MAX_SIGNER_MODE_LEN];          /* "local" | "nsigner_unix" | "nsigner_tcp" | "nsigner_serial" | "nsigner_fds" | "nsigner_qrexec" */
    char socket_name[OW_MAX_SIGNER_SOCKET_LEN]; /* nsigner_unix: abstract socket name (without @); "" = auto-discover */
    char role[OW_MAX_SIGNER_ROLE_LEN];          /* n_signer role selector (default "main"). Required for all nsigner_* modes. */
    char role_path[OW_MAX_URL_LEN];            /* full BIP-44 derivation path (e.g. "m/44'/1237'/0'/0/0"). Required for
                                                 * all nsigner_* modes — n_signer rejects role-only with 2009 path_required
                                                 * and bare nostr_index with 2006 nostr_index_deprecated. */
    int derive_index;                          /* algorithm index for the derive verb (HMAC). -1 = unset (default).
                                                 * CLI/runtime-only — NOT persisted to genesis. Set via --signer-derive-index. */
    int timeout_ms;                             /* per-call timeout (default 15000) */
    char auth_privkey_hex[OW_MAX_SIGNER_AUTH_HEX_LEN]; /* optional, TCP auth envelope only */
    /* nsigner_tcp parsed host/port (populated from --signer-tcp or config) */
    char tcp_host[OW_MAX_SIGNER_HOST_LEN];
    int tcp_port;
    /* nsigner_serial: device path (e.g. "/dev/ttyACM0"). Populated from
     * --signer-serial or the signer.serial_device config field. */
    char serial_device[OW_MAX_URL_LEN];
    /* nsigner_fds: pre-connected file descriptors. CLI/runtime-only — NOT
     * persisted to genesis. Populated from --signer-fds <read:write>. */
    int fds_read_fd;
    int fds_write_fd;
    /* nsigner_qrexec: target Qubes qube name + qrexec service name.
     * Populated from --signer-qrexec <target_qube> or the signer.target_qube /
     * signer.service_name config fields. service_name defaults to
     * "qubes.NsignerRpc" when empty. */
    char target_qube[OW_MAX_SIGNER_HOST_LEN];
    char service_name[OW_MAX_SIGNER_SOCKET_LEN];
    /* Optional emergency local nsec for admin-alert fallback (Phase 4 item 20).
     *
     * OFF by default (empty string). When populated AND a remote signer is
     * unreachable, a future phase may use this in-process key ONLY to sign a
     * minimal admin alert DM reporting the signer outage. This reintroduces
     * the nsec into the agent process for that one purpose, which is a
     * deliberate operator-accepted tradeoff: better to leak the nsec briefly
     * to notify the admin than to fail silently.
     *
     * CURRENT STATUS: parsed and stored only. No active fallback behavior is
     * implemented yet (feature flag / documentation placeholder). The field
     * exists so operators can pre-stage the value; the fallback path is
     * deferred until the supervisor/health surface (item 19) is proven. */
    char emergency_local_nsec[OW_MAX_KEY_LEN];  /* "" = disabled (default) */
} signer_config_t;

typedef struct {
    agent_keys_t keys;
    admin_config_t admin;
    dm_protocol_t dm_protocol;
    char** relays;
    int relay_count;
    llm_config_t llm;
    tools_config_t tools;
    security_config_t security;
    admin_context_config_t admin_context;
    triggers_config_t triggers;
    api_config_t api;
    cashu_wallet_config_t cashu_wallet;
    signer_config_t signer;
    startup_event_t* startup_events;
    int startup_event_count;
    encrypted_event_t* encrypted_events;
    int encrypted_event_count;
    char config_path[OW_MAX_URL_LEN];
} didactyl_config_t;

int config_load(const char* path, didactyl_config_t* config);
int config_ensure_startup_skill_adoption(didactyl_config_t* config);
const char* config_last_error(void);
void config_free(didactyl_config_t* config);

/* Strip JSONC single-line and block comments, returning malloc'd pure JSON. */
char* jsonc_strip_comments(const char* src, size_t src_len);

#endif