/*
 * el_seed.h — El language seed runtime header
 *
 * Declares all OS-boundary primitives available to compiled El programs.
 * All functions use the __ prefix convention. Signatures use el_val_t (= int64_t)
 * as the universal value type.
 *
 * el_seed.c is the complete C boundary for the El runtime. The heavy runtime
 * (el_runtime.c) has been retired — everything lives in el_seed.c plus the
 * native El runtime (runtime/ *.el files).
 *
 * Link requirements:
 *   -lcurl    — HTTP client (__http_do, __http_do_to_file)
 *   -lpthread — threading (__thread_create, __thread_join, __mutex_new, ...)
 *
 * Canonical compile (via elb):
 *   elb builds and links el_seed.c automatically.
 */

#pragma once

#include <stdint.h>
#include <stdlib.h>

/* ── Value model ─────────────────────────────────────────────────────────────
 * All El values are el_val_t (int64_t). On 64-bit systems a pointer fits.
 *   String  -> el_val_t  (holds const char* via uintptr_t cast)
 *   Int     -> el_val_t  (stored directly)
 *   Bool    -> el_val_t  (0 = false, nonzero = true)
 *   Void    -> void
 */
typedef int64_t el_val_t;

#define EL_STR(s)  ((el_val_t)(uintptr_t)(s))
#define EL_CSTR(v) ((const char*)(uintptr_t)(v))
#define EL_INT(v)  (v)
#define EL_NULL    ((el_val_t)0)

/* Float values share the el_val_t slot via bit-cast. */
static inline double el_to_float(el_val_t v) {
    union { int64_t i; double f; } u; u.i = (int64_t)v; return u.f;
}
static inline el_val_t el_from_float(double f) {
    union { double f; int64_t i; } u; u.f = f; return (el_val_t)u.i;
}

#ifdef __cplusplus
extern "C" {
#endif

/* ── String primitives ───────────────────────────────────────────────────── */

el_val_t  __str_len(el_val_t s);
el_val_t  __str_char_at(el_val_t s, el_val_t i);       /* returns Int (byte value) */
el_val_t  __str_alloc(el_val_t n);                     /* malloc(n+1), zero-init, return String */
el_val_t  __str_set_char(el_val_t s, el_val_t i, el_val_t c);  /* s[i]=c, return s */
el_val_t  __str_cmp(el_val_t a, el_val_t b);           /* strcmp result as Int */
el_val_t  __str_ncmp(el_val_t a, el_val_t b, el_val_t n);      /* strncmp */
el_val_t  __str_concat_raw(el_val_t a, el_val_t b);    /* malloc+strcpy concat */
el_val_t  __str_slice_raw(el_val_t s, el_val_t start, el_val_t end);  /* substring copy */
el_val_t  __int_to_str(el_val_t n);
el_val_t  __str_to_int(el_val_t s);
el_val_t  __float_to_str(el_val_t f);                  /* f is bit-cast double */
el_val_t  __str_to_float(el_val_t s);                  /* strtod, bit-cast result */

/* ── I/O ─────────────────────────────────────────────────────────────────── */

void      __println(el_val_t s);
void      __print(el_val_t s);
el_val_t  __readline(void);

/* ── Filesystem ──────────────────────────────────────────────────────────── */

el_val_t  __fs_read(el_val_t path);
el_val_t  __fs_write(el_val_t path, el_val_t content);
el_val_t  __fs_exists(el_val_t path);
el_val_t  __fs_list_raw(el_val_t path);               /* newline-separated filenames */
el_val_t  __fs_mkdir(el_val_t path);
el_val_t  __fs_write_bytes(el_val_t path, el_val_t bytes, el_val_t n);

/* ── HTTP client ─────────────────────────────────────────────────────────── */

/* Unified HTTP call. headers_json is a JSON object of header name->value pairs
 * (e.g. {"Authorization":"Bearer ...","Content-Type":"application/json"}).
 * Use "" or "{}" for no extra headers. timeout_ms <= 0 uses the default. */
el_val_t  __http_do(el_val_t method, el_val_t url, el_val_t body,
                    el_val_t headers_json, el_val_t timeout_ms);

/* Stream response body directly to a file. Returns 1 on success, 0 on failure. */
el_val_t  __http_do_to_file(el_val_t method, el_val_t url, el_val_t body,
                             el_val_t headers_json, el_val_t out_path);

/* ── HTTP server ─────────────────────────────────────────────────────────── */

/* Blocking HTTP server. handler_name is the El function name to dispatch to.
 * v1 handler: (method, path, body) -> String
 * v2 handler: (method, path, headers_map, body) -> String or envelope */
void      __http_serve(el_val_t port, el_val_t handler_name);
void      __http_serve_v2(el_val_t port, el_val_t handler_name);

/* Build a structured HTTP response envelope.
 * headers_json: JSON object literal like {"Content-Type":"text/plain"} or "{}" */
el_val_t  __http_response(el_val_t status, el_val_t headers_json, el_val_t body);

/* ── HTTP SSE — Server-Sent Events streaming ─────────────────────────────── */

/* Returns the raw file descriptor for the current HTTP connection.
 * Valid only inside an http_serve_v2 handler before it returns.
 * Returns -1 if called outside a handler context. */
el_val_t  __http_conn_fd(void);

/* Sends SSE response headers on conn_id (the fd from __http_conn_fd),
 * keeping the connection open for streaming. Returns 1 on success, 0 on
 * write failure. Call once at the start of an SSE handler. */
el_val_t  __http_sse_open(el_val_t conn_id);

/* Writes one SSE event frame: "data: <data>\n\n". data must not contain
 * newlines. Returns 1 on success, 0 if the client disconnected. */
el_val_t  __http_sse_send(el_val_t conn_id, el_val_t data);

/* Closes the SSE connection. The handler must return http_sse_sentinel()
 * so the HTTP worker does not double-close the fd. */
el_val_t  __http_sse_close(el_val_t conn_id);

/* ── Threading ───────────────────────────────────────────────────────────── */

/* Create a thread that calls the named El function with a String argument.
 * fn_name is resolved via dlsym(RTLD_DEFAULT, fn_name). Returns a thread
 * handle Int that can be passed to __thread_join. Returns -1 on failure. */
el_val_t  __thread_create(el_val_t fn_name, el_val_t arg);

/* Wait for thread tid (returned by __thread_create) to finish.
 * Returns the thread's return value as a String. */
el_val_t  __thread_join(el_val_t tid);

/* Allocate a new mutex. Returns a handle Int (index into internal table). */
el_val_t  __mutex_new(void);

void      __mutex_lock(el_val_t m);
void      __mutex_unlock(el_val_t m);

/* ── Subprocess ──────────────────────────────────────────────────────────── */

el_val_t  __exec(el_val_t cmd);            /* popen, capture all stdout, return String */
void      __exec_bg(el_val_t cmd);         /* fire and forget */

/* ── Environment and process ─────────────────────────────────────────────── */

el_val_t  __env_get(el_val_t key);         /* getenv, return "" if not set */
void      __exit_program(el_val_t code);
el_val_t  __args_json(void);               /* CLI args as JSON array string */

/* ── Time ────────────────────────────────────────────────────────────────── */

el_val_t  __time_now_ns(void);             /* clock_gettime REALTIME, nanoseconds */
void      __sleep_ms(el_val_t ms);

/* ── UUID ────────────────────────────────────────────────────────────────── */

el_val_t  __uuid_v4(void);

/* ── Math ────────────────────────────────────────────────────────────────── */

el_val_t  __sqrt_f(el_val_t f);
el_val_t  __log_f(el_val_t f);
el_val_t  __ln_f(el_val_t f);
el_val_t  __sin_f(el_val_t f);
el_val_t  __cos_f(el_val_t f);
el_val_t  __pi_f(void);

/* ── JSON ────────────────────────────────────────────────────────────────── */

el_val_t  __json_get(el_val_t json, el_val_t key);
el_val_t  __json_get_raw(el_val_t json_str, el_val_t key);
el_val_t  __json_parse(el_val_t s);
el_val_t  __json_stringify(el_val_t v);
el_val_t  __json_parse_map(el_val_t json_str);     /* alias for __json_parse */
el_val_t  __json_stringify_val(el_val_t val);      /* alias for __json_stringify */
el_val_t  __json_array_len(el_val_t json_str);
el_val_t  __json_array_get(el_val_t json_str, el_val_t index);
el_val_t  __json_array_get_string(el_val_t json_str, el_val_t index);
el_val_t  __json_get_string(el_val_t json_str, el_val_t key);
el_val_t  __json_get_int(el_val_t json_str, el_val_t key);
el_val_t  __json_get_float(el_val_t json_str, el_val_t key);
el_val_t  __json_get_bool(el_val_t json_str, el_val_t key);
el_val_t  __json_set(el_val_t json_str, el_val_t key, el_val_t value);

/* ── State K/V ───────────────────────────────────────────────────────────── */

el_val_t  __state_set(el_val_t key, el_val_t value);
el_val_t  __state_get(el_val_t key);
el_val_t  __state_del(el_val_t key);
el_val_t  __state_keys(void);

/* ── HTML/URL ────────────────────────────────────────────────────────────── */

el_val_t  __html_sanitize(el_val_t input_html, el_val_t allowlist_json);
el_val_t  __url_encode(el_val_t s);
el_val_t  __url_decode(el_val_t s);

/* ── Engram ──────────────────────────────────────────────────────────────── */

el_val_t  __engram_node(el_val_t content, el_val_t node_type, el_val_t salience);
el_val_t  __engram_node_full(el_val_t content, el_val_t node_type, el_val_t label,
                              el_val_t salience, el_val_t importance, el_val_t confidence,
                              el_val_t tier, el_val_t tags);
el_val_t  __engram_node_layered(el_val_t content, el_val_t node_type, el_val_t label,
                                 el_val_t salience, el_val_t certainty, el_val_t confidence,
                                 el_val_t status, el_val_t tags, el_val_t layer_id);
el_val_t  __engram_add_layer(el_val_t name, el_val_t priority, el_val_t suppressible,
                              el_val_t transparent, el_val_t injectable);
el_val_t  __engram_remove_layer(el_val_t layer_id);
el_val_t  __engram_list_layers(void);
el_val_t  __engram_get_node(el_val_t id);
void      __engram_strengthen(el_val_t node_id);
void      __engram_forget(el_val_t node_id);
el_val_t  __engram_node_count(void);
el_val_t  __engram_search(el_val_t query, el_val_t limit);
el_val_t  __engram_scan_nodes(el_val_t limit, el_val_t offset);
void      __engram_connect(el_val_t from_id, el_val_t to_id, el_val_t weight, el_val_t relation);
el_val_t  __engram_edge_between(el_val_t from_id, el_val_t to_id);
el_val_t  __engram_neighbors(el_val_t node_id);
el_val_t  __engram_neighbors_filtered(el_val_t node_id, el_val_t max_depth, el_val_t direction);
el_val_t  __engram_edge_count(void);
el_val_t  __engram_activate(el_val_t query, el_val_t depth);
el_val_t  __engram_save(el_val_t path);
el_val_t  __engram_load(el_val_t path);
el_val_t  __engram_get_node_json(el_val_t id);
el_val_t  __engram_search_json(el_val_t query, el_val_t limit);
el_val_t  __engram_scan_nodes_json(el_val_t limit, el_val_t offset);
el_val_t  __engram_scan_nodes_by_type_json(el_val_t node_type, el_val_t limit, el_val_t offset);
el_val_t  __engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t direction);
el_val_t  __engram_activate_json(el_val_t query, el_val_t depth);
el_val_t  __engram_stats_json(void);
el_val_t  __engram_list_layers_json(void);
el_val_t  __engram_compile_layered_json(el_val_t intent, el_val_t depth);

/* ── Cryptographic hashing ────────────────────────────────────────────────── */

/* __sha256_hex — return the SHA-256 hex digest of a string.
 * The returned string is 64 hex characters (lowercase). */
el_val_t  __sha256_hex(el_val_t s);

/* ── args init (called from main) ────────────────────────────────────────── */
/* Store argc/argv for __args_json. Call once at the start of main(). */
void      el_seed_init_args(int argc, char** argv);

/* ── Native widget system (macOS AppKit) ─────────────────────────────────── */
/*
 * Available when compiled with -DEL_TARGET_MACOS and linked with el_appkit.m
 * (-framework Cocoa). Widget handles are opaque Int values (int64_t slot
 * indices). The null/invalid handle value is -1.
 *
 * Lifecycle:
 *   1. Call __native_init() once at program start.
 *   2. Build widget tree with __window_create / __vstack_create / etc.
 *   3. Attach children with __widget_add_child(parent, child).
 *   4. Register callbacks with __widget_on_click / __widget_on_change.
 *   5. Call __window_show(win) to make the window visible.
 *   6. Call __native_run_loop() — never returns. AppKit owns the thread.
 *
 * Callback El function signature:
 *   fn my_handler(widget: Int, data: String) -> Void
 */
#ifdef EL_TARGET_MACOS

/* Initialisation */
void      __native_init(void);
void      __native_run_loop(void);

/* Window */
el_val_t  __window_create(el_val_t title, el_val_t width, el_val_t height,
                           el_val_t min_width, el_val_t min_height);
void      __window_show(el_val_t handle);
void      __window_set_title(el_val_t handle, el_val_t title);

/* Layout containers */
el_val_t  __vstack_create(el_val_t spacing);
el_val_t  __hstack_create(el_val_t spacing);
el_val_t  __zstack_create(void);
el_val_t  __scroll_create(void);

/* Widgets */
el_val_t  __label_create(el_val_t text);
el_val_t  __button_create(el_val_t label);
el_val_t  __text_field_create(el_val_t placeholder);
el_val_t  __text_area_create(el_val_t placeholder);
el_val_t  __image_create(el_val_t path_or_name);

/* Widget properties */
void      __widget_set_text(el_val_t handle, el_val_t text);
el_val_t  __widget_get_text(el_val_t handle);
void      __widget_set_color(el_val_t handle, el_val_t r, el_val_t g, el_val_t b, el_val_t a);
void      __widget_set_bg_color(el_val_t handle, el_val_t r, el_val_t g, el_val_t b, el_val_t a);
void      __widget_set_font(el_val_t handle, el_val_t family, el_val_t size, el_val_t bold);
void      __widget_set_padding(el_val_t handle, el_val_t top, el_val_t right,
                                el_val_t bottom, el_val_t left);
void      __widget_set_width(el_val_t handle, el_val_t width);
void      __widget_set_height(el_val_t handle, el_val_t height);
void      __widget_set_flex(el_val_t handle, el_val_t flex);
void      __widget_set_corner_radius(el_val_t handle, el_val_t radius);
void      __widget_set_disabled(el_val_t handle, el_val_t disabled);
void      __widget_set_hidden(el_val_t handle, el_val_t hidden);

/* Layout / tree */
void      __widget_add_child(el_val_t parent, el_val_t child);
void      __widget_remove_child(el_val_t parent, el_val_t child);
void      __widget_destroy(el_val_t handle);

/* Events */
void      __widget_on_click(el_val_t handle, el_val_t fn_name);
void      __widget_on_change(el_val_t handle, el_val_t fn_name);
void      __widget_on_submit(el_val_t handle, el_val_t fn_name);

/* Manifest reader */
/* Parse the app{} block from manifest.el at path. Returns a JSON string:
 * {"title":"...","width":N,"height":N,"min_width":N,"min_height":N} */
el_val_t  __manifest_read(el_val_t path);

#endif /* EL_TARGET_MACOS */

#ifdef __cplusplus
}
#endif
