/*
 * SmartScribeDocx.h  —  C API for SmartScribe.Docx SDK
 * ======================================================
 * Pure C linkage. No C++ types in the public interface.
 * Usable from: Python (ctypes/cffi), C# (P/Invoke), Rust (bindgen),
 *              Java (JNI/JNA), Swift (direct C interop), plain C.
 *
 * All strings are UTF-8, null-terminated.
 * All byte buffers returned by the API are owned by the library and
 * remain valid until the next call that returns a buffer on the same handle,
 * or until ssdocx_close() is called. Do NOT free them yourself.
 *
 * Error handling:
 *   - Functions that can fail return int: 1 = success, 0 = failure.
 *   - ssdocx_error(handle) returns the last error message.
 *
 * Thread safety:
 *   - Each handle is NOT thread-safe. Use one handle per thread,
 *     or serialize access externally.
 *   - ssdocx_build_hf_xml() is stateless and thread-safe.
 *
 * Quick start (Python ctypes):
 *   import ctypes
 *   lib = ctypes.CDLL("SmartScribeDocx.dll")
 *   lib.ssDocx_open.restype = ctypes.c_void_p
 *   lib.ssDocx_open.argtypes = [ctypes.c_char_p]
 *   h = lib.ssDocx_open(b"mybook.docx")
 *   ...
 *   lib.ssDocx_close(h)
 *
 * HFType values: 0 = Default (odd pages), 1 = Even pages, 2 = First page
 *
 * Version: 1.1.0
 */

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

/* ── Platform export/import macros ─────────────────────────────────────── */
#if defined(_WIN32) || defined(_WIN64)
  #ifdef SMARTSCRIBEDOCX_BUILDING_DLL
    #define SSAPI __declspec(dllexport)
  #else
    #define SSAPI __declspec(dllimport)
  #endif
#else
  #define SSAPI __attribute__((visibility("default")))
#endif

/* ── Opaque document handle ─────────────────────────────────────────────── */
typedef struct SsDocxImpl_* SsDocxHandle;

/* ── HFType constants ───────────────────────────────────────────────────── */
#define SS_HF_DEFAULT  0   /* Default: odd pages (or all pages when even/odd off) */
#define SS_HF_EVEN     1   /* Even pages (requires evenAndOdd = true)              */
#define SS_HF_FIRST    2   /* First page only (requires titlePage = true)          */

/* ═══════════════════════════════════════════════════════════════════════════
 * Lifecycle
 * ═══════════════════════════════════════════════════════════════════════════ */

/*
 * ssDocx_init — call once before first use when no Qt event loop exists.
 * Prints a one-line development notice to stderr on every init.
 * Safe to call multiple times. Safe to skip if QCoreApplication exists.
 * For production use, call ssDocx_init_licensed() instead.
 */
SSAPI void ssDocx_init(void);

/*
 * ssDocx_init_licensed — production init with a commercial license key.
 * key format: "SSDX-XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX"
 * Returns 1 if the key is valid and accepted (no notice printed).
 * Returns 0 if the key is invalid or absent — falls back to development
 * mode with a one-line notice printed to stderr. The library continues
 * to function normally either way; the notice is informational only.
 *
 * If maintenance has expired the library still works but prints a
 * one-line "maintenance expired" notice. Updates require renewal;
 * the version you licensed continues to function indefinitely.
 */
SSAPI int ssDocx_init_licensed(const char* key);

/*
 * ssDocx_version — returns "major.minor.patch" e.g. "1.0.0"
 */
SSAPI const char* ssDocx_version(void);

/*
 * ssDocx_open — open an existing DOCX file.
 * Returns NULL on failure. Use ssDocx_error(NULL) for a static error message.
 */
SSAPI SsDocxHandle ssDocx_open(const char* path);

/*
 * ssDocx_create_blank — create a blank DOCX at the given path.
 * Returns NULL on failure.
 */
SSAPI SsDocxHandle ssDocx_create_blank(const char* path);

/*
 * ssDocx_close — release all resources. Handle is invalid after this call.
 */
SSAPI void ssDocx_close(SsDocxHandle h);

/*
 * ssDocx_is_valid — 1 if the handle is open and valid, 0 otherwise.
 */
SSAPI int ssDocx_is_valid(SsDocxHandle h);

/*
 * ssDocx_error — last error message for this handle (UTF-8, null-terminated).
 * If h is NULL, returns the last static error from ssDocx_open/create_blank.
 * Valid until the next API call on this handle.
 */
SSAPI const char* ssDocx_error(SsDocxHandle h);

/* ═══════════════════════════════════════════════════════════════════════════
 * Save
 * ═══════════════════════════════════════════════════════════════════════════ */

/* Save to the document's original path. Returns 1 on success. */
SSAPI int ssDocx_save(SsDocxHandle h);

/* Save to a new path (version copy). Original is unchanged. */
SSAPI int ssDocx_save_as(SsDocxHandle h, const char* path);

/* === Body content authoring (v1.1.0) === */

/*
 * ssDocx_set_body_html - replace the document body with content built from
 * UTF-8 HTML. Paragraphs and inline runs (bold / italic / underline / font
 * family / size) are emitted. Builds into the open document WITHOUT saving;
 * call ssDocx_save() or ssDocx_save_as() afterwards, so you can set the body,
 * then margins / headers / properties, then save in any order.
 * Returns 1 on success, 0 on failure (see ssDocx_error).
 */
SSAPI int ssDocx_set_body_html(SsDocxHandle h, const char* html);

/*
 * ssDocx_write_html - one-shot convenience. Creates a blank DOCX at path,
 * fills its body from UTF-8 HTML, and saves. No handle required.
 * Returns 1 on success, 0 on failure (see ssDocx_error(NULL)).
 */
SSAPI int ssDocx_write_html(const char* path, const char* html);

/*
 * ssDocx_resave_full - open an existing DOCX, render its full body through the
 * engine (reader -> QTextDocument), then write it back to out_path via the same
 * saveSection round-trip path the editor uses. Effectively normalizes/rebuilds
 * a document through the engine. No handle required.
 * Returns 1 on success, 0 on failure (see ssDocx_error(NULL)).
 */
SSAPI int ssDocx_resave_full(const char* in_path, const char* out_path);

/* ═══════════════════════════════════════════════════════════════════════════
 * Margins   (all values in twips; 1 inch = 1440 twips)
 * ═══════════════════════════════════════════════════════════════════════════ */

SSAPI int ssDocx_get_margins(SsDocxHandle h,
    int* top, int* bottom, int* left, int* right,
    int* header_dist, int* footer_dist, int* gutter, int* mirror_margins);

SSAPI int ssDocx_set_margins(SsDocxHandle h,
    int top, int bottom, int left, int right,
    int header_dist, int footer_dist, int gutter, int mirror_margins);

/* ═══════════════════════════════════════════════════════════════════════════
 * Headers and Footers
 * ═══════════════════════════════════════════════════════════════════════════ */

/*
 * ssDocx_get_header_xml / ssDocx_get_footer_xml
 * Returns pointer to the raw part XML bytes, sets *out_size to byte count.
 * Returns NULL (out_size=0) if that variant is not defined.
 * Buffer is valid until next get_header/footer_xml call on this handle.
 */
SSAPI const unsigned char* ssDocx_get_header_xml(SsDocxHandle h, int hf_type,
                                                   unsigned int* out_size);
SSAPI const unsigned char* ssDocx_get_footer_xml(SsDocxHandle h, int hf_type,
                                                   unsigned int* out_size);

/*
 * ssDocx_set_header_xml / ssDocx_set_footer_xml
 * Writes xml_bytes into the document (creates part + rels + Content_Types if needed).
 * xml_size = byte count of xml_bytes (not including any null terminator).
 */
SSAPI int ssDocx_set_header_xml(SsDocxHandle h, int hf_type,
                                 const unsigned char* xml_bytes, unsigned int xml_size);
SSAPI int ssDocx_set_footer_xml(SsDocxHandle h, int hf_type,
                                 const unsigned char* xml_bytes, unsigned int xml_size);

/* ═══════════════════════════════════════════════════════════════════════════
 * H/F XML builder  (stateless — no handle needed)
 * Builds a complete <w:hdr> or <w:ftr> part from a template string.
 *
 * is_header : 1 = header, 0 = footer
 * template  : UTF-8 text with optional variables:
 *             {PAGE} {NUMPAGES} {TITLE} {CHAPTER} {AUTHOR}
 * alignment : "left", "center", or "right"
 * out_size  : set to the byte count of the returned buffer
 *
 * Returns a buffer owned by the library. Valid until the next call to
 * ssDocx_build_hf_xml(). Thread-safe (uses thread-local storage).
 * Returns NULL on internal error.
 * ═══════════════════════════════════════════════════════════════════════════ */
SSAPI const unsigned char* ssDocx_build_hf_xml(int is_header,
                                                 const char* template_text,
                                                 const char* alignment,
                                                 unsigned int* out_size);

/* ═══════════════════════════════════════════════════════════════════════════
 * Document properties  (docProps/core.xml)
 * key: "title", "author", "subject", "description"
 * ═══════════════════════════════════════════════════════════════════════════ */

/* Returns UTF-8 string, valid until next get_doc_property call on this handle.
   Returns "" (not NULL) if property is not set. */
SSAPI const char* ssDocx_get_doc_property(SsDocxHandle h, const char* key);

/* Returns 1 on success, 0 if property could not be set. */
SSAPI int ssDocx_set_doc_property(SsDocxHandle h, const char* key, const char* value);

/* ═══════════════════════════════════════════════════════════════════════════
 * Section flags
 * ═══════════════════════════════════════════════════════════════════════════ */

SSAPI int ssDocx_get_title_page(SsDocxHandle h);        /* 1 if w:titlePg set   */
SSAPI int ssDocx_set_title_page(SsDocxHandle h, int on);

SSAPI int ssDocx_get_even_and_odd(SsDocxHandle h);      /* 1 if evenAndOdd set  */
SSAPI int ssDocx_set_even_and_odd(SsDocxHandle h, int on);

/* ═══════════════════════════════════════════════════════════════════════════
 * Page number format   (w:pgNumType in sectPr)
 * fmt: "decimal", "lowerRoman", "upperRoman", "lowerLetter", "upperLetter"
 * start: page number to start at; pass -1 to continue from previous section
 * ═══════════════════════════════════════════════════════════════════════════ */
SSAPI int ssDocx_set_page_number_format(SsDocxHandle h,
                                         const char* fmt, int start);

#ifdef __cplusplus
}  /* extern "C" */
#endif
