/**
 * @file scene_ai_toy.c
 * @brief AI 玩具场景实现
 */

#include "scene_ai_toy.h"
#include "scene_ai_toy_config.h"
#include "aiagent_credentials.h"
#include "aiagent_engine.h"
#include "function_call_menu.h"
#include "hal_log.h"

#define TAG "TOY"

/* 场景私有状态 */
static aiagent_engine_t s_engine = NULL;

/* ==========================================================================
 * 角色预设表
 *
 * 名称需与控制台「大模型配置 - 角色」中的 sceneRole 保持一致。
 * 端侧通过 scene_role 字段切换角色。
 *
 * 数组作为角色列表传给 function_call_menu 模块，角色循环、查找、
 * 切换由该模块完成。
 * ========================================================================== */
static const char *const s_toy_characters[] = {
    AI_TOY_CHAR_BEAR_NAME,        /* 北极熊 */
    AI_TOY_CHAR_TEACHER_NAME,     /* 情感陪伴老师 */
    AI_TOY_CHAR_PIGSY_NAME,       /* 猪八戒 */
    AI_TOY_CHAR_NEZHA_NAME,       /* 哪吒 */
};
#define TOY_CHARACTER_COUNT  (sizeof(s_toy_characters) / sizeof(s_toy_characters[0]))

/* 音色预设表（显示名与音色 ID） */
static const function_call_menu_voice_t s_toy_voices[] = {
    {AI_TOY_VOICE_XUEMEI_NAME,    AI_TOY_VOICE_XUEMEI_ID},
    {AI_TOY_VOICE_XINGMENG_NAME,  AI_TOY_VOICE_XINGMENG_ID},
    {AI_TOY_VOICE_SUFEI_NAME,     AI_TOY_VOICE_SUFEI_ID},
    {AI_TOY_VOICE_WENRUN_NAME,    AI_TOY_VOICE_WENRUN_ID},
    {AI_TOY_VOICE_TONGYIN_NAME,   AI_TOY_VOICE_TONGYIN_ID},
    {AI_TOY_VOICE_SHAONIAN_NAME,  AI_TOY_VOICE_SHAONIAN_ID},
    {AI_TOY_VOICE_FENGLING_NAME,  AI_TOY_VOICE_FENGLING_ID},
    {AI_TOY_VOICE_NANSHENG_NAME,  AI_TOY_VOICE_NANSHENG_ID},
    {AI_TOY_VOICE_MIANTANG_NAME,  AI_TOY_VOICE_MIANTANG_ID},
};
#define TOY_VOICE_COUNT  (sizeof(s_toy_voices) / sizeof(s_toy_voices[0]))

/* 场景配置，连接 URL 由引擎层构建 */
static const aiagent_config_t s_toy_config = {
    /* 引擎根据配置参数构建连接 URL */
    .ws_host = AIAGENT_WS_HOST,

    /* 凭证 */
    .appid          = AIAGENT_APPID,
    .license_key    = AIAGENT_LICENSE_KEY,
#if AIAGENT_CONN_MODE == AIAGENT_CONN_MODE_AKSK
    .access_key     = AIAGENT_ACCESS_KEY,
    .secret_key     = AIAGENT_SECRET_KEY,
#elif AIAGENT_CONN_MODE == AIAGENT_CONN_MODE_USERSERVER
    .userserver_url          = AIAGENT_USERSERVER_URL,
    .userserver_create_path  = AIAGENT_USERSERVER_CREATE,
    .userserver_destroy_path = AIAGENT_USERSERVER_DESTROY,
#endif

    /* 上行音频编码 */
    .audio_codec    = "raw16k",

    /* 云端会话参数 */
    .cfg = {
        .tts_sayhi  = AI_TOY_SAYHI_TEXT,
        .lang       = AI_TOY_LANG,
        // .tts        = "DEFAULT",
        // .tts_url    = AI_TOY_TTS_URL,
        .ip_to_location = true,
        .audiocodec = "raw16k",
        .dfda       = true,
        .remote_music_player = true,
        .tts_enable_fast_send = true,
        /* 情绪识别 */
        .emotion_cfg = "{\"enable\":true,\"injectToLLM\":true}",
        /* 声纹识别 */
        .voice_fp_url = "{\"appId\":\"" AIAGENT_APPID "\",\"enable\":true,\"firstSentenceRegistration\":true,\"interruptMode\":0,\"enableClassifyOthers\":true,\"similarity\":[0.18,0.22,0.30,0.40]}",
    },

    /* 本地运行参数 */
    .audio_sample_rate  = AI_TOY_SAMPLE_RATE,
    .audio_channels     = AI_TOY_CHANNELS,
    // .audio_frame_ms     = AI_TOY_FRAME_MS,
    .default_mode       = AI_TOY_DEFAULT_MODE,
    .aec_enable         = true,  /* 开启回声消除 */
};

static const aiagent_config_t *toy_get_config(void)
{
    return &s_toy_config;
}

static int toy_on_init(aiagent_engine_t engine)
{
    s_engine = engine;
    BD_LOGI(TAG, "AI玩具场景初始化");

    /* 注入角色列表，菜单函数调用由 function_call_menu 处理 */
    function_call_menu_cfg_t menu_cfg = {
        .engine          = engine,
        .characters      = s_toy_characters,
        .character_count = TOY_CHARACTER_COUNT,
        .voices          = s_toy_voices,
        .voice_count     = TOY_VOICE_COUNT,
    };
    if (function_call_menu_init(&menu_cfg) != 0) {
        BD_LOGW(TAG, "function_call_menu_init 失败");
    }
    return 0;
}

static void toy_on_start(aiagent_engine_t engine)
{
    BD_LOGI(TAG, "AI玩具场景启动");
}

static void toy_on_stop(aiagent_engine_t engine)
{
    BD_LOGI(TAG, "AI玩具场景停止");
    function_call_menu_deinit();
    s_engine = NULL;
}

static void toy_on_destroy(void)
{
    BD_LOGI(TAG, "AI玩具场景销毁");
}

static void toy_on_state_change(aiagent_state_t old_st, aiagent_state_t new_st)
{
    BD_LOGD(TAG, "状态变化: %d -> %d", old_st, new_st);
}

/**
 * @brief 场景级 ASR 回调（含情绪/声纹扩展）
 *
 * 仅在 AIAGENT_ASR_TEXT_EXT=1 且云端开启 asr_text_ext 时 ext 非 NULL。
 * 此处打印情绪日志，可按 emotion 扩展表情、反馈等本地行为。
 */
static void toy_on_asr_result(const char *text, bool is_final, const aiagent_asr_ext_t *ext)
{
    if (!is_final) {
        return;  /* 跳过中间帧 */
    }
    if (ext && ext->emotion) {
        BD_LOGI(TAG, "ASR final: \"%s\"  emotion=[%s] name=[%s]",
                text ? text : "",
                ext->emotion,
                ext->name ? ext->name : "-");
    } else {
        BD_LOGI(TAG, "ASR final: \"%s\"", text ? text : "");
    }
}

/**
 * @brief 场景级 Function Call 处理
 *
 * 先处理菜单切换，再处理场景自定义能力，未命中时交给引擎内置处理。
 */
static int toy_on_function_call(const char *session_id, const char *name, const char *params)
{
    BD_LOGI(TAG, "场景FC: name=%s params=%s",
            name ? name : "null", params ? params : "null");

    if (!s_engine || !name) {
        return 0;
    }

    /* 优先交给菜单示例模块 */
    if (function_call_menu_dispatch(session_id, name, params) == 0) {
        return 1;
    }

    /* 玩具场景自定义能力可在此扩展，处理成功后返回 1。 */

    return 0;  /* 交给引擎内置 FC 注册表兜底 */
}

static void toy_on_key_event(int action, int key_value)
{
    BD_LOGD(TAG, "按键事件: action=%d, key=%d", action, key_value);
    /* 按键事件委托给引擎的对话管理器 */
}

static void toy_on_network_event(int event)
{
    BD_LOGI(TAG, "网络事件: %d", event);
}

static const aiagent_scene_ops_t s_toy_ops = {
    .name             = "ai_toy",
    .get_config       = toy_get_config,
    .on_init          = toy_on_init,
    .on_start         = toy_on_start,
    .on_stop          = toy_on_stop,
    .on_destroy       = toy_on_destroy,
    .on_state_change  = toy_on_state_change,
    .on_asr_result    = toy_on_asr_result,
    .on_function_call = toy_on_function_call,
    .on_key_event     = toy_on_key_event,
    .on_network_event = toy_on_network_event,
};

const aiagent_scene_ops_t *scene_ai_toy_get_ops(void)
{
    return &s_toy_ops;
}
