/* Generated by cbindgen — do not edit manually. */

#ifndef FFF_C_H
#define FFF_C_H

/* Generated with cbindgen:0.29.2 */

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

/**
 * Current used version of [`FffCreateOptions`].
 */
#define FFF_CREATE_OPTIONS_VERSION 2

/**
 * Result envelope returned by all `fff_*` functions.
 *
 * Heap-allocated. The caller must free it with `fff_free_result`. Calling `fff_free_result`
 * **does not** deallocate the underlying `handle` pointer. It needs to be cleaned separately.
 * see (`fff_destroy`, `fff_free_search_result`, `fff_free_grep_result`, `fff_free_string`, etc.).
 *
 * Depending on the function, the payload is delivered through different fields:
 *
 * | Function                   | Payload field | Type                          |
 * |----------------------------|---------------|-------------------------------|
 * | `fff_create_instance`      | `handle`      | opaque instance pointer       |
 * | `fff_search`               | `handle`      | `*mut FffSearchResult`        |
 * | `fff_live_grep`            | `handle`      | `*mut FffGrepResult`          |
 * | `fff_multi_grep`           | `handle`      | `*mut FffGrepResult`          |
 * | `fff_get_scan_progress`    | `handle`      | `*mut FffScanProgress`        |
 * | `fff_health_check`         | `handle`      | `*mut c_char` (JSON string)   |
 * | `fff_get_historical_query` | `handle`      | `*mut c_char` (string or null)|
 * | `fff_wait_for_scan`        | `int_value`   | 1 = completed, 0 = timed out  |
 * | `fff_track_query`          | `int_value`   | 1 = success, 0 = failure      |
 * | `fff_refresh_git_status`   | `int_value`   | number of files updated       |
 * | `fff_scan_files`           | (none)        | success flag only             |
 * | `fff_restart_index`        | (none)        | success flag only             |
 *
 * On failure, `success` is false and `error` contains the message.
 */
typedef struct FffResult {
  /**
   * Whether the operation succeeded.
   */
  bool success;
  /**
   * Error message on failure. Null on success.
   */
  char *error;
  /**
   * Opaque pointer payload. May be null.
   */
  void *handle;
  /**
   * Integer payload for simple return values (bool as 0/1, counts, etc.).
   */
  int64_t int_value;
} FffResult;

/**
 * Options for `fff_create_instance_with`.
 *
 * Versioned struct: you populate the struct at your call level, we guarantee that
 * the version is stable across the version changes, new fields only appended!
 */
typedef struct FffCreateOptions {
  /**
   * Set to [`FFF_CREATE_OPTIONS_VERSION`] when allocating. Used by the
   * library to determine which trailing fields are populated.
   */
  uint32_t version;
  /**
   * Directory to index (required, non-NULL).
   */
  const char *base_path;
  /**
   * Frecency LMDB database path. NULL/empty to skip frecency tracking.
   */
  const char *frecency_db_path;
  /**
   * Query history LMDB database path. NULL/empty to skip query tracking.
   */
  const char *history_db_path;
  /**
   * Pre-populate mmap caches for top-frecency files after the initial scan.
   */
  bool enable_mmap_cache;
  /**
   * Build content index after the initial scan for faster grep.
   */
  bool enable_content_indexing;
  /**
   * Start a background file-system watcher for live updates.
   */
  bool watch;
  /**
   * Enable AI-agent optimizations.
   */
  bool ai_mode;
  /**
   * Tracing log file path. NULL/empty to skip log init.
   */
  const char *log_file_path;
  /**
   * Log level: `"trace" | "debug" | "info" | "warn" | "error"`.
   * NULL/empty defaults to `"info"`. Ignored when `log_file_path` is unset.
   */
  const char *log_level;
  /**
   * Content cache file-count cap. 0 = auto.
   */
  uint64_t cache_budget_max_files;
  /**
   * Content cache byte cap. 0 = auto.
   */
  uint64_t cache_budget_max_bytes;
  /**
   * Per-file byte cap inside the content cache. 0 = auto.
   */
  uint64_t cache_budget_max_file_size;
  /**
   * Allow indexing the filesystem root (`/`). Off by default — root is
   * rarely the intended target and floods the watcher with churn.
   */
  bool enable_fs_root_scanning;
  /**
   * Allow indexing the user's home directory. Same trade-off as
   * `enable_fs_root_scanning`.
   */
  bool enable_home_dir_scanning;
  /**
   * Follow symlinks during scan and watcher walks. Off by default —
   * enabling this without external loop protection can wedge the watcher
   * on cyclic symlink graphs. Caller is responsible for the trade-off.
   */
  bool follow_symlinks;
} FffCreateOptions;

/**
 * A file item returned by `fff_search`.
 *
 * All string fields are heap-allocated and owned by the parent `FffSearchResult`.
 * Free the entire result with `fff_free_search_result`.
 */
typedef struct FffFileItem {
  char *relative_path;
  char *file_name;
  char *git_status;
  uint64_t size;
  uint64_t modified;
  int64_t access_frecency_score;
  int64_t modification_frecency_score;
  int64_t total_frecency_score;
  bool is_binary;
} FffFileItem;

/**
 * Score breakdown for a search result.
 */
typedef struct FffScore {
  int32_t total;
  int32_t base_score;
  int32_t filename_bonus;
  int32_t special_filename_bonus;
  int32_t frecency_boost;
  int32_t distance_penalty;
  int32_t current_file_penalty;
  int32_t combo_match_boost;
  int32_t path_alignment_bonus;
  bool exact_match;
  char *match_type;
} FffScore;

/**
 * Location parsed from a query string (e.g. `"file.ts:42:10"`).
 *
 * `tag` encodes the variant:
 *   0 = no location,
 *   1 = line only (`line` is set),
 *   2 = position (`line` + `col`),
 *   3 = range (`line`/`col` = start, `end_line`/`end_col` = end).
 */
typedef struct FffLocation {
  uint8_t tag;
  int32_t line;
  int32_t col;
  int32_t end_line;
  int32_t end_col;
} FffLocation;

/**
 * Search result returned by `fff_search`.
 *
 * The caller must free this with `fff_free_search_result`.
 */
typedef struct FffSearchResult {
  /**
   * Pointer to a heap-allocated array of `FffFileItem` (length = `count`).
   */
  struct FffFileItem *items;
  /**
   * Pointer to a heap-allocated array of `FffScore` (length = `count`).
   */
  struct FffScore *scores;
  /**
   * Number of items/scores in the arrays.
   */
  uint32_t count;
  /**
   * Total number of files that matched the query.
   */
  uint32_t total_matched;
  /**
   * Total number of indexed files.
   */
  uint32_t total_files;
  /**
   * Location parsed from the query string.
   */
  struct FffLocation location;
} FffSearchResult;

/**
 * A byte range within a matched line, used for highlighting.
 */
typedef struct FffMatchRange {
  uint32_t start;
  uint32_t end;
} FffMatchRange;

/**
 * A single grep match with file and line information.
 *
 * All string fields and arrays are heap-allocated. Free the parent
 * `FffGrepResult` with `fff_free_grep_result` to release everything.
 */
typedef struct FffGrepMatch {
  char *relative_path;
  char *file_name;
  char *git_status;
  char *line_content;
  struct FffMatchRange *match_ranges;
  char **context_before;
  char **context_after;
  uint64_t size;
  uint64_t modified;
  int64_t total_frecency_score;
  int64_t access_frecency_score;
  int64_t modification_frecency_score;
  uint64_t line_number;
  uint64_t byte_offset;
  uint32_t col;
  uint32_t match_ranges_count;
  uint32_t context_before_count;
  uint32_t context_after_count;
  uint16_t fuzzy_score;
  bool has_fuzzy_score;
  bool is_binary;
  bool is_definition;
} FffGrepMatch;

/**
 * Grep result returned by `fff_live_grep` and `fff_multi_grep`.
 *
 * The caller must free this with `fff_free_grep_result`.
 */
typedef struct FffGrepResult {
  /**
   * Pointer to a heap-allocated array of `FffGrepMatch` (length = `count`).
   */
  struct FffGrepMatch *items;
  /**
   * Number of matches in the `items` array.
   */
  uint32_t count;
  /**
   * Total number of matches (always equal to `count`).
   */
  uint32_t total_matched;
  /**
   * Number of files actually opened and searched in this call.
   */
  uint32_t total_files_searched;
  /**
   * Total number of indexed files (before any filtering).
   */
  uint32_t total_files;
  /**
   * Number of files eligible for search after filtering.
   */
  uint32_t filtered_file_count;
  /**
   * File offset for the next page. 0 if all files have been searched.
   */
  uint32_t next_file_offset;
  /**
   * Regex compilation error when falling back to literal matching. Null if none.
   */
  char *regex_fallback_error;
} FffGrepResult;

/**
 * Scan progress returned by `fff_get_scan_progress`.
 * The caller must free this with `fff_free_scan_progress`.
 */
typedef struct FffScanProgress {
  uint64_t scanned_files_count;
  bool is_scanning;
  bool is_watcher_ready;
  bool is_warmup_complete;
} FffScanProgress;

/**
 * A directory item returned by `fff_search_directories`.
 *
 * All string fields are heap-allocated and owned by the parent `FffDirSearchResult`.
 * Free the entire result with `fff_free_dir_search_result`.
 */
typedef struct FffDirItem {
  char *relative_path;
  char *dir_name;
  int32_t max_access_frecency;
} FffDirItem;

/**
 * Directory search result returned by `fff_search_directories`.
 *
 * The caller must free this with `fff_free_dir_search_result`.
 */
typedef struct FffDirSearchResult {
  /**
   * Pointer to a heap-allocated array of `FffDirItem` (length = `count`).
   */
  struct FffDirItem *items;
  /**
   * Pointer to a heap-allocated array of `FffScore` (length = `count`).
   */
  struct FffScore *scores;
  /**
   * Number of items/scores in the arrays.
   */
  uint32_t count;
  /**
   * Total number of directories that matched the query.
   */
  uint32_t total_matched;
  /**
   * Total number of indexed directories.
   */
  uint32_t total_dirs;
} FffDirSearchResult;

/**
 * A single item in a mixed (files + directories) search result.
 *
 * `item_type`: 0 = file, 1 = directory.
 * All string fields are heap-allocated and owned by the parent `FffMixedSearchResult`.
 */
typedef struct FffMixedItem {
  /**
   * 0 = file, 1 = directory.
   */
  uint8_t item_type;
  char *relative_path;
  /**
   * Filename for files, last directory segment for directories.
   */
  char *display_name;
  char *git_status;
  uint64_t size;
  uint64_t modified;
  /**
   * The access frecency score for files, or max access frecency among all the immediate
   * children for directories.
   */
  int64_t access_frecency_score;
  /**
   * Always 0 for directories
   */
  int64_t modification_frecency_score;
  /**
   * Always 0 for directories
   */
  int64_t total_frecency_score;
  /**
   * Always 0 for directories
   */
  bool is_binary;
} FffMixedItem;

/**
 * Mixed search result returned by `fff_search_mixed`.
 *
 * The caller must free this with `fff_free_mixed_search_result`.
 */
typedef struct FffMixedSearchResult {
  /**
   * Pointer to a heap-allocated array of `FffMixedItem` (length = `count`).
   */
  struct FffMixedItem *items;
  /**
   * Pointer to a heap-allocated array of `FffScore` (length = `count`).
   */
  struct FffScore *scores;
  /**
   * Number of items/scores in the arrays.
   */
  uint32_t count;
  /**
   * Total number of items (files + dirs) that matched the query.
   */
  uint32_t total_matched;
  /**
   * Total number of indexed files.
   */
  uint32_t total_files;
  /**
   * Total number of indexed directories.
   */
  uint32_t total_dirs;
  /**
   * Location parsed from the query string.
   */
  struct FffLocation location;
} FffMixedSearchResult;

/**
 * Create a new file finder instance (legacy 8-arg positional signature).
 *
 * @deprecated Use [`fff_create_instance_with`] (or
 * [`fff_create_instance_with_value`] for FFI bindings) — both take the
 * versioned [`FffCreateOptions`] struct that evolves without ABI breaks.
 * This function delegates to `fff_create_instance_with` internally; the
 * `use_unsafe_no_lock` parameter is deprecated and ignored.
 *
 * ## Safety
 * See `fff_create_instance_with`.
 */
__attribute__((deprecated("Use fff_create_instance_with (by pointer) or fff_create_instance_with_value (by value) with FffCreateOptions instead. The struct evolves without ABI breaks.")))
struct FffResult *fff_create_instance(const char *base_path,
                                      const char *frecency_db_path,
                                      const char *history_db_path,
                                      bool _use_unsafe_no_lock,
                                      bool enable_mmap_cache,
                                      bool enable_content_indexing,
                                      bool watch,
                                      bool ai_mode);

/**
 * Create a new file finder instance (legacy 13-arg positional signature).
 *
 * @deprecated Use [`fff_create_instance_with`] (or
 * [`fff_create_instance_with_value`] for FFI bindings) — both take the
 * versioned [`FffCreateOptions`] struct that evolves without ABI breaks.
 * The `use_unsafe_no_lock` parameter is deprecated and ignored.
 *
 * ## Safety
 * See `fff_create_instance_with`.
 */
__attribute__((deprecated("Use fff_create_instance_with (by pointer) or fff_create_instance_with_value (by value) with FffCreateOptions instead. The struct evolves without ABI breaks.")))
struct FffResult *fff_create_instance2(const char *base_path,
                                       const char *frecency_db_path,
                                       const char *history_db_path,
                                       bool _use_unsafe_no_lock,
                                       bool enable_mmap_cache,
                                       bool enable_content_indexing,
                                       bool watch,
                                       bool ai_mode,
                                       const char *log_file_path,
                                       const char *log_level,
                                       uint64_t cache_budget_max_files,
                                       uint64_t cache_budget_max_bytes,
                                       uint64_t cache_budget_max_file_size);

/**
 * Create a new file finder instance from an [`FffCreateOptions`] struct.
 *
 * **Direct C consumers** populate the struct (designated initializers
 * recommended), set `version` to [`FFF_CREATE_OPTIONS_VERSION`], and pass
 * it by pointer. New fields are appended in future versions; old callers
 * passing `version = 1` keep working forever.
 *
 * **FFI consumers** that prefer struct-by-value semantics (e.g. ffi-rs's
 * `paramsType: [structDef]`) should use [`fff_create_instance_with_value`]
 * instead — it's a thin calling-convention adapter that delegates here.
 *
 * Required: `opts.base_path` must be non-NULL and non-empty.
 *
 * When all three `cache_budget_*` values are 0 the budget is auto-computed
 * from repo size after the initial scan. Otherwise an explicit budget is
 * used: any field left at 0 falls back to its `unlimited()` default.
 *
 * ## Safety
 * * `opts` must be a valid pointer to an `FffCreateOptions` whose `version`
 *   is in the range `1..=FFF_CREATE_OPTIONS_VERSION`.
 * * All string pointers inside `opts` must be valid null-terminated UTF-8
 *   or NULL.
 */
struct FffResult *fff_create_instance_with(const struct FffCreateOptions *opts);

/**
 * Calling-convention adapter for [`fff_create_instance_with`].
 *
 * Same logic, but takes the [`FffCreateOptions`] struct **by value**. This
 * makes the function callable from FFI libraries whose native struct
 * support passes structs by value on the wire (e.g. Node's `ffi-rs` with
 * `paramsType: [structDef]`).
 *
 * This is **not** a versioned wrapper — when new fields are appended to
 * `FffCreateOptions`, both this function and `fff_create_instance_with`
 * pick them up automatically with no signature change.
 *
 * ## Safety
 * All `*const c_char` fields inside `opts` must be valid null-terminated
 * UTF-8 or NULL. The struct itself is consumed by value.
 */
struct FffResult *fff_create_instance_with_value(struct FffCreateOptions opts);

/**
 * Destroy a file finder instance and free all its resources.
 *
 * ## Safety
 * `fff_handle` must be a valid pointer returned by `fff_create_instance`, or null (no-op).
 */
void fff_destroy(void *fff_handle);

/**
 * Perform fuzzy search on indexed files.
 *
 * # Parameters
 *
 * * `fff_handle`              – instance from `fff_create_instance`
 * * `query`                   – search query string
 * * `current_file`            – path of the currently open file for deprioritization (NULL/empty to skip)
 * * `max_threads`             – maximum worker threads (0 = auto-detect)
 * * `page_index`              – pagination offset (0 = first page)
 * * `page_size`               – results per page (0 = default 100)
 * * `combo_boost_multiplier`  – score multiplier for combo matches (0 = default 100)
 * * `min_combo_count`         – minimum combo count before boost applies (0 = default 3)
 *
 * ## Safety
 * * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 * * `query` and `current_file` must be valid null-terminated UTF-8 strings or NULL.
 */
struct FffResult *fff_search(void *fff_handle,
                             const char *query,
                             const char *current_file,
                             uint32_t max_threads,
                             uint32_t page_index,
                             uint32_t page_size,
                             int32_t combo_boost_multiplier,
                             uint32_t min_combo_count);

/**
 * Glob-only search: filter indexed files by a single glob pattern, rank by
 * frecency, and paginate. Bypasses the regular query parser entirely.
 *
 * Use this when you already have a literal glob pattern (e.g. `*.rs`, a
 * recursive `**` match, or `src/components` prefix) and want neither fuzzy
 * matching nor multi-token constraint parsing. Ranking falls back to
 * frecency because there is no fuzzy score to combine with.
 *
 * # Parameters
 *
 * * `fff_handle`   - instance from `fff_create_instance`
 * * `pattern`      - glob pattern (required, no parsing - passed through verbatim)
 * * `current_file` - path of the currently open file for deprioritization (NULL/empty to skip)
 * * `max_threads`  - maximum worker threads (0 = auto-detect)
 * * `page_index`   - pagination offset (0 = first page)
 * * `page_size`    - results per page (0 = default 100)
 *
 * ## Safety
 * * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 * * `pattern` and `current_file` must be valid null-terminated UTF-8 strings or NULL.
 */
struct FffResult *fff_glob(void *fff_handle,
                           const char *pattern,
                           const char *current_file,
                           uint32_t max_threads,
                           uint32_t page_index,
                           uint32_t page_size);

/**
 * Perform fuzzy search on indexed directories.
 *
 * # Parameters
 *
 * * `fff_handle`   – instance from `fff_create_instance`
 * * `query`        – search query string
 * * `current_file` – path of the currently open file for distance scoring (NULL/empty to skip)
 * * `max_threads`  – maximum worker threads (0 = auto-detect)
 * * `page_index`   – pagination offset (0 = first page)
 * * `page_size`    – results per page (0 = default 100)
 *
 * ## Safety
 * * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 * * `query` and `current_file` must be valid null-terminated UTF-8 strings or NULL.
 */
struct FffResult *fff_search_directories(void *fff_handle,
                                         const char *query,
                                         const char *current_file,
                                         uint32_t max_threads,
                                         uint32_t page_index,
                                         uint32_t page_size);

/**
 * Perform a mixed fuzzy search across both files and directories.
 *
 * Returns a single flat list where files and directories are interleaved
 * by total score in descending order. Each item has an `item_type` field
 * (0 = file, 1 = directory).
 *
 * # Parameters
 *
 * * `fff_handle`              – instance from `fff_create_instance`
 * * `query`                   – search query string
 * * `current_file`            – path of the currently open file (NULL/empty to skip)
 * * `max_threads`             – maximum worker threads (0 = auto-detect)
 * * `page_index`              – pagination offset (0 = first page)
 * * `page_size`               – results per page (0 = default 100)
 * * `combo_boost_multiplier`  – score multiplier for combo matches (0 = default 100)
 * * `min_combo_count`         – minimum combo count before boost applies (0 = default 3)
 *
 * ## Safety
 * * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 * * `query` and `current_file` must be valid null-terminated UTF-8 strings or NULL.
 */
struct FffResult *fff_search_mixed(void *fff_handle,
                                   const char *query,
                                   const char *current_file,
                                   uint32_t max_threads,
                                   uint32_t page_index,
                                   uint32_t page_size,
                                   int32_t combo_boost_multiplier,
                                   uint32_t min_combo_count);

/**
 * Perform content search (grep) across indexed files.
 *
 * # Parameters
 *
 * * `fff_handle`            – instance from `fff_create_instance`
 * * `query`                 – search query (supports constraint syntax like `*.rs pattern`)
 * * `mode`                  – 0 = plain text (SIMD), 1 = regex, 2 = fuzzy
 * * `max_file_size`         – skip files larger than this in bytes (0 = default 10 MB)
 * * `max_matches_per_file`  – max matches per file (0 = unlimited)
 * * `smart_case`            – case-insensitive when query is all lowercase
 * * `file_offset`           – file-based pagination offset (0 = start)
 * * `page_limit`            – max matches to return (0 = default 50)
 * * `time_budget_ms`        – wall-clock budget in ms (0 = unlimited)
 * * `before_context`        – context lines before each match
 * * `after_context`         – context lines after each match
 * * `classify_definitions`  – tag matches that are code definitions
 *
 * ## Safety
 * * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 * * `query` must be a valid null-terminated UTF-8 string.
 */
struct FffResult *fff_live_grep(void *fff_handle,
                                const char *query,
                                uint8_t mode,
                                uint64_t max_file_size,
                                uint32_t max_matches_per_file,
                                bool smart_case,
                                uint32_t file_offset,
                                uint32_t page_limit,
                                uint64_t time_budget_ms,
                                uint32_t before_context,
                                uint32_t after_context,
                                bool classify_definitions);

/**
 * Perform multi-pattern OR search (Aho-Corasick) across indexed files.
 *
 * Searches for lines matching ANY of the provided patterns using
 * SIMD-accelerated multi-needle matching.
 *
 * # Parameters
 *
 * * `fff_handle`              – instance from `fff_create_instance`
 * * `patterns_joined`         – patterns separated by `\n` (e.g. `"foo\nbar\nbaz"`)
 * * `constraints`             – file filter like `"*.rs"` or `"/src/"` (NULL/empty to skip)
 * * `max_file_size`           – skip files larger than this in bytes (0 = default 10 MB)
 * * `max_matches_per_file`    – max matches per file (0 = unlimited)
 * * `smart_case`              – case-insensitive when all patterns are lowercase
 * * `file_offset`             – file-based pagination offset (0 = start)
 * * `page_limit`              – max matches to return (0 = default 50)
 * * `time_budget_ms`          – wall-clock budget in ms (0 = unlimited)
 * * `before_context`          – context lines before each match
 * * `after_context`           – context lines after each match
 * * `classify_definitions`    – tag matches that are code definitions
 *
 * ## Safety
 * * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 * * `patterns_joined` and `constraints` must be valid null-terminated UTF-8 or NULL.
 */
struct FffResult *fff_multi_grep(void *fff_handle,
                                 const char *patterns_joined,
                                 const char *constraints,
                                 uint64_t max_file_size,
                                 uint32_t max_matches_per_file,
                                 bool smart_case,
                                 uint32_t file_offset,
                                 uint32_t page_limit,
                                 uint64_t time_budget_ms,
                                 uint32_t before_context,
                                 uint32_t after_context,
                                 bool classify_definitions);

/**
 * Trigger a rescan of the file index.
 *
 * ## Safety
 * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 */
struct FffResult *fff_scan_files(void *fff_handle);

/**
 * Check if a scan is currently in progress.
 *
 * ## Safety
 * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 */
bool fff_is_scanning(void *fff_handle);

/**
 * Get the base path of the file picker.
 *
 * Returns an `FffResult` with a heap-allocated C string in the `handle`
 * field. Free the string with `fff_free_string` after reading it.
 *
 * ## Safety
 * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 */
struct FffResult *fff_get_base_path(void *fff_handle);

/**
 * Get scan progress information.
 *
 * ## Safety
 * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 */
struct FffResult *fff_get_scan_progress(void *fff_handle);

/**
 * Wait for initial scan to complete.
 *
 * ## Safety
 * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 */
struct FffResult *fff_wait_for_scan(void *fff_handle, uint64_t timeout_ms);

/**
 * Wait for the background file watcher to be ready.
 *
 * ## Safety
 * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 */
struct FffResult *fff_wait_for_watcher(void *fff_handle, uint64_t timeout_ms);

/**
 * Restart indexing in a new directory.
 *
 * ## Safety
 * * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 * * `new_path` must be a valid null-terminated UTF-8 string.
 */
struct FffResult *fff_restart_index(void *fff_handle, const char *new_path);

/**
 * Refresh git status cache.
 *
 * ## Safety
 * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 */
struct FffResult *fff_refresh_git_status(void *fff_handle);

/**
 * Track query completion for smart suggestions.
 *
 * ## Safety
 * * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 * * `query` and `file_path` must be valid null-terminated UTF-8 strings.
 */
struct FffResult *fff_track_query(void *fff_handle, const char *query, const char *file_path);

/**
 * Get historical query by offset (0 = most recent).
 *
 * ## Safety
 * `fff_handle` must be a valid instance pointer from `fff_create_instance`.
 */
struct FffResult *fff_get_historical_query(void *fff_handle, uint64_t offset);

/**
 * Get health check information.
 *
 * ## Safety
 * * `fff_handle` must be a valid instance pointer from `fff_create_instance`, or null for
 *   a limited health check (version + git only).
 * * `test_path` can be null or a valid null-terminated UTF-8 string.
 */
struct FffResult *fff_health_check(void *fff_handle, const char *test_path);

/**
 * Free a search result returned by `fff_search`.
 *
 * This frees the `FffSearchResult` struct, its `items` and `scores` arrays,
 * and all heap-allocated strings within each item and score.
 *
 * ## Safety
 * `result` must be a valid pointer previously returned via `FffResult.handle`
 * from `fff_search`, or null (no-op).
 */
void fff_free_search_result(struct FffSearchResult *result);

/**
 * Get a pointer to the `index`-th `FffFileItem` in a search result.
 *
 * Returns null if `result` is null or `index >= result->count`.
 * The returned pointer is valid until the search result is freed.
 *
 * ## Safety
 * `result` must be a valid `FffSearchResult` pointer from `fff_search`.
 */
const struct FffFileItem *fff_search_result_get_item(const struct FffSearchResult *result,
                                                     uint32_t index);

/**
 * Get a pointer to the `index`-th `FffScore` in a search result.
 *
 * Returns null if `result` is null or `index >= result->count`.
 * The returned pointer is valid until the search result is freed.
 *
 * ## Safety
 * `result` must be a valid `FffSearchResult` pointer from `fff_search`.
 */
const struct FffScore *fff_search_result_get_score(const struct FffSearchResult *result,
                                                   uint32_t index);

/**
 * Free a grep result returned by `fff_live_grep` or `fff_multi_grep`.
 *
 * This frees the `FffGrepResult` struct, its `items` array, and all
 * heap-allocated strings, match ranges, and context arrays within each match.
 *
 * ## Safety
 * `result` must be a valid pointer previously returned via `FffResult.handle`
 * from `fff_live_grep` or `fff_multi_grep`, or null (no-op).
 */
void fff_free_grep_result(struct FffGrepResult *result);

/**
 * Get a pointer to the `index`-th `FffGrepMatch` in a grep result.
 *
 * Returns null if `result` is null or `index >= result->count`.
 * The returned pointer is valid until the grep result is freed.
 *
 * ## Safety
 * `result` must be a valid `FffGrepResult` pointer from `fff_live_grep` or `fff_multi_grep`.
 */
const struct FffGrepMatch *fff_grep_result_get_match(const struct FffGrepResult *result,
                                                     uint32_t index);

/**
 * Free a scan progress result returned by `fff_get_scan_progress`.
 *
 * ## Safety
 * `result` must be a valid pointer previously returned via `FffResult.handle`
 * from `fff_get_scan_progress`, or null (no-op).
 */
void fff_free_scan_progress(struct FffScanProgress *result);

/**
 * Offset a pointer by `byte_offset` bytes.
 *
 * General-purpose utility for FFI consumers that need pointer arithmetic
 * (e.g. iterating over arrays). Returns null if `base` is null.
 *
 * ## Safety
 * The resulting pointer must be within the bounds of the original allocation.
 */
const void *fff_ptr_offset(const void *base, uintptr_t byte_offset);

/**
 * Free a result returned by any `fff_*` function.
 * **IMPORTANT:** this doesn't clean the the internal handle, so it is safe to call right after
 * you handle the error case.
 *
 * Note: Many non-libffi implementations are not supporting struct-by-value returns, so it's more
 * convenient to have pointer returned at most of the time, though allocating result for every call
 * is annoying, so we just rely on the fact that our allocator is good enough.
 *
 * ## Safety
 * `result_ptr` must be a valid pointer returned by a `fff_*` function.
 */
void fff_free_result(struct FffResult *result_ptr);

/**
 * Free a string returned by `fff_*` functions.
 *
 * ## Safety
 * `s` must be a valid C string allocated by this library.
 */
void fff_free_string(char *s);

/**
 * Free a directory search result returned by `fff_search_directories`.
 *
 * ## Safety
 * `result` must be a valid pointer previously returned via `FffResult.handle`
 * from `fff_search_directories`, or null (no-op).
 */
void fff_free_dir_search_result(struct FffDirSearchResult *result);

/**
 * Get a pointer to the `index`-th `FffDirItem` in a directory search result.
 *
 * ## Safety
 * `result` must be a valid `FffDirSearchResult` pointer from `fff_search_directories`.
 */
const struct FffDirItem *fff_dir_search_result_get_item(const struct FffDirSearchResult *result,
                                                        uint32_t index);

/**
 * Get a pointer to the `index`-th `FffScore` in a directory search result.
 *
 * ## Safety
 * `result` must be a valid `FffDirSearchResult` pointer from `fff_search_directories`.
 */
const struct FffScore *fff_dir_search_result_get_score(const struct FffDirSearchResult *result,
                                                       uint32_t index);

/**
 * Free a mixed search result returned by `fff_search_mixed`.
 *
 * ## Safety
 * `result` must be a valid pointer previously returned via `FffResult.handle`
 * from `fff_search_mixed`, or null (no-op).
 */
void fff_free_mixed_search_result(struct FffMixedSearchResult *result);

/**
 * Get a pointer to the `index`-th `FffMixedItem` in a mixed search result.
 *
 * ## Safety
 * `result` must be a valid `FffMixedSearchResult` pointer from `fff_search_mixed`.
 */
const struct FffMixedItem *fff_mixed_search_result_get_item(const struct FffMixedSearchResult *result,
                                                            uint32_t index);

/**
 * Get a pointer to the `index`-th `FffScore` in a mixed search result.
 *
 * ## Safety
 * `result` must be a valid `FffMixedSearchResult` pointer from `fff_search_mixed`.
 */
const struct FffScore *fff_mixed_search_result_get_score(const struct FffMixedSearchResult *result,
                                                         uint32_t index);

/**
 * Returns the relative path of a file item (e.g. `"src/main.rs"`).
 *
 * Returns null if `item` is null. The returned pointer is valid for the
 * lifetime of the owning `FffSearchResult`; do not free it directly.
 *
 * ## Safety
 * `item` must be a valid `FffFileItem` pointer or null.
 */
const char *fff_file_item_get_relative_path(const struct FffFileItem *item);

/**
 * Returns the file-name component of a file item (e.g. `"main.rs"`).
 *
 * Returns null if `item` is null. Do not free the returned pointer.
 *
 * ## Safety
 * `item` must be a valid `FffFileItem` pointer or null.
 */
const char *fff_file_item_get_file_name(const struct FffFileItem *item);

/**
 * Returns the git status string for a file item (e.g. `"M "`, `"??"`)
 * or null if git is unavailable, the file is untracked, or `item` is null.
 *
 * Do not free the returned pointer.
 *
 * ## Safety
 * `item` must be a valid `FffFileItem` pointer or null.
 */
const char *fff_file_item_get_git_status(const struct FffFileItem *item);

/**
 * Returns the file size in bytes. Returns `0` if `item` is null.
 *
 * ## Safety
 * `item` must be a valid `FffFileItem` pointer or null.
 */
uint64_t fff_file_item_get_size(const struct FffFileItem *item);

/**
 * Returns the last-modified time as seconds since the UNIX epoch.
 * Returns `0` if `item` is null.
 *
 * ## Safety
 * `item` must be a valid `FffFileItem` pointer or null.
 */
uint64_t fff_file_item_get_modified(const struct FffFileItem *item);

/**
 * Returns the combined frecency score. Returns `0` if `item` is null.
 *
 * ## Safety
 * `item` must be a valid `FffFileItem` pointer or null.
 */
int64_t fff_file_item_get_total_frecency_score(const struct FffFileItem *item);

/**
 * Returns the access-based frecency score. Returns `0` if `item` is null.
 *
 * ## Safety
 * `item` must be a valid `FffFileItem` pointer or null.
 */
int64_t fff_file_item_get_access_frecency_score(const struct FffFileItem *item);

/**
 * Returns the modification-based frecency score. Returns `0` if `item` is null.
 *
 * ## Safety
 * `item` must be a valid `FffFileItem` pointer or null.
 */
int64_t fff_file_item_get_modification_frecency_score(const struct FffFileItem *item);

/**
 * Returns `true` if the file was detected as binary. Returns `false` if `item` is null.
 *
 * ## Safety
 * `item` must be a valid `FffFileItem` pointer or null.
 */
bool fff_file_item_get_is_binary(const struct FffFileItem *item);

/**
 * Returns the relative path of the file containing this grep match.
 *
 * Returns null if `m` is null. Do not free the returned pointer.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
const char *fff_grep_match_get_relative_path(const struct FffGrepMatch *m);

/**
 * Returns the file-name component of the file containing this grep match.
 *
 * Returns null if `m` is null. Do not free the returned pointer.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
const char *fff_grep_match_get_file_name(const struct FffGrepMatch *m);

/**
 * Returns the git status string for the matched file (e.g. `"M "`, `"??"`)
 * or null if git is unavailable, the file is untracked, or `m` is null.
 *
 * Do not free the returned pointer.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
const char *fff_grep_match_get_git_status(const struct FffGrepMatch *m);

/**
 * Returns the full text content of the matched line.
 *
 * Returns null if `m` is null. Do not free the returned pointer.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
const char *fff_grep_match_get_line_content(const struct FffGrepMatch *m);

/**
 * Returns the 1-based line number of the match within its file.
 * Returns `0` if `m` is null.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
uint64_t fff_grep_match_get_line_number(const struct FffGrepMatch *m);

/**
 * Returns the 0-based column of the match start within its line.
 * Returns `0` if `m` is null.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
uint32_t fff_grep_match_get_col(const struct FffGrepMatch *m);

/**
 * Returns the byte offset of the match start from the beginning of the file.
 * Returns `0` if `m` is null.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
uint64_t fff_grep_match_get_byte_offset(const struct FffGrepMatch *m);

/**
 * Returns the file size in bytes for the matched file. Returns `0` if `m` is null.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
uint64_t fff_grep_match_get_size(const struct FffGrepMatch *m);

/**
 * Returns the combined frecency score for the matched file.
 * Returns `0` if `m` is null.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
int64_t fff_grep_match_get_total_frecency_score(const struct FffGrepMatch *m);

/**
 * Returns the access-based frecency score for the matched file.
 * Returns `0` if `m` is null.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
int64_t fff_grep_match_get_access_frecency_score(const struct FffGrepMatch *m);

/**
 * Returns the modification-based frecency score for the matched file.
 * Returns `0` if `m` is null.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
int64_t fff_grep_match_get_modification_frecency_score(const struct FffGrepMatch *m);

/**
 * Returns the last-modified time as seconds since the UNIX epoch for the matched file.
 * Returns `0` if `m` is null.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
uint64_t fff_grep_match_get_modified(const struct FffGrepMatch *m);

/**
 * Returns the number of highlight ranges in this match. Returns `0` if `m` is null.
 *
 * Use with [`fff_grep_match_get_match_range`] to iterate the highlight spans.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
uint32_t fff_grep_match_get_match_ranges_count(const struct FffGrepMatch *m);

/**
 * Returns a pointer to the `index`-th [`FffMatchRange`] highlight span.
 *
 * Returns null if `m` is null, `index >= match_ranges_count`, or the
 * ranges array is null. The returned pointer is valid until the owning
 * `FffGrepResult` is freed; do not free it directly.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
const struct FffMatchRange *fff_grep_match_get_match_range(const struct FffGrepMatch *m,
                                                           uint32_t index);

/**
 * Returns the number of context lines captured before the match.
 * Returns `0` if `m` is null.
 *
 * Use with [`fff_grep_match_get_context_before`] to read each line.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
uint32_t fff_grep_match_get_context_before_count(const struct FffGrepMatch *m);

/**
 * Returns the `index`-th context line before the match.
 *
 * Returns null if `m` is null, `index >= context_before_count`, or the
 * context array is null. Do not free the returned pointer.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
const char *fff_grep_match_get_context_before(const struct FffGrepMatch *m, uint32_t index);

/**
 * Returns the number of context lines captured after the match.
 * Returns `0` if `m` is null.
 *
 * Use with [`fff_grep_match_get_context_after`] to read each line.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
uint32_t fff_grep_match_get_context_after_count(const struct FffGrepMatch *m);

/**
 * Returns the `index`-th context line after the match.
 *
 * Returns null if `m` is null, `index >= context_after_count`, or the
 * context array is null. Do not free the returned pointer.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
const char *fff_grep_match_get_context_after(const struct FffGrepMatch *m, uint32_t index);

/**
 * Returns the fuzzy match score. Returns `0` if `m` is null or no fuzzy
 * score is present.
 *
 * Always check [`fff_grep_match_get_has_fuzzy_score`] first; `0` is
 * ambiguous without that flag.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
uint16_t fff_grep_match_get_fuzzy_score(const struct FffGrepMatch *m);

/**
 * Returns `true` if this match carries a valid fuzzy score.
 * Returns `false` if `m` is null.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
bool fff_grep_match_get_has_fuzzy_score(const struct FffGrepMatch *m);

/**
 * Returns `true` if the match was identified as a symbol definition.
 * Returns `false` if `m` is null.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
bool fff_grep_match_get_is_definition(const struct FffGrepMatch *m);

/**
 * Returns `true` if the matched file was detected as binary.
 * Returns `false` if `m` is null.
 *
 * ## Safety
 * `m` must be a valid `FffGrepMatch` pointer or null.
 */
bool fff_grep_match_get_is_binary(const struct FffGrepMatch *m);

/**
 * Returns the number of items in the result. Returns `0` if `r` is null.
 *
 * ## Safety
 * `r` must be a valid `FffSearchResult` pointer or null.
 */
uint32_t fff_search_result_get_count(const struct FffSearchResult *r);

/**
 * Returns the total number of files that matched before the result was
 * truncated to the page size. Returns `0` if `r` is null.
 *
 * ## Safety
 * `r` must be a valid `FffSearchResult` pointer or null.
 */
uint32_t fff_search_result_get_total_matched(const struct FffSearchResult *r);

/**
 * Returns the total number of indexed files considered during search.
 * Returns `0` if `r` is null.
 *
 * ## Safety
 * `r` must be a valid `FffSearchResult` pointer or null.
 */
uint32_t fff_search_result_get_total_files(const struct FffSearchResult *r);

/**
 * Returns the number of matches in the result. Returns `0` if `r` is null.
 *
 * ## Safety
 * `r` must be a valid `FffGrepResult` pointer or null.
 */
uint32_t fff_grep_result_get_count(const struct FffGrepResult *r);

/**
 * Returns the total number of matches found across all pages.
 * Returns `0` if `r` is null.
 *
 * ## Safety
 * `r` must be a valid `FffGrepResult` pointer or null.
 */
uint32_t fff_grep_result_get_total_matched(const struct FffGrepResult *r);

/**
 * Returns the number of files actually opened and searched in this call.
 * Returns `0` if `r` is null.
 *
 * ## Safety
 * `r` must be a valid `FffGrepResult` pointer or null.
 */
uint32_t fff_grep_result_get_total_files_searched(const struct FffGrepResult *r);

/**
 * Returns the total number of indexed files before any filtering.
 * Returns `0` if `r` is null.
 *
 * ## Safety
 * `r` must be a valid `FffGrepResult` pointer or null.
 */
uint32_t fff_grep_result_get_total_files(const struct FffGrepResult *r);

/**
 * Returns the number of files eligible for search after path/type filtering.
 * Returns `0` if `r` is null.
 *
 * ## Safety
 * `r` must be a valid `FffGrepResult` pointer or null.
 */
uint32_t fff_grep_result_get_filtered_file_count(const struct FffGrepResult *r);

/**
 * Returns the file offset for the next page, or `0` if all files have been
 * searched or `r` is null. Pass this value as `file_offset` to a subsequent
 * `fff_live_grep` or `fff_multi_grep` call to continue pagination.
 *
 * ## Safety
 * `r` must be a valid `FffGrepResult` pointer or null.
 */
uint32_t fff_grep_result_get_next_file_offset(const struct FffGrepResult *r);

/**
 * Returns the regex compilation error string if the engine fell back to
 * literal matching, or null if there was no error or `r` is null.
 *
 * Do not free the returned pointer.
 *
 * ## Safety
 * `r` must be a valid `FffGrepResult` pointer or null.
 */
const char *fff_grep_result_get_regex_fallback_error(const struct FffGrepResult *r);

#endif  /* FFF_C_H */
