#pragma once

/**
 * @file ml.h
 * @brief Unified C API for machine learning operations
 *
 * This header provides a comprehensive C interface for various ML tasks including:
 * - Language models (LLM) and multimodal models (VLM)
 * - Text embeddings and reranking
 * - Image generation and computer vision (OCR)
 * - Speech recognition (ASR) and text-to-speech (TTS)
 * - Speaker diarization
 *
 * All functions return status codes where applicable, with negative values indicating errors.
 * Memory management follows RAII principles - use corresponding destroy/free functions.
 */

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

#ifdef ML_SHARED
#if defined(_WIN32) && !defined(__MINGW32__)
#ifdef ML_BUILD
#define ML_API __declspec(dllexport)
#else
#define ML_API __declspec(dllimport)
#endif
#else
#define ML_API __attribute__((visibility("default")))
#endif
#else
#define ML_API
#endif

#ifdef __cplusplus
extern "C" {
#endif

/** Error code enumeration for ML operations */
typedef enum {
    /** ===== SUCCESS ===== */

    ML_SUCCESS = 0, /**< Operation completed successfully */

    /* ===== COMMON ERRORS (100xxx) ===== */

    ML_ERROR_COMMON_UNKNOWN           = -100000, /**< Unknown error */
    ML_ERROR_COMMON_INVALID_INPUT     = -100001, /**< Invalid input parameters or handle */
    ML_ERROR_COMMON_MEMORY_ALLOCATION = -100003, /**< Memory allocation failed */
    ML_ERROR_COMMON_FILE_NOT_FOUND    = -100004, /**< File not found or inaccessible */
    ML_ERROR_COMMON_NOT_INITIALIZED   = -100007, /**< Library not initialized */
    ML_ERROR_COMMON_NOT_SUPPORTED     = -100013, /**< Operation not supported */

    ML_ERROR_COMMON_MODEL_LOAD    = -100201, /**< Model loading failed */
    ML_ERROR_COMMON_MODEL_INVALID = -100203, /**< Invalid model format */

    ML_ERROR_COMMON_LICENSE_INVALID = -100601, /**< Invalid license */
    ML_ERROR_COMMON_LICENSE_EXPIRED = -100602, /**< License expired */

    /* ===== LLM ERRORS (200xxx) ===== */

    ML_ERROR_LLM_TOKENIZATION_FAILED         = -200001, /**< Tokenization failed */
    ML_ERROR_LLM_TOKENIZATION_CONTEXT_LENGTH = -200004, /**< Context length exceeded */

    ML_ERROR_LLM_GENERATION_FAILED          = -200101, /**< Text generation failed */
    ML_ERROR_LLM_GENERATION_PROMPT_TOO_LONG = -200103, /**< Input prompt too long */

    /* ===== VLM ERRORS (201xxx) ===== */

    ML_ERROR_VLM_IMAGE_LOAD   = -201001, /**< Image loading failed */
    ML_ERROR_VLM_IMAGE_FORMAT = -201002, /**< Unsupported image format */

    ML_ERROR_VLM_AUDIO_LOAD   = -201101, /**< Audio loading failed */
    ML_ERROR_VLM_AUDIO_FORMAT = -201102, /**< Unsupported audio format */

    ML_ERROR_VLM_GENERATION_FAILED = -201201, /**< Multimodal generation failed */

    /* ===== Embedding ERRORS (202xxx) ===== */

    ML_ERROR_EMBEDDING_GENERATION = -202301, /**< Embedding generation failed */
    ML_ERROR_EMBEDDING_DIMENSION  = -202302, /**< Invalid embedding dimension */

    /* ===== Reranking ERRORS (203xxx) ===== */

    ML_ERROR_RERANK_FAILED = -203401, /**< Reranking failed */
    ML_ERROR_RERANK_INPUT  = -203402, /**< Invalid reranking input */

    /* ===== Image Generation ERRORS (204xxx) ===== */

    ML_ERROR_IMAGEGEN_GENERATION = -204501, /**< Image generation failed */
    ML_ERROR_IMAGEGEN_PROMPT     = -204502, /**< Invalid image prompt */
    ML_ERROR_IMAGEGEN_DIMENSION  = -204503, /**< Invalid image dimensions */

    /* ===== ASR ERRORS (205xxx) ===== */

    ML_ERROR_ASR_TRANSCRIPTION = -205001, /**< ASR transcription failed */
    ML_ERROR_ASR_AUDIO_FORMAT  = -205002, /**< Unsupported ASR audio format */
    ML_ERROR_ASR_LANGUAGE      = -205003, /**< Unsupported ASR language */

    /* ===== ASR Streaming ERRORS (205xxx) ===== */

    ML_ERROR_ASR_STREAM_NOT_STARTED    = -205010, /**< Streaming not started */
    ML_ERROR_ASR_STREAM_ALREADY_ACTIVE = -205011, /**< Streaming already active */
    ML_ERROR_ASR_STREAM_INVALID_AUDIO  = -205012, /**< Invalid audio data */
    ML_ERROR_ASR_STREAM_BUFFER_FULL    = -205013, /**< Audio buffer full */
    ML_ERROR_ASR_STREAM_CALLBACK_ERROR = -205014, /**< Callback execution error */

    /* ===== TTS ERRORS (206xxx) ===== */

    ML_ERROR_TTS_SYNTHESIS    = -206001, /**< TTS synthesis failed */
    ML_ERROR_TTS_VOICE        = -206002, /**< TTS voice not found */
    ML_ERROR_TTS_AUDIO_FORMAT = -206003, /**< TTS audio format error */

    /* ===== CV ERRORS (207xxx) ===== */

    ML_ERROR_CV_OCR_DETECTION   = -207001, /**< OCR text detection failed */
    ML_ERROR_CV_OCR_RECOGNITION = -207002, /**< OCR text recognition failed */
    ML_ERROR_CV_OCR_FAILED      = -207003, /**< OCR failed */

    /* ===== Diarization ERRORS (208xxx) ===== */

    ML_ERROR_DIARIZE_AUDIO_LOAD   = -208001, /**< Audio loading failed */
    ML_ERROR_DIARIZE_SEGMENTATION = -208101, /**< Segmentation model execution failed */
    ML_ERROR_DIARIZE_EMBEDDING    = -208102, /**< Embedding extraction failed */
    ML_ERROR_DIARIZE_CLUSTERING   = -208103, /**< Speaker clustering failed (PLDA/VBx) */

} ml_ErrorCode;

/** Get error message string for error code */
ML_API const char* ml_get_error_message(const ml_ErrorCode error_code);

/* ========================================================================== */
/*                              CORE TYPES & UTILITIES                         */
/* ========================================================================== */

/** Plugin Id string type - plain char* for plugin id
 * @ref ml_get_device_list device must in list of plugin ids
 */
typedef const char* ml_PluginId;

/** Path string type - plain char* for file paths */
typedef const char* ml_Path;

typedef enum {
    ML_LOG_LEVEL_TRACE, /* Trace messages */
    ML_LOG_LEVEL_DEBUG, /* Debug messages */
    ML_LOG_LEVEL_INFO,  /* Informational messages */
    ML_LOG_LEVEL_WARN,  /* Warning messages */
    ML_LOG_LEVEL_ERROR  /* Error messages */
} ml_LogLevel;

/** Logging callback function type */
typedef void (*ml_log_callback)(ml_LogLevel, const char*);

/** Token callback for streaming generation */
typedef bool (*ml_token_callback)(const char* token, void* user_data);

/** Input structure for saving KV cache */
typedef struct {
    ml_Path path; /** Path to save the KV cache */
} ml_KvCacheSaveInput;

/** Output structure for saving KV cache (empty for now) */
typedef struct {
    void* reserved; /** Reserved for future use, safe to set as NULL */
} ml_KvCacheSaveOutput;

/** Input structure for loading KV cache */
typedef struct {
    ml_Path path; /** Path to load the KV cache from */
} ml_KvCacheLoadInput;

/** Output structure for loading KV cache (empty for now) */
typedef struct {
    void* reserved; /** Reserved for future use, safe to set as NULL */
} ml_KvCacheLoadOutput;

/* ====================  Core Initialization  ================================ */

/**
 * @brief Initialize the ML C-Lib runtime, starting the life cycle of the library.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe.
 */
ML_API int32_t ml_init(void);

/** Plugin id create function type */
typedef ml_PluginId (*ml_plugin_id_func)();

/** Plugin instance create function type */
typedef void* (*ml_create_plugin_func)();

/**
 * @brief Register a custom plugin with the ML C-Lib runtime.
 *
 * @param plugin_id_func[in]: The pointer to plugin create_id function.
 * @param create_func[in]: The pointer to plugin create function.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Thread-safe.
 */
ML_API int32_t ml_register_plugin(ml_plugin_id_func plugin_id_func, ml_create_plugin_func create_func);

/**
 * @brief Deinitialize the ML C-Lib runtime, ending the life cycle of the library.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe.
 */
ML_API int32_t ml_deinit(void);

/**
 * @brief Set custom logging callback function, call before init
 *
 * @param callback[in]: The callback function to set.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Thread-safe
 */
ML_API int32_t ml_set_log(ml_log_callback callback);

/**
 * @brief Simple wrapper around free() to free memory allocated by ML library functions
 *
 * @param ptr[in]: The pointer to free.
 *
 * @thread_safety: Thread-safe if called for different pointers.
 */
ML_API void ml_free(void* ptr);

/**
 * @brief Get Library Version
 *
 * @param out_version[out]: Pointer to the library version.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Thread-safe.
 */
ML_API const char* ml_version(void);

/** Output structure containing the list of available plugins */
typedef struct {
    ml_PluginId* plugin_ids;   /**< Array of plugin IDs (UTF-8) (caller must free with ml_free) */
    int32_t      plugin_count; /**< Number of plugin IDs in the list */
} ml_GetPluginListOutput;

/**
 * @brief Query the list of available plugins.
 *
 * @param output[out] Pointer to plugin list and count. caller must free with `ml_free`.
 *
 * @return ml_ErrorCode ML_SUCCESS on success, negative value on failure.
 *
 * @thread_safety: Not thread-safe.
 *
 * @note The returned plugin_list TODO
 */
ML_API int32_t ml_get_plugin_list(ml_GetPluginListOutput* output);

/** Input structure for querying available devices for a plugin */
typedef struct {
    ml_PluginId plugin_id; /**< Plugin identifier */
} ml_GetDeviceListInput;

/** Output structure containing the list of available devices */
typedef struct {
    // example: Vulkan0
    const char** device_ids;   /**< Array of device IDs  (caller must free with ml_free when not null) */
    const char** device_names; /**< Array of device names  (caller must free with ml_free when not null) */
    int32_t      device_count; /**< Number of device names in the list */
} ml_GetDeviceListOutput;

/**
 * @brief Query the list of available devices for a given plugin.
 *
 * @param input[in]   Pointer to input structure specifying the plugin.
 * @param output[out] Pointer to output structure to receive device list and count.
 *
 * @return ml_ErrorCode ML_SUCCESS on success, negative value on failure.
 *
 * @thread_safety: Not thread-safe.
 *
 * @note The returned device_list TODO
 */
ML_API int32_t ml_get_device_list(const ml_GetDeviceListInput* input, ml_GetDeviceListOutput* output);

/* ====================  Data Structures  ==================================== */

/** Profile data structure for performance metrics */
typedef struct {
    int64_t ttft;        /* Time to first token (us) */
    int64_t prompt_time; /* Prompt processing time (us) */
    int64_t decode_time; /* Token generation time (us) */

    int64_t prompt_tokens;    /* Number of prompt tokens */
    int64_t generated_tokens; /* Number of generated tokens */
    int64_t audio_duration;   /* Audio duration (us) */

    double prefill_speed;    /* Prefill speed (tokens/sec) */
    double decoding_speed;   /* Decoding speed (tokens/sec) */
    double real_time_factor; /* Real-Time Factor(RTF) (1.0 = real-time, >1.0 = faster, <1.0 = slower) */

    const char* stop_reason; /* Stop reason: "eos", "length", "user", "stop_sequence" */
} ml_ProfileData;

/* ========================================================================== */
/*                              LANGUAGE MODELS (LLM)                          */
/* ========================================================================== */

/** Text generation sampling parameters */
typedef struct {
    float       temperature;        /* Sampling temperature (0.0-2.0) */
    float       top_p;              /* Nucleus sampling parameter (0.0-1.0) */
    int32_t     top_k;              /* Top-k sampling parameter */
    float       min_p;              /* Minimum probability for nucleus sampling */
    float       repetition_penalty; /* Penalty for repeated tokens */
    float       presence_penalty;   /* Penalty for token presence */
    float       frequency_penalty;  /* Penalty for token frequency */
    int32_t     seed;               /* Random seed (-1 for random) */
    ml_Path     grammar_path;       /* Optional grammar file path */
    const char* grammar_string;     /* Optional grammar string (BNF-like format) */
    bool        enable_json;        /* Enable JSON grammar */
} ml_SamplerConfig;

/** LLM / VLM generation configuration (IMPROVED: support multiple images and audios) */
typedef struct {
    int32_t           max_tokens;     /* Maximum tokens to generate */
    const char**      stop;           /* Array of stop sequences */
    int32_t           stop_count;     /* Number of stop sequences */
    int32_t           n_past;         /* Number of past tokens to consider */
    ml_SamplerConfig* sampler_config; /* Advanced sampling config */
    // --- Improved multimodal support ---
    ml_Path* image_paths;      /* Array of image paths for VLM (NULL if none) */
    int32_t  image_count;      /* Number of images */
    int32_t  image_max_length; /* Maximum length of the image */
    ml_Path* audio_paths;      /* Array of audio paths for VLM (NULL if none) */
    int32_t  audio_count;      /* Number of audios */
} ml_GenerationConfig;

/** LLM / VLM model configuration */
typedef struct {
    int32_t n_ctx;            // text context, 0 = from model
    int32_t n_threads;        // number of threads to use for generation
    int32_t n_threads_batch;  // number of threads to use for batch processing
    int32_t n_batch;          // logical maximum batch size that can be submitted to llama_decode
    int32_t n_ubatch;         // physical maximum batch size
    int32_t n_seq_max;        // max number of sequences (i.e. distinct states for recurrent models)
    int32_t n_gpu_layers;     // number of layers to offload to GPU, 0 = all layers on CPU

    // TODO: consider removing the following fields from ModelConfig, or move to another struct
    ml_Path     chat_template_path;     // path to chat template file, optional
    const char* chat_template_content;  // content of chat template file, optional
    const char* system_prompt;          // system prompt for chat template, optional
    bool        enable_sampling;        // DEPRECATED, use enable_json in ml_SamplerConfig
    const char* grammar_str;            // grammar string
    int32_t     max_tokens;             // max tokens to generate
    bool        enable_thinking;        // enable thinking mode for Qwen models
    bool        verbose;                // verbose logging
    // For QNN
    ml_Path qnn_model_folder_path;  // path to QNN model folder, default same as model_path
    ml_Path qnn_lib_folder_path;    // path to QNN library folder, default same as model_path
} ml_ModelConfig;

/* ====================  LLM Handle  ======================================== */
typedef struct ml_LLM ml_LLM; /* Opaque LLM handle */

/* ====================  Lifecycle Management  ============================== */
typedef struct {
    const char*    model_name;     /** Name of the model */
    ml_Path        model_path;     /** Path to the model file */
    ml_Path        tokenizer_path; /** Path to the tokenizer file */
    ml_ModelConfig config;         /** Model configuration */
    ml_PluginId    plugin_id;      /** plugin to use for the model */
    const char*    device_id;      /** device to use for the model, NULL for default device */
    const char*    license_id; /** licence id for loading NPU models, must be provided upon the first use of the license
                                  key. null terminated string */
    const char* license_key;   /** licence key for loading NPU models, null terminated string */
} ml_LlmCreateInput;

/**
 * @brief Create and initialize an LLM instance from model files
 *
 * @param input[in]: Input parameters for the LLM creation
 * @param out_handle[out]: Pointer to the LLM handle. Must be freed with ml_llm_destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_llm_create(const ml_LlmCreateInput* input, ml_LLM** out_handle);

/**
 * @brief Destroy LLM instance and free associated resources
 *
 * @param handle[in]: The LLM handle to destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_llm_destroy(ml_LLM* handle);

/**
 * @brief Reset LLM internal state (clear KV cache, reset sampling)
 *
 * @param handle[in]: The LLM handle to reset.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_llm_reset(ml_LLM* handle);

/* ====================  KV-Cache Management  ============================== */

/**
 * @brief Save current KV cache state to file
 *
 * @param handle[in]: LLM handle
 * @param input[in]: Input parameters for saving KV cache
 * @param output[out]: Reserved struct for future use, safe to pass nullptr now
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 */
ML_API int32_t ml_llm_save_kv_cache(ml_LLM* handle, const ml_KvCacheSaveInput* input, ml_KvCacheSaveOutput* output);

/**
 * @brief Load KV cache state from file
 *
 * @param handle[in]: LLM handle
 * @param input[in]: Input parameters for loading KV cache
 * @param output[out]: Reserved struct for future use, safe to pass nullptr now
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 */
ML_API int32_t ml_llm_load_kv_cache(ml_LLM* handle, const ml_KvCacheLoadInput* input, ml_KvCacheLoadOutput* output);

/* ====================  Chat Template ================================== */

/** Chat message structure */
typedef struct {
    const char* role;    /* Message role: "user", "assistant", "system" */
    const char* content; /* Message content in UTF-8 */
} ml_LlmChatMessage;

/** Input structure for applying chat template */
typedef struct {
    ml_LlmChatMessage* messages;              /** Array of chat messages */
    int32_t            message_count;         /** Number of messages */
    const char*        tools;                 /** Tool JSON string (optional, can be NULL) */
    bool               enable_thinking;       /** Enable thinking */
    bool               add_generation_prompt; /** Add generation prompt */
} ml_LlmApplyChatTemplateInput;

/** Output structure for applying chat template */
typedef struct {
    char* formatted_text; /** Formatted chat text (caller must free with ml_free) */
} ml_LlmApplyChatTemplateOutput;

/**
 * @brief Apply chat template to messages
 *
 * @param handle[in]: LLM handle
 * @param input[in]: Input parameters for applying chat template
 * @param output[out]: Output data containing the formatted text
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 */
ML_API int32_t ml_llm_apply_chat_template(
    ml_LLM* handle, const ml_LlmApplyChatTemplateInput* input, ml_LlmApplyChatTemplateOutput* output);

/* ====================  Streaming Generation  ============================= */

/** Input structure for streaming text generation */
typedef struct {
    const char*                prompt_utf8; /** The full chat history as UTF-8 string */
    const ml_GenerationConfig* config;      /** Generation configuration (optional, can be nullptr) */
    ml_token_callback          on_token;    /** Token callback function for streaming */
    void*                      user_data;   /** User data passed to callback (optional, can be nullptr) */
} ml_LlmGenerateInput;

/** Output structure for streaming text generation */
typedef struct {
    char*          full_text;    /** Complete generated text (caller must free with ml_free) */
    ml_ProfileData profile_data; /** Profiling data for the generation */
} ml_LlmGenerateOutput;

/**
 * @brief Generate text with streaming token callback
 *
 * @param handle[in]: LLM handle
 * @param input[in]: Input parameters for streaming generation
 * @param output[out]: Output containing the complete generated text
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 */
ML_API int32_t ml_llm_generate(ml_LLM* handle, const ml_LlmGenerateInput* input, ml_LlmGenerateOutput* output);

/* ========================================================================== */
/*                              MULTIMODAL MODELS (VLM)                          */
/* ========================================================================== */

typedef struct {
    const char* type;  // "text", "image", "audio", … (null-terminated UTF-8)
    const char* text;  // payload: the actual text, URL, or special token
} ml_VlmContent;

/* ---------- Message ---------- */
typedef struct {
    const char*    role;           // "user", "assistant", "system", …
    ml_VlmContent* contents;       // dynamically-allocated array (may be NULL)
    int64_t        content_count;  // number of elements in `contents`
} ml_VlmChatMessage;

typedef struct ml_VLM ml_VLM; /* Opaque VLM handle */

/* ====================  Lifecycle Management  ============================== */

typedef struct {
    const char*    model_name;     /** Name of the model */
    ml_Path        model_path;     /** Path to the model file */
    ml_Path        mmproj_path;    /** Path to the mmproj file */
    ml_ModelConfig config;         /** Model configuration */
    ml_PluginId    plugin_id;      /** Plugin to use for the model */
    const char*    device_id;      /** device to use for the model */
    ml_Path        tokenizer_path; /** Path to the tokenizer file */
    const char*    license_id; /** licence id for loading NPU models, must be provided upon the first use of the license
                                  key. null terminated string */
    const char* license_key;   /** licence key for loading NPU models, null terminated string */
} ml_VlmCreateInput;

/**
 * @brief Create and initialize a VLM instance from model files
 *
 * @param input[in]: Input parameters for the VLM creation
 * @param out_handle[out]: Pointer to the VLM handle. Must be freed with ml_vlm_destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_vlm_create(const ml_VlmCreateInput* input, ml_VLM** out_handle);

/**
 * @brief Destroy VLM instance and free associated resources
 *
 * @param handle[in]: The VLM handle to destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_vlm_destroy(ml_VLM* handle);

/**
 * @brief Reset VLM internal state (clear KV cache, reset sampling)
 *
 * @param handle[in]: The VLM handle to reset.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_vlm_reset(ml_VLM* handle);

/* ====================  Text Generation  ================================== */

/** Input structure for applying VLM chat template */
typedef struct {
    ml_VlmChatMessage* messages;        /** Array of chat messages */
    int32_t            message_count;   /** Number of messages */
    const char*        tools;           /** Tool JSON string (optional, can be NULL) */
    bool               enable_thinking; /** Enable thinking */

    // deepseek-ocr
    bool grounding; /** Enable grounding (Add grounding token) */
} ml_VlmApplyChatTemplateInput;

/** Output structure for applying VLM chat template */
typedef struct {
    char* formatted_text; /** Formatted chat text (caller must free with ml_free) */
} ml_VlmApplyChatTemplateOutput;

/**
 * @brief Apply chat template to messages
 *
 * @param handle[in]: VLM handle
 * @param input[in]: Input parameters for applying chat template
 * @param output[out]: Output data containing the formatted text
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 */
ML_API int32_t ml_vlm_apply_chat_template(
    ml_VLM* handle, const ml_VlmApplyChatTemplateInput* input, ml_VlmApplyChatTemplateOutput* output);

/* ====================  Streaming Generation  ============================= */

/** Input structure for VLM streaming text generation */
typedef struct {
    const char*                prompt_utf8; /** The full chat history as UTF-8 string */
    const ml_GenerationConfig* config;      /** Generation configuration (optional, can be nullptr) */
    ml_token_callback          on_token;    /** Token callback function for streaming */
    void*                      user_data;   /** User data passed to callback (optional, can be nullptr) */
} ml_VlmGenerateInput;

/** Output structure for VLM streaming text generation */
typedef struct {
    char*          full_text;    /** Complete generated text (caller must free with ml_free) */
    ml_ProfileData profile_data; /** Profiling data for the generation */
} ml_VlmGenerateOutput;

/**
 * @brief Generate text with streaming token callback
 *
 * @param handle[in]: VLM handle
 * @param input[in]: Input parameters for streaming generation
 * @param output[out]: Output containing the complete generated text
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 */
ML_API int32_t ml_vlm_generate(ml_VLM* handle, const ml_VlmGenerateInput* input, ml_VlmGenerateOutput* output);

/* ========================================================================== */
/*                              EMBEDDING MODELS                               */
/* ========================================================================== */

/** Embedding generation configuration */
typedef struct {
    int32_t     batch_size;       /* Processing batch size */
    bool        normalize;        /* Whether to normalize embeddings */
    const char* normalize_method; /* Normalization: "l2", "mean", "none" */
} ml_EmbeddingConfig;

typedef struct ml_Embedder ml_Embedder; /* Opaque embedder handle */

/* ====================  Lifecycle Management  ============================== */

/** Input structure for creating an embedder */
typedef struct {
    const char*    model_name;     /** Name of the model */
    ml_Path        model_path;     /** Path to the model file */
    ml_Path        tokenizer_path; /** Path to the tokenizer file */
    ml_ModelConfig config;         /** Model configuration */
    ml_PluginId    plugin_id;      /** Plugin to use for the model */
    const char*    device_id;      /** device to use for the model */
} ml_EmbedderCreateInput;

/**
 * @brief Create and initialize an embedder instance from model files
 *
 * @param input[in]: Input parameters for the embedder creation
 * @param out_handle[out]: Pointer to the embedder handle. Must be freed with ml_embedder_destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_embedder_create(const ml_EmbedderCreateInput* input, ml_Embedder** out_handle);

/**
 * @brief Destroy embedder instance and free associated resources
 *
 * @param handle[in]: The embedder handle to destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_embedder_destroy(ml_Embedder* handle);

/* ====================  Embedding Generation  ============================= */

/** Input structure for embedding generation */
typedef struct {
    const char**              texts;        /** Array of input texts in UTF-8 encoding */
    int32_t                   text_count;   /** Number of input texts */
    const ml_EmbeddingConfig* config;       /** Embedding configuration (optional, can be nullptr) */
    const int32_t**           input_ids_2d; /** 2D array of already tokenized raw input ids.
                                             * When passed in, texts will be ignored.
                                             * NOTE: this is supported for cpu_gpu backend only.
                                             * Passing this param to other backends will be ignored */
    const int32_t* input_ids_row_lengths;   /** Array containing the length of each row in input_ids_2d */
    int32_t        input_ids_row_count;     /** Number of rows in input_ids_2d array */
    const char*    task_type;               /** Task type: "query", "document" */

    /* ====================  Image inputs (for multimodal embedders)  ============================= */

    ml_Path* image_paths; /** Array of image file paths to embed (UTF-8).
                           *  When non-NULL and image_count > 0, the call is treated as
                           *  an image embedding request.
                           *
                           *  Each path should point to an image file in a supported format
                           *  for the underlying plugin/model (e.g. PNG/JPEG).
                           *
                           *  NOTE: Text/token inputs and image inputs are mutually exclusive.
                           *  Providing both will result in ML_ERROR_COMMON_INVALID_INPUT. */
    int32_t image_count;  /** Number of images in image_paths. */
} ml_EmbedderEmbedInput;

/** Output structure for embedding generation */
typedef struct {
    float*         embeddings;      /** Output embeddings array (caller must free with ml_free) */
    int32_t        embedding_count; /** Number of embeddings returned */
    ml_ProfileData profile_data;    /** Profiling data for the embedding generation */
} ml_EmbedderEmbedOutput;

/**
 * @brief Generate embeddings for input texts
 *
 * @param handle[in]: Embedder handle
 * @param input[in]: Input parameters for embedding generation
 * @param output[out]: Output data containing the generated embeddings
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_embedder_embed(
    ml_Embedder* handle, const ml_EmbedderEmbedInput* input, ml_EmbedderEmbedOutput* output);

/* ====================  Model Information  ================================ */

/** Output structure for getting embedding dimension */
typedef struct {
    int32_t dimension; /** The embedding dimension size */
} ml_EmbedderDimOutput;

/**
 * @brief Get embedding dimension from the model
 *
 * @param handle[in]: Embedder handle
 * @param output[out]: Output data containing the embedding dimension
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Thread-safe
 */
ML_API int32_t ml_embedder_embedding_dim(const ml_Embedder* handle, ml_EmbedderDimOutput* output);

/* ========================================================================== */
/*                              RERANKING MODELS                               */
/* ========================================================================== */

/** Reranking configuration */
typedef struct {
    int32_t     batch_size;       /* Processing batch size */
    bool        normalize;        /* Whether to normalize scores */
    const char* normalize_method; /* Normalization: "softmax", "min-max", "none" */
} ml_RerankConfig;

typedef struct ml_Reranker ml_Reranker; /* Opaque reranker handle */

/* ====================  Lifecycle Management  ============================== */

/** Input structure for creating a reranker */
typedef struct {
    const char*    model_name;     /** Name of the model */
    ml_Path        model_path;     /** Path to the model file */
    ml_Path        tokenizer_path; /** Path to the tokenizer file */
    ml_ModelConfig config;         /** Model configuration */
    ml_PluginId    plugin_id;      /** Plugin to use for the model */
    const char*    device_id;      /** device to use for the model */
} ml_RerankerCreateInput;

/**
 * @brief Create and initialize a reranker instance from model files
 *
 * @param input[in]: Input parameters for the reranker creation
 * @param out_handle[out]: Pointer to the reranker handle. Must be freed with ml_reranker_destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_reranker_create(const ml_RerankerCreateInput* input, ml_Reranker** out_handle);

/**
 * @brief Destroy reranker instance and free associated resources
 *
 * @param handle[in]: The reranker handle to destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_reranker_destroy(ml_Reranker* handle);

/* ====================  Reranking  ========================================= */

/** Input structure for reranking operation */
typedef struct {
    const char*            query;           /** Query text in UTF-8 encoding */
    const char**           documents;       /** Array of document texts in UTF-8 encoding */
    int32_t                documents_count; /** Number of documents */
    const ml_RerankConfig* config;          /** Reranking configuration (optional, can be nullptr) */
} ml_RerankerRerankInput;

/** Output structure for reranking operation */
typedef struct {
    float*         scores;       /** Output ranking scores array (caller must free with ml_free) */
    int32_t        score_count;  /** Number of scores returned */
    ml_ProfileData profile_data; /** Profiling data for the reranking operation */
} ml_RerankerRerankOutput;

/**
 * @brief Rerank documents against a query
 *
 * @param handle[in]: Reranker handle
 * @param input[in]: Input parameters for reranking operation
 * @param output[out]: Output data containing the ranking scores
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_reranker_rerank(
    ml_Reranker* handle, const ml_RerankerRerankInput* input, ml_RerankerRerankOutput* output);

/* ========================================================================== */
/*                              IMAGE GENERATION                               */
/* ========================================================================== */

/* ====================  Configuration Structures  =========================== */

/** Image generation sampling parameters */
typedef struct {
    const char* method;         /* Sampling method: "ddim", "ddpm", etc. */
    int32_t     steps;          /* Number of denoising steps */
    float       guidance_scale; /* Classifier-free guidance scale */
    float       eta;            /* DDIM eta parameter */
    int32_t     seed;           /* Random seed (-1 for random) */
} ml_ImageSamplerConfig;

/** Diffusion scheduler configuration */
typedef struct {
    const char* type;                /* Scheduler type: "ddim", etc. */
    int32_t     num_train_timesteps; /* Training timesteps */
    int32_t     steps_offset;        /* An offset added to the inference steps */
    float       beta_start;          /* Beta schedule start */
    float       beta_end;            /* Beta schedule end */
    const char* beta_schedule;       /* Beta schedule: "scaled_linear" */
    const char* prediction_type;     /* Prediction type: "epsilon", "v_prediction" */
    const char* timestep_type;       /* Timestep type: "discrete", "continuous" */
    const char* timestep_spacing;    /* Timestep spacing: "linspace", "leading", "trailing" */
    const char* interpolation_type;  /* Interpolation type: "linear", "exponential" */
    ml_Path     config_path;         /* Optional config file path */
} ml_SchedulerConfig;

/** Image generation configuration */
typedef struct {
    const char**          prompts;               /* Required positive prompts */
    int32_t               prompt_count;          /* Number of positive prompts */
    const char**          negative_prompts;      /* Optional negative prompts */
    int32_t               negative_prompt_count; /* Number of negative prompts */
    int32_t               height;                /* Output image height */
    int32_t               width;                 /* Output image width */
    ml_ImageSamplerConfig sampler_config;        /* Sampling parameters */
    ml_SchedulerConfig    scheduler_config;      /* Scheduler configuration */
    float                 strength;              /* Denoising strength for img2img */
} ml_ImageGenerationConfig;

typedef struct ml_ImageGen ml_ImageGen; /* Opaque image generator handle */

/* ====================  Lifecycle Management  ============================== */

/** Input structure for creating an image generator */
typedef struct {
    const char*    model_name;            /** Name of the model */
    ml_Path        model_path;            /** Path to the model file */
    ml_ModelConfig config;                /** Model configuration */
    ml_Path        scheduler_config_path; /** Path to the scheduler config file */
    ml_PluginId    plugin_id;             /** Plugin to use for the model */
    const char*    device_id;             /** Device to use for the model, NULL for default device */
} ml_ImageGenCreateInput;

/**
 * @brief Create and initialize an image generator instance
 *
 * @param input[in]: Input parameters for the image generator creation
 * @param out_handle[out]: Pointer to the image generator handle. Must be freed with ml_imagegen_destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_imagegen_create(const ml_ImageGenCreateInput* input, ml_ImageGen** out_handle);

/**
 * @brief Destroy image generator instance and free associated resources
 *
 * @param handle[in]: The image generator handle to destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_imagegen_destroy(ml_ImageGen* handle);

/* ====================  Image Generation  ================================== */

/** Input structure for text-to-image generation */
typedef struct {
    const char*                     prompt_utf8; /** Text prompt in UTF-8 encoding */
    const ml_ImageGenerationConfig* config;      /** Image generation configuration */
    ml_Path                         output_path; /** Optional output file path (NULL for auto-generated) */
} ml_ImageGenTxt2ImgInput;

/** Input structure for image-to-image generation */
typedef struct {
    ml_Path                         init_image_path; /** Path to initial image file for img2img */
    const char*                     prompt_utf8;     /** Text prompt in UTF-8 encoding */
    const ml_ImageGenerationConfig* config;          /** Image generation configuration */
    ml_Path                         output_path;     /** Optional output file path (NULL for auto-generated) */
} ml_ImageGenImg2ImgInput;

/** Output structure for image generation */
typedef struct {
    ml_Path output_image_path; /** Path where the generated image will be saved (caller must free with ml_free) */
} ml_ImageGenOutput;

/**
 * @brief Generate image from text prompt and save to filesystem
 *
 * @param handle[in]: Image generator handle
 * @param input[in]: Input parameters for text-to-image generation
 * @param output[out]: Output data containing the path where the generated image is saved
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_imagegen_txt2img(
    ml_ImageGen* handle, const ml_ImageGenTxt2ImgInput* input, ml_ImageGenOutput* output);

/**
 * @brief Generate image from initial image file and prompt, save to filesystem
 *
 * @param handle[in]: Image generator handle
 * @param input[in]: Input parameters for image-to-image generation (includes initial image path)
 * @param output[out]: Output data containing the path where the generated image is saved
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_imagegen_img2img(
    ml_ImageGen* handle, const ml_ImageGenImg2ImgInput* input, ml_ImageGenOutput* output);

/* ========================================================================== */
/*                              SPEECH RECOGNITION (ASR)                       */
/* ========================================================================== */

/* ====================  Configuration Structures  =========================== */

/** ASR processing configuration */
typedef struct {
    const char* timestamps; /* Timestamp mode: "none", "segment", "word" */
    int32_t     beam_size;  /* Beam search size */
    bool        stream;     /* Enable streaming mode */
} ml_ASRConfig;

/** ASR transcription result */
typedef struct {
    char*   transcript;        /* Transcribed text (UTF-8, caller must free with ml_free) */
    float*  confidence_scores; /* Confidence scores for each unit (caller must free with ml_free) */
    int32_t confidence_count;  /* Number of confidence scores */
    float*  timestamps;        /* Timestamp pairs: [start, end] for each unit (caller must free with ml_free) */
    int32_t timestamp_count;   /* Number of timestamp pairs */
} ml_ASRResult;

typedef struct ml_ASR ml_ASR; /* Opaque ASR handle */

/* ====================  Lifecycle Management  ============================== */

/** Input structure for creating an ASR instance */
typedef struct {
    const char*    model_name;     /** Name of the model */
    ml_Path        model_path;     /** Path to the model file */
    ml_Path        tokenizer_path; /** Path to the tokenizer file (may be NULL) */
    ml_ModelConfig config;         /** Model configuration */
    const char*    language;       /** Language code (ISO 639-1 or NULL) */
    ml_PluginId    plugin_id;      /** Plugin to use for the model */
    const char*    device_id;      /** Device to use for the model, NULL for default device */
    const char*    license_id; /** licence id for loading NPU models, must be provided upon the first use of the license
                              key. null terminated string */
    const char* license_key;   /** licence key for loading NPU models, null terminated string */
} ml_AsrCreateInput;

/**
 * @brief Create and initialize an ASR instance with language support
 *
 * @param input[in]: Input parameters for the ASR creation
 * @param out_handle[out]: Pointer to the ASR handle. Must be freed with ml_asr_destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_asr_create(const ml_AsrCreateInput* input, ml_ASR** out_handle);

/**
 * @brief Destroy ASR instance and free associated resources
 *
 * @param handle[in]: The ASR handle to destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_asr_destroy(ml_ASR* handle);

/* ====================  Transcription  ===================================== */

/** Input structure for ASR transcription */
typedef struct {
    ml_Path             audio_path; /** Path to audio file */
    const char*         language;   /** Language code (ISO 639-1 or NULL for auto-detect) */
    const ml_ASRConfig* config;     /** ASR configuration (optional, can be nullptr) */
} ml_AsrTranscribeInput;

/** Output structure for ASR transcription */
typedef struct {
    ml_ASRResult   result;       /** Transcription result (caller must free with ml_free for text fields) */
    ml_ProfileData profile_data; /** Profiling data for the transcription operation */
} ml_AsrTranscribeOutput;

/**
 * @brief Transcribe audio file to text with specified language
 *
 * @param handle[in]: ASR handle
 * @param input[in]: Input parameters for transcription (includes audio file path and language)
 * @param output[out]: Output data containing the transcription result
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_asr_transcribe(ml_ASR* handle, const ml_AsrTranscribeInput* input, ml_AsrTranscribeOutput* output);

/* ====================  Language Management  ============================== */

/** Input structure for getting supported languages */
typedef struct {
    void* reserved; /** Reserved for future use, safe to set as NULL */
} ml_AsrListSupportedLanguagesInput;

/** Output structure for getting supported languages */
typedef struct {
    const char** language_codes; /** Array of supported language codes (caller must free with ml_free) */
    int32_t      language_count; /** Number of supported languages */
} ml_AsrListSupportedLanguagesOutput;

/**
 * @brief Get list of supported languages for ASR model
 *
 * @param handle[in]: ASR handle
 * @param input[in]: Input parameters for language list query
 * @param output[out]: Output data containing the supported languages array and count
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Thread-safe
 */
ML_API int32_t ml_asr_list_supported_languages(
    const ml_ASR* handle, const ml_AsrListSupportedLanguagesInput* input, ml_AsrListSupportedLanguagesOutput* output);

/* ========================================================================== */
/*                              ASR STREAMING                                  */
/* ========================================================================== */

/* ====================  Streaming Types & Callbacks  ====================== */

/** Callback for streaming transcription updates */
typedef void (*ml_asr_transcription_callback)(const char* text, void* user_data);

/** ASR streaming configuration */
typedef struct {
    float       chunk_duration;   /* Duration in seconds for each chunk (default: 4.0) */
    float       overlap_duration; /* Overlap between chunks in seconds (default: 3.0) */
    int32_t     sample_rate;      /* Audio sample rate (default: 16000) */
    int32_t     max_queue_size;   /* Maximum chunks in processing queue (default: 10) */
    int32_t     buffer_size;      /* Audio buffer size for input (default: 512) */
    const char* timestamps;       /* Timestamp mode: "none", "segment", "word" */
    int32_t     beam_size;        /* Beam search size */
} ml_ASRStreamConfig;

/* ====================  Streaming Operations  ============================== */

/** Input structure for beginning ASR streaming */
typedef struct {
    const ml_ASRStreamConfig*     stream_config;    /** Streaming configuration (optional) */
    const char*                   language;         /** Language code (optional) */
    ml_asr_transcription_callback on_transcription; /** Required: transcription updates */
    void*                         user_data;        /** User data passed to callbacks */
} ml_AsrStreamBeginInput;

/** Output structure for streaming begin (minimal) */
typedef struct {
    void* reserved; /** Reserved for future use */
} ml_AsrStreamBeginOutput;

/**
 * @brief Begin streaming ASR with specified callbacks
 *
 * @param handle[in]: ASR handle
 * @param input[in]: Streaming callbacks configuration
 * @param output[out]: Output structure (reserved for future use)
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_asr_stream_begin(
    ml_ASR* handle, const ml_AsrStreamBeginInput* input, ml_AsrStreamBeginOutput* output);

/** Input structure for processing audio data */
typedef struct {
    const float* audio_data; /** Audio samples (float32) */
    int32_t      length;     /** Number of samples */
} ml_AsrStreamPushAudioInput;

/**
 * @brief Push audio data to streaming ASR for processing
 *
 * @param handle[in]: ASR handle
 * @param input[in]: Audio data to process
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_asr_stream_push_audio(ml_ASR* handle, const ml_AsrStreamPushAudioInput* input);

/** Input structure for stopping streaming */
typedef struct {
    bool graceful; /** If true, processes remaining audio before stopping; if false, stops immediately */
} ml_AsrStreamStopInput;

/**
 * @brief Stop streaming ASR
 *
 * @param handle[in]: ASR handle
 * @param input[in]: Stop configuration (graceful vs immediate)
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_asr_stream_stop(ml_ASR* handle, const ml_AsrStreamStopInput* input);

/* ========================================================================== */
/*                              TEXT-TO-SPEECH (TTS)                         */
/* ========================================================================== */

/* ====================  Configuration Structures  =========================== */

/** TTS synthesis configuration */
typedef struct {
    const char* voice;       /* Voice identifier */
    float       speed;       /* Speech speed (1.0 = normal) */
    int32_t     seed;        /* Random seed (-1 for random) */
    int32_t     sample_rate; /* Output sample rate in Hz */
} ml_TTSConfig;

/** TTS sampling parameters */
typedef struct {
    float temperature;  /* Sampling temperature */
    float noise_scale;  /* Noise scale for voice variation */
    float length_scale; /* Length scale for speech duration */
} ml_TTSSamplerConfig;

/** TTS synthesis result */
typedef struct {
    ml_Path audio_path;       /* Path where the synthesized audio is saved (caller must free with ml_free) */
    float   duration_seconds; /* Audio duration in seconds */
    int32_t sample_rate;      /* Audio sample rate in Hz */
    int32_t channels;         /* Number of audio channels (default: 1) */
    int32_t num_samples;      /* Number of audio samples */
} ml_TTSResult;

typedef struct ml_TTS ml_TTS; /* Opaque TTS handle */

/* ====================  Lifecycle Management  ============================== */

/** Input structure for creating a TTS instance */
typedef struct {
    const char*    model_name;   /** Name of the model */
    ml_Path        model_path;   /** Path to the TTS model file */
    ml_ModelConfig config;       /** Model configuration */
    ml_Path        vocoder_path; /** Path to the vocoder file */
    ml_PluginId    plugin_id;    /** Plugin to use for the model */
    const char*    device_id;    /** Device to use for the model, NULL for default device */
} ml_TtsCreateInput;

/**
 * @brief Create and initialize a TTS instance with model and vocoder
 *
 * @param input[in]: Input parameters for the TTS creation
 * @param out_handle[out]: Pointer to the TTS handle. Must be freed with ml_tts_destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_tts_create(const ml_TtsCreateInput* input, ml_TTS** out_handle);

/**
 * @brief Destroy TTS instance and free associated resources
 *
 * @param handle[in]: The TTS handle to destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_tts_destroy(ml_TTS* handle);

/* ====================  Speech Synthesis  ================================== */

/** Input structure for TTS synthesis */
typedef struct {
    const char*         text_utf8;   /** Text to synthesize in UTF-8 encoding */
    const ml_TTSConfig* config;      /** TTS configuration (optional, can be nullptr) */
    ml_Path             output_path; /** Optional output file path (NULL for auto-generated) */
} ml_TtsSynthesizeInput;

/** Output structure for TTS synthesis */
typedef struct {
    ml_TTSResult   result;       /** Synthesis result with audio saved to filesystem */
    ml_ProfileData profile_data; /** Profiling data for the synthesis operation */
} ml_TtsSynthesizeOutput;

/**
 * @brief Synthesize speech from text and save to filesystem
 *
 * @param handle[in]: TTS handle
 * @param input[in]: Input parameters for speech synthesis
 * @param output[out]: Output data containing the path where synthesized audio is saved
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_tts_synthesize(ml_TTS* handle, const ml_TtsSynthesizeInput* input, ml_TtsSynthesizeOutput* output);

/* ====================  Voice Management  ================================== */

/** Input structure for getting available voices */
typedef struct {
    void* reserved; /** Reserved for future use, safe to set as NULL */
} ml_TtsListAvailableVoicesInput;

/** Output structure for getting available voices */
typedef struct {
    const char** voice_ids;   /** Array of available voice identifiers (caller must free with ml_free) */
    int32_t      voice_count; /** Number of available voices */
} ml_TtsListAvailableVoicesOutput;

/**
 * @brief Get list of available voice identifiers
 *
 * @param handle[in]: TTS handle
 * @param input[in]: Input parameters for voice list query
 * @param output[out]: Output data containing the available voices array and count
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Thread-safe
 */
ML_API int32_t ml_tts_list_available_voices(
    const ml_TTS* handle, const ml_TtsListAvailableVoicesInput* input, ml_TtsListAvailableVoicesOutput* output);

/* ========================================================================== */
/*                              COMPUTER VISION (CV)                           */
/* ========================================================================== */

/* ====================  Generic CV Data Types  ============================= */
/** Generic bounding box structure */
typedef struct {
    float x;      /* X coordinate (normalized or pixel, depends on model) */
    float y;      /* Y coordinate (normalized or pixel, depends on model) */
    float width;  /* Width */
    float height; /* Height */
} ml_BoundingBox;

/** Generic detection/classification result */
typedef struct {
    ml_Path*       image_paths;   /* Output image paths (caller must free with ml_free) */
    int32_t        image_count;   /* Number of output images */
    int32_t        class_id;      /* Class ID (example: ConvNext) */
    float          confidence;    /* Confidence score [0.0-1.0] */
    ml_BoundingBox bbox;          /* Bounding box (example: YOLO) */
    const char*    text;          /* Text result (example: OCR) (caller must free with ml_free) */
    float*         embedding;     /* Feature embedding (example: CLIP embedding) (caller must free with ml_free) */
    int32_t        embedding_dim; /* Embedding dimension */
    float*         mask;          /* Mask (example: segmentation mask) (caller must free with ml_free) */
    int32_t        mask_h;        /* Mask height */
    int32_t        mask_w;        /* Mask width */
} ml_CVResult;

/** CV capabilities */
typedef enum {
    ML_CV_OCR            = 0, /* OCR */
    ML_CV_CLASSIFICATION = 1, /* Classification */
    ML_CV_SEGMENTATION   = 2, /* Segmentation */
    ML_CV_CUSTOM         = 3, /* Custom task */
} ml_CVCapabilities;

/** CV model preprocessing configuration */
typedef struct {
    ml_CVCapabilities capabilities;   /* Capabilities */
    ml_Path           det_model_path; /* detection model path */
    ml_Path           rec_model_path; /* recognition model path */
    ml_Path           char_dict_path; /* Character dictionary path */

    // QNN
    ml_Path qnn_model_folder_path; /* Model path */
    ml_Path qnn_lib_folder_path;   /* System library path */
} ml_CVModelConfig;

/* ====================  Generic CV Model  ================================== */

typedef struct ml_CV ml_CV; /* Opaque CV model handle */

typedef struct {
    const char*      model_name; /** Name of the model */
    ml_CVModelConfig config;     /** CV model configuration */
    ml_PluginId      plugin_id;  /** Plugin to use for the model */
    const char*      device_id;  /** device to use for the model */
    const char* license_id;  /** licence id for loading NPU models, must be provided upon the first use of the license
                                key. null terminated string */
    const char* license_key; /** licence key for loading NPU models, null terminated string */
} ml_CVCreateInput;

/* ====================  Lifecycle Management  ============================== */

/**
 * @brief Create and initialize a CV model
 *
 * @param input[in]: Input parameters for the CV model creation
 * @param out_handle[out]: Pointer to the CV model handle. Must be freed with ml_cv_destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 */
ML_API int32_t ml_cv_create(const ml_CVCreateInput* input, ml_CV** out_handle);

/**
 * @brief Destroy CV model instance and free associated resources
 *
 * @param handle[in]: The CV model handle to destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 */
ML_API int32_t ml_cv_destroy(ml_CV* handle);

/* ====================  Generic Inference  ================================= */
/** Input structure for CV inference */
typedef struct {
    const char* input_image_path; /* Input image path */
} ml_CVInferInput;

/** Output structure for CV inference */
typedef struct {
    ml_CVResult* results;      /* Array of CV results (caller must free with ml_free) */
    int32_t      result_count; /* Number of CV results */
} ml_CVInferOutput;

/**
 * @brief Perform inference on a single image
 *
 * @param handle[in]: The CV model handle
 * @param input[in]: Input parameters for the inference
 * @param output[out]: Output data containing the inference results
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 */
ML_API int32_t ml_cv_infer(const ml_CV* handle, const ml_CVInferInput* input, ml_CVInferOutput* output);

/* ========================================================================== */
/*                              SPEAKER DIARIZATION                            */
/* ========================================================================== */

/* ====================  Configuration Structures  =========================== */

/** Diarization processing configuration */
typedef struct {
    int32_t min_speakers; /* Minimum number of speakers (0 = auto-detect) */
    int32_t max_speakers; /* Maximum number of speakers (0 = no limit) */
} ml_DiarizeConfig;

/** Speech segment structure */
typedef struct {
    float start_time;    /* Segment start time in seconds */
    float end_time;      /* Segment end time in seconds */
    char* speaker_label; /* Speaker label (e.g., "SPEAKER_00") (caller must free with ml_free) */
} ml_DiarizeSpeechSegment;

typedef struct ml_Diarize ml_Diarize; /* Opaque diarization handle */

/* ====================  Lifecycle Management  ============================== */

/** Input structure for creating a diarization instance */
typedef struct {
    const char*    model_name; /** Name of the model */
    ml_Path        model_path; /** Path to the model folder */
    ml_ModelConfig config;     /** Model configuration */
    ml_PluginId    plugin_id;  /** Plugin to use for the model */
    const char*    device_id;  /** Device to use for the model, NULL for default device */
    const char*    license_id; /** Licence id for loading NPU models, must be provided upon the first use of the license
                                  key. null terminated string */
    const char* license_key;   /** Licence key for loading NPU models, null terminated string */
} ml_DiarizeCreateInput;

/**
 * @brief Create and initialize a diarization instance
 *
 * @param input[in]: Input parameters for the diarization instance creation
 * @param out_handle[out]: Pointer to the diarization handle. Must be freed with ml_diarize_destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_diarize_create(const ml_DiarizeCreateInput* input, ml_Diarize** out_handle);

/**
 * @brief Destroy diarization instance and free associated resources
 *
 * @param handle[in]: The diarization handle to destroy.
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_diarize_destroy(ml_Diarize* handle);

/* ====================  Diarization Inference  ================================ */

/** Input structure for diarization inference */
typedef struct {
    ml_Path                 audio_path; /** Path to audio file */
    const ml_DiarizeConfig* config;     /** Diarization configuration (optional, can be nullptr) */
} ml_DiarizeInferInput;

/** Output structure for diarization inference */
typedef struct {
    ml_DiarizeSpeechSegment* segments;      /** Array of speech segments (caller must free with ml_free) */
    int32_t                  segment_count; /** Number of segments */
    int32_t                  num_speakers;  /** Total unique speakers detected */
    float                    duration;      /** Total audio duration in seconds */
    ml_ProfileData           profile_data;  /** Profiling data for the diarization operation */
} ml_DiarizeInferOutput;

/**
 * @brief Perform speaker diarization on audio file
 *
 * Determines "who spoke when" in the audio recording, producing time-stamped segments
 * with speaker labels. Segments are time-ordered and non-overlapping.
 *
 * @param handle[in]: Diarization handle
 * @param input[in]: Input parameters for diarization (audio file path and optional configuration)
 * @param output[out]: Output data containing the diarization results
 *
 * @return ml_ErrorCode: ML_SUCCESS on success, negative on failure.
 *
 * @thread_safety: Not thread-safe
 */
ML_API int32_t ml_diarize_infer(ml_Diarize* handle, const ml_DiarizeInferInput* input, ml_DiarizeInferOutput* output);

#ifdef __cplusplus
} /* extern "C" */
#endif
#if defined(_WIN32)
#define PLUGIN_API __declspec(dllexport)
#else
#define PLUGIN_API __attribute__((visibility("default")))
#endif

#ifdef __cplusplus
extern "C" {
#endif

PLUGIN_API ml_PluginId llama_plugin_id();
PLUGIN_API void*       create_llama_plugin();

PLUGIN_API ml_PluginId ane_plugin_id();
PLUGIN_API void*       create_ane_plugin();

#ifdef __cplusplus
}
#endif
