/** @file dc_signal_yk.cpp — YK 信号注册/控制/异步执行 */
#include "dc_internal.h"

/**
 * @brief 创建 YK 遥控信号：计算 XXH128 hash，注册到 g_dc_yk，将 cb 加入 ctrl_cb 列表
 */
extern "C" int dc_signal_yk(const char *saddr, const char *desc, uint8_t data_type, uint8_t ctrl_type, void *p_data, dc_signal_change_cb_t cb, const char *module_id)
{
    if (!g_initialized || !saddr || !p_data || !module_id)
    {
        return DC_ERR_PARAM;
    }

    if (dc_core_find(saddr, g_dc_yk))
    {
        LOG_E("yk %s exists\n", saddr);

        return DC_ERR_EXISTS;
    }

    dc_signal_t sig = {};
    sig.hash = XXH3_128bits(saddr, strlen(saddr));
    strncpy(sig.saddr, saddr, DC_SADDR_MAX_LEN - 1);

    if (desc)
    {
        strncpy(sig.desc, desc, DC_DESC_MAX_LEN - 1);
    }

    sig.data_type = data_type;
    sig.ctrl_type = ctrl_type;
    sig.vec_p_data = (void **)malloc(sizeof(void *));
    sig.vec_p_data[0] = p_data;
    sig.vec_p_data_count = 1;

    if (cb)
    {
        strncpy(sig.cb_list[0].module_id, module_id, DC_MODULE_MAX_LEN - 1);
        sig.cb_list[0].ctrl_cb = cb;
        sig.cb_count = 1;
    }

    return dc_core_add(sig, g_dc_yk);
}

/**
 * @brief 链接已有 YK 信号：将 *p_data 指向信号的 vec_p_data[0]，可选添加 cb
 */
extern "C" int dc_signal_yk_link_with_callback(const char *saddr, void **p_data, dc_signal_change_cb_t cb, const char *module_id)
{
    if (!g_initialized || !saddr || !p_data || !module_id)
    {
        return DC_ERR_PARAM;
    }

    dc_signal_t *ps = dc_core_find(saddr, g_dc_yk);

    if (!ps)
    {
        return DC_ERR_NOTFOUND;
    }

    if (!ps->vec_p_data || !ps->vec_p_data[0])
    {
        return DC_ERR_PARAM;
    }

    *p_data = ps->vec_p_data[0];

    if (cb && ps->cb_count < DC_MAX_CALLBACKS)
    {
        strncpy(ps->cb_list[ps->cb_count].module_id, module_id, DC_MODULE_MAX_LEN - 1);
        ps->cb_list[ps->cb_count].ctrl_cb = cb;
        ps->cb_count++;
    }

    return DC_OK;
}

/**
 * @brief 同步遥控执行：ctrl 校验 → step 处理（SELECT 写暂存 / DIRECT 写数据）→ 遍历回调（跳过发起方 module_id）
 */
extern "C" int dc_signal_yk_set_status(const char *saddr, dc_ctrl_step_t step, dc_ctrl_t *ctrl, const void *p_data, const char *module_id)
{
    if (!g_initialized || !saddr || !ctrl || !p_data || !module_id)
    {
        return DC_ERR_PARAM;
    }

    dc_signal_t *ps = dc_core_find(saddr, g_dc_yk);

    if (!ps)
    {
        return DC_ERR_NOTFOUND;
    }

    int ret = dc_check_ctrl_valid(ps, step, ctrl, p_data);

    if (ret != DC_OK)
    {
        return ret;
    }

    if (step == DC_STEP_SELECT)
    {
        dc_util_val_copy(ctrl->p_data, p_data, ps->data_type);
    }
    else if (step == DC_STEP_DIRECT)
    {
        dc_util_val_copy(ps->vec_p_data[0], p_data, ps->data_type);
    }
    /* DC_STEP_CANCEL: no data operation */

    ctrl->step = step;

    for (int i = 0; i < ps->cb_count; i++)
    {
        if (!ps->cb_list[i].ctrl_cb)
        {
            continue;
        }

        if (0 == strcmp(ps->cb_list[i].module_id, module_id))
        {
            continue;
        }

        ps->cb_list[i].ctrl_cb(ps->saddr, step, ps->data_type, 0, ps->vec_p_data[0]);
    }

    return DC_OK;
}

/**
 * @brief 发起遥控异步执行请求
 */
extern "C" int dc_yk_exec_async(const char *saddr, dc_ctrl_step_t step, const dc_ctrl_t *ctrl, const void *p_data, const char *module_id, dc_async_result_cb_t result_cb, void *user_arg, uint32_t timeout_ms, uint32_t *request_id)
{
    if (!g_initialized || !saddr || !ctrl || !p_data || !module_id)
    {
        return DC_ERR_PARAM;
    }

    uint32_t req_id = dc_async_enqueue(g_dc_yk, saddr, step, ctrl, p_data, 0, 0, module_id, result_cb, user_arg, timeout_ms);

    if (request_id)
    {
        *request_id = req_id;
    }

    return (req_id == 0) ? DC_ERR_FULL : DC_OK;
}

/**
 * @brief 模块 B 返回遥控异步执行结果
 */
extern "C" int dc_yk_set_result(uint32_t request_id, int result_code, const char *err_msg)
{
    return dc_async_set_result(request_id, result_code, err_msg);
}

/**
 * @brief 取消未完成的遥控异步请求
 */
extern "C" int dc_yk_cancel_async(uint32_t request_id)
{
    return dc_async_cancel(request_id);
}

/**
 * @brief 注册遥控异步执行回调（模块 B 调用）
 */
extern "C" int dc_yk_register_exec_cb(const char *saddr, dc_async_exec_cb_t exec_cb, void *module_ctx)
{
    if (!g_initialized || !saddr)
    {
        return DC_ERR_PARAM;
    }

    dc_signal_t *ps = dc_core_find(saddr, g_dc_yk);

    if (!ps)
    {
        return DC_ERR_NOTFOUND;
    }

    ps->exec_cb = exec_cb;
    ps->module_ctx = module_ctx;

    return DC_OK;
}

