/**
 * @file protocol_commands.c
 * @brief 上行协议命令构造与发送
 */

#include "protocol/protocol_commands.h"
#include "protocol/agent_protocol.h"
#include "engine_internal.h"
#include "connection/connection_manager.h"
#include "hal_log.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TAG "CMD"

/**
 * 发送一条已构造好的文本消息
 */
static int send_ws_text(engine_internal_ctx_t *ctx, const char *msg)
{
    if (!ctx || !ctx->ws_handle || !msg) {
        return -1;
    }
    return conn_mgr_send_text(ctx, msg);
}

/* ==========================================================================
 * 打断
 * ========================================================================== */

int protocol_send_break(engine_internal_ctx_t *ctx)
{
    return send_ws_text(ctx, AGENT_CMD_BREAK);
}

int protocol_send_break_begin(engine_internal_ctx_t *ctx, unsigned int delay_ms)
{
    char buf[64];
    snprintf(buf, sizeof(buf), "%s%u", AGENT_CMD_BREAK_BEGIN, delay_ms);
    BD_LOGI(TAG, "send [B]:[BEGIN]:%u", delay_ms);
    return send_ws_text(ctx, buf);
}

int protocol_send_break_end(engine_internal_ctx_t *ctx)
{
    return send_ws_text(ctx, AGENT_CMD_BREAK_END);
}

/* ==========================================================================
 * 文本输入
 * ========================================================================== */

int protocol_send_text(engine_internal_ctx_t *ctx, const char *text)
{
    if (!ctx || !text) {
        return -1;
    }

    size_t prefix_len = strlen(AGENT_CMD_TEXT);
    size_t text_len = strlen(text);
    size_t total = prefix_len + text_len + 1;

    /* 小消息用栈缓冲，大消息用堆 */
    char stack_buf[256];
    char *buf = stack_buf;
    if (total > sizeof(stack_buf)) {
        buf = (char *)malloc(total);
        if (!buf) {
            return -1;
        }
    }

    snprintf(buf, total, "%s%s", AGENT_CMD_TEXT, text);
    int ret = send_ws_text(ctx, buf);

    if (buf != stack_buf) {
        free(buf);
    }
    return ret;
}

int protocol_send_tts_direct(engine_internal_ctx_t *ctx, const char *text)
{
    if (!ctx || !text) {
        return -1;
    }

    size_t prefix_len = strlen(AGENT_CMD_TTS_DIRECT);
    size_t text_len = strlen(text);
    size_t total = prefix_len + text_len + 1;

    char stack_buf[256];
    char *buf = stack_buf;
    if (total > sizeof(stack_buf)) {
        buf = (char *)malloc(total);
        if (!buf) {
            return -1;
        }
    }

    snprintf(buf, total, "%s%s", AGENT_CMD_TTS_DIRECT, text);
    int ret = send_ws_text(ctx, buf);

    if (buf != stack_buf) {
        free(buf);
    }
    return ret;
}

/* ==========================================================================
 * 对话模式控制
 * ========================================================================== */

int protocol_send_asr_enable_realtime(engine_internal_ctx_t *ctx)
{
    BD_LOGI(TAG, "ASR enable realtime");
    return send_ws_text(ctx, AGENT_CMD_ASR_ENABLE_REALTIME);
}

int protocol_send_asr_disable_realtime(engine_internal_ctx_t *ctx)
{
    BD_LOGI(TAG, "ASR disable realtime");
    return send_ws_text(ctx, AGENT_CMD_ASR_DISABLE_REALTIME);
}

int protocol_send_asr_start_longtext(engine_internal_ctx_t *ctx)
{
    BD_LOGI(TAG, "ASR start longtext");
    return send_ws_text(ctx, AGENT_CMD_ASR_START_LONGTEXT);
}

int protocol_send_asr_stop_longtext(engine_internal_ctx_t *ctx)
{
    BD_LOGI(TAG, "ASR stop longtext");
    return send_ws_text(ctx, AGENT_CMD_ASR_STOP_LONGTEXT);
}

/* ==========================================================================
 * 自动打断控制
 * ========================================================================== */

int protocol_send_auto_int_enable(engine_internal_ctx_t *ctx)
{
    BD_LOGI(TAG, "auto interrupt ON");
    return send_ws_text(ctx, AGENT_CMD_AUTO_INT_TRUE);
}

int protocol_send_auto_int_disable(engine_internal_ctx_t *ctx)
{
    BD_LOGI(TAG, "auto interrupt OFF");
    return send_ws_text(ctx, AGENT_CMD_AUTO_INT_FALSE);
}

/* ==========================================================================
 * 设备信息 / SET 命令
 * ========================================================================== */

int protocol_send_device_info(engine_internal_ctx_t *ctx, const char *model,
                              const char *device_id, const char *user_id,
                              bool asr_text_ext)
{
    if (!ctx || !model || !device_id || !user_id || device_id[0] == '\0') {
        return -1;
    }

    char buf[256];
    snprintf(buf, sizeof(buf), AGENT_CMD_DEVICE_INFO_FMT,
             model, device_id, user_id, asr_text_ext ? "true" : "false");
    return send_ws_text(ctx, buf);
}

int protocol_send_update_system_prompt(engine_internal_ctx_t *ctx, const char *json_payload)
{
    if (!ctx || !json_payload) {
        return -1;
    }

    size_t prefix_len = strlen(AGENT_CMD_UPDATE_SYSTEM_PROMPT);
    size_t payload_len = strlen(json_payload);
    size_t total = prefix_len + payload_len + 1;

    char *buf = (char *)malloc(total);
    if (!buf) {
        return -1;
    }

    snprintf(buf, total, "%s%s", AGENT_CMD_UPDATE_SYSTEM_PROMPT, json_payload);
    int ret = send_ws_text(ctx, buf);
    free(buf);
    return ret;
}

int protocol_send_enhance_query(engine_internal_ctx_t *ctx, const char *json_payload)
{
    if (!ctx || !json_payload) {
        return -1;
    }

    size_t prefix_len = strlen(AGENT_CMD_ENHANCE_QUERY);
    size_t payload_len = strlen(json_payload);
    size_t total = prefix_len + payload_len + 1;

    char *buf = (char *)malloc(total);
    if (!buf) {
        return -1;
    }

    snprintf(buf, total, "%s%s", AGENT_CMD_ENHANCE_QUERY, json_payload);
    int ret = send_ws_text(ctx, buf);
    free(buf);
    return ret;
}

/* ==========================================================================
 * 音色 / 角色切换
 * ========================================================================== */

int protocol_send_switch_voice(engine_internal_ctx_t *ctx, const char *vcn_id)
{
    if (!ctx || !vcn_id) {
        return -1;
    }

    char buf[256];
    snprintf(buf, sizeof(buf),
             "%s{\"tts\":\"DEFAULT{\\\"vcn\\\":\\\"%s\\\"}\"}",
             AGENT_CMD_SWITCH_SCENE_ROLE, vcn_id);
    BD_LOGI(TAG, "switch voice: %s", vcn_id);
    return send_ws_text(ctx, buf);
}

int protocol_send_switch_scene_role(engine_internal_ctx_t *ctx, const char *json_payload)
{
    if (!ctx || !json_payload) {
        return -1;
    }

    size_t prefix_len = strlen(AGENT_CMD_SWITCH_SCENE_ROLE);
    size_t payload_len = strlen(json_payload);
    size_t total = prefix_len + payload_len + 1;

    char stack_buf[256];
    char *buf = stack_buf;
    if (total > sizeof(stack_buf)) {
        buf = (char *)malloc(total);
        if (!buf) {
            return -1;
        }
    }

    snprintf(buf, total, "%s%s", AGENT_CMD_SWITCH_SCENE_ROLE, json_payload);
    int ret = send_ws_text(ctx, buf);

    if (buf != stack_buf) {
        free(buf);
    }
    return ret;
}

/* ==========================================================================
 * 函数调用结果回执
 * ========================================================================== */

int protocol_send_fc_result(engine_internal_ctx_t *ctx, const char *session_id,
                            const char *result, const char *message)
{
    if (!ctx || !session_id || !result) {
        return -1;
    }

    const char *msg = message ? message : "";
    char buf[512];
    snprintf(buf, sizeof(buf), AGENT_CMD_FC_RESULT_FMT, session_id, result, msg);
    BD_LOGI(TAG, "FC result: %s", buf);
    return send_ws_text(ctx, buf);
}

/* ==========================================================================
 * 云端播放控制
 * ========================================================================== */

int protocol_send_remote_player_stop(engine_internal_ctx_t *ctx)
{
    return send_ws_text(ctx, AGENT_CMD_REMOTE_PLAYER_STOP);
}

int protocol_send_remote_player_pause(engine_internal_ctx_t *ctx)
{
    return send_ws_text(ctx, AGENT_CMD_REMOTE_PLAYER_PAUSE);
}

int protocol_send_remote_player_resume(engine_internal_ctx_t *ctx)
{
    return send_ws_text(ctx, AGENT_CMD_REMOTE_PLAYER_RESUME);
}

/* ==========================================================================
 * MCP
 * ========================================================================== */

int protocol_send_mcp_tools_changed(engine_internal_ctx_t *ctx)
{
    return send_ws_text(ctx, AGENT_CMD_MCP_TOOLS_CHANGED);
}
