/**
 * @file connection_url_builder.c
 * @brief WebSocket URL 构建实现（cfg JSON 序列化 + 鉴权参数拼接）
 */

#include "connection/connection_url_builder.h"
#include "engine_internal.h"
#include "connection/userserver_client.h"
#include "aiagent_credentials.h"
#include "string_utils.h"
#include "hal_device_info.h"
#include "hal_log.h"
#include <stdio.h>
#include <string.h>

#define TAG "URL_BUILD"

/* cfg JSON 编码后进 URL，缓冲区按最坏情况分配 */
#define CFG_BUF_SIZE     2048
#define CFG_ENC_BUF_SIZE (CFG_BUF_SIZE * 3)
#define URL_BUF_SIZE     (CFG_ENC_BUF_SIZE + 1024)

static char s_url_buf[URL_BUF_SIZE];
static char s_cfg_buf[CFG_BUF_SIZE];
static char s_cfg_enc_buf[CFG_ENC_BUF_SIZE];

/* ---- cfg JSON 构建辅助宏 ---- */
#define CFG_APPEND(fmt, ...) do { \
    int _n = snprintf(p, (size_t)(end - p), \
        "%s" fmt, (p > s_cfg_buf + 1) ? "," : "" \
        , ##__VA_ARGS__); \
    if (_n > 0 && p + _n < end) p += _n; \
} while(0)

#define CFG_STR(key, val) \
    if ((val) && (val)[0]) { CFG_APPEND("\"%s\":\"%s\"", key, val); }
#define CFG_STR_RAW(key, val) \
    if ((val) && (val)[0]) { CFG_APPEND("\"%s\":%s", key, val); }
#define CFG_INT(key, val) \
    if ((val) != 0) { CFG_APPEND("\"%s\":%d", key, val); }
#define CFG_BOOL(key, val) \
    if (val) { CFG_APPEND("\"%s\":true", key); }
#define CFG_FLOAT(key, val) \
    if ((val) > 0.01f) { \
        CFG_APPEND("\"%s\":%.1f", key, (double)(val)); \
    }

/**
 * @brief 序列化 cfg 参数为 JSON，只写非 NULL/非零字段
 */
static void build_cfg_json(const aiagent_cfg_params_t *cfg)
{
    char *p = s_cfg_buf;
    char *end = s_cfg_buf + CFG_BUF_SIZE - 1;

    *p++ = '{';

#if AIAGENT_REGION_IS_INTL
    /* 海外区域标识 */
    CFG_STR("region_type", "intl");
#endif

    /* 地理位置 */
    CFG_STR("location", cfg->location);
    CFG_STR("gis", cfg->gis);
    CFG_BOOL("ip_to_location", cfg->ip_to_location);

    /* 角色 */
    CFG_STR("role", cfg->role);
    CFG_STR("sceneRole", cfg->scene_role);
    CFG_STR_RAW("sceneRoleCfg", cfg->scene_role_cfg);

    /* 招呼语 & 语言 */
    CFG_STR("tts_sayhi", cfg->tts_sayhi);
    CFG_STR("lang", cfg->lang);

    /* 下行音频 */
    CFG_STR("audiocodec", cfg->audiocodec);
    CFG_INT("audio_bitrate", cfg->audio_bitrate);
    CFG_BOOL("aoco", cfg->aoco);
    CFG_INT("aopt", cfg->aopt);

    /* 打断控制 */
    CFG_BOOL("disable_voice_auto_int", cfg->disable_voice_auto_int);
    CFG_STR("interruption_words", cfg->interruption_words);
    CFG_STR("interruption_answer", cfg->interruption_answer);
    CFG_INT("auto_pause_secs", cfg->auto_pause_secs);

    /* 静音包 */
    CFG_BOOL("dfda", cfg->dfda);

    /* TTS */
    CFG_STR("tts", cfg->tts);
    CFG_STR("tts_url", cfg->tts_url);
    CFG_INT("tts_end_delay_ms", cfg->tts_end_delay_ms);
    CFG_BOOL("tts_enable_fast_send", cfg->tts_enable_fast_send);
    CFG_INT("tts_fast_send_second", cfg->tts_fast_send_second);
    CFG_FLOAT("tts_fast_send_ratio", cfg->tts_fast_send_ratio);
    CFG_BOOL("etbt", cfg->etbt);

    /* LLM */
    CFG_STR("llm", cfg->llm);
    CFG_STR("llm_url", cfg->llm_url);
    CFG_STR("llm_cfg", cfg->llm_cfg);
    CFG_STR("llm_token", cfg->llm_token);

    /* 端到端语音模型 */
    CFG_STR("e2ellm_mode", cfg->e2ellm_mode);
    CFG_INT("e2ellm_sample_rate", cfg->e2ellm_sample_rate);

    /* user_id 未设置时回退到 device_id */
    char uid_fallback[40] = {0};
    const char *uid = cfg->user_id;
    if (!uid || !uid[0]) {
        if (hal_device_get_device_id(uid_fallback,
                                     sizeof(uid_fallback)) == 0
            && uid_fallback[0]) {
            uid = uid_fallback;
        }
    }
    CFG_STR("user_id", uid);

    /* ASR */
    CFG_BOOL("asr_long_audio_mode", cfg->asr_long_audio_mode);
    CFG_INT("asr_vad", cfg->asr_vad);
    CFG_INT("asr_vad_level", cfg->asr_vad_level);
    CFG_STR("hotwords", cfg->hotwords);

    /* 声纹 */
    CFG_STR_RAW("voice_fp_url", cfg->voice_fp_url);

    /* 云播 */
    CFG_BOOL("remote_music_player", cfg->remote_music_player);

    /* 情感 */
    CFG_STR_RAW("emotionRecognitionCfg", cfg->emotion_cfg);

    /* 云端3A */
    CFG_STR_RAW("cloud_3A_url", cfg->cloud_3a_url);

    /* 内容库 */
    CFG_STR("content_used_db", cfg->content_used_db);

    /* 翻译 */
    CFG_STR("translationSourceLanguage", cfg->translation_src_lang);
    CFG_STR("translationTargetLanguage", cfg->translation_tgt_lang);
    CFG_STR("translationServiceVersion", cfg->translation_svc_ver);

    /* 视觉 */
    if (cfg->enable_visual) {
        CFG_APPEND("\"enable_visual\":\"true\"");
    }
    CFG_INT("screen_width", cfg->screen_width);
    CFG_INT("screen_height", cfg->screen_height);

    /* 意图路由 */
    CFG_STR_RAW("intentCfg", cfg->intent_cfg);

    /* MCP */
    CFG_STR_RAW("mcp_servers", cfg->mcp_servers);

    /* 扩展: 场景自定义额外cfg片段 */
    if (cfg->extra_cfg && cfg->extra_cfg[0]) {
        int _n = snprintf(p, (size_t)(end - p), "%s%s",
                          (p > s_cfg_buf + 1) ? "," : "",
                          cfg->extra_cfg);
        if (_n > 0 && p + _n < end) {
            p += _n;
        }
    }

    *p++ = '}';
    *p = '\0';
}

const char *conn_url_build(engine_internal_ctx_t *ctx)
{
    const aiagent_config_t *cfg = &ctx->config;

    if (cfg->ws_url && cfg->ws_url[0] != '\0') {
        return cfg->ws_url;
    }

    if (!cfg->appid || cfg->appid[0] == '\0') {
        return NULL;
    }

    const char *host = (cfg->ws_host && cfg->ws_host[0] != '\0')
                       ? cfg->ws_host : AIAGENT_WS_HOST;
    const char *codec = (cfg->audio_codec && cfg->audio_codec[0])
                        ? cfg->audio_codec : "raw16k";

    build_cfg_json(&cfg->cfg);

#if AIAGENT_CONN_MODE == AIAGENT_CONN_MODE_USERSERVER
    userserver_session_t session;
    if (userserver_create_instance(cfg->userserver_url,
                                   cfg->userserver_create_path,
                                   cfg->appid, s_cfg_buf,
                                   &session) < 0) {
        BD_LOGE(TAG, "userserver create fail");
        return NULL;
    }
    snprintf(ctx->userserver_instance_id,
             sizeof(ctx->userserver_instance_id),
             "%s", session.instance_id);

    int n = snprintf(s_url_buf, sizeof(s_url_buf),
        "%s?a=%s&id=%s&t=%s&ac=%s",
        host, cfg->appid, session.instance_id,
        session.token, codec);
    if (cfg->audio_frame_ms > 0 && n > 0
        && n < (int)sizeof(s_url_buf)) {
        n += snprintf(s_url_buf + n, sizeof(s_url_buf) - n,
                      "&ptime=%d", cfg->audio_frame_ms);
    }
#else
    str_utils_url_encode(s_cfg_buf, s_cfg_enc_buf,
                         sizeof(s_cfg_enc_buf));

#if AIAGENT_CONN_MODE == AIAGENT_CONN_MODE_AKSK
    if (!cfg->access_key || !cfg->access_key[0] ||
        !cfg->secret_key || !cfg->secret_key[0]) {
        BD_LOGE(TAG, "AKSK mode requires access_key/secret_key");
        return NULL;
    }
    int n = snprintf(s_url_buf, sizeof(s_url_buf),
        "%s?a=%s&ak=%s&sk=%s&ac=%s&cfg=%s",
        host, cfg->appid, cfg->access_key, cfg->secret_key,
        codec, s_cfg_enc_buf);
    if (cfg->audio_frame_ms > 0 && n > 0
        && n < (int)sizeof(s_url_buf)) {
        n += snprintf(s_url_buf + n, sizeof(s_url_buf) - n,
                      "&ptime=%d", cfg->audio_frame_ms);
    }
    if (cfg->license_key && cfg->license_key[0] != '\0'
        && n > 0 && n < (int)sizeof(s_url_buf)) {
        n += snprintf(s_url_buf + n, sizeof(s_url_buf) - n,
                      "&lk=%s", cfg->license_key);
    }
#else /* AIAGENT_CONN_MODE_TEST */
    int n = snprintf(s_url_buf, sizeof(s_url_buf),
        "%s?a=%s&ac=%s&cfg=%s",
        host, cfg->appid, codec, s_cfg_enc_buf);
    if (cfg->audio_frame_ms > 0 && n > 0
        && n < (int)sizeof(s_url_buf)) {
        n += snprintf(s_url_buf + n, sizeof(s_url_buf) - n,
                      "&ptime=%d", cfg->audio_frame_ms);
    }
#endif
#endif

    (void)n;
    return s_url_buf;
}

