/**
 * @file customer_tag.c
 * @brief 自定义标签消息解析实现
 *
 * 解析服务端下发的 {"XCUSTOM":{...}} 结构化 JSON 结果，
 * 通过 JSON key 区分消息类型并填充对应结构体。
 */

#include "customer_tag.h"
#include "hal_json.h"
#include "hal_log.h"
#include <string.h>
#include <stdlib.h>

#define TAG "CTAG"

/* ==========================================================================
 * 辅助: 从裸 JSON 值中提取字符串 (去引号)
 * ========================================================================== */

/**
 * @brief 从 hal_json_to_string 返回的裸值中提取字符串
 *
 * hal_json_get_array_item 返回的 item, 用 hal_json_to_string 得到
 * 带引号的原始值如 "\"hello\"", 需要去掉引号拷贝。
 */
static void extract_raw_string(hal_json_t item, char *dst, int dst_size)
{
    const char *raw = hal_json_to_string(item);
    if (!raw) {
        return;
    }
    if (raw[0] == '"') {
        const char *start = raw + 1;
        const char *end = strchr(start, '"');
        int len = end ? (int)(end - start) : (int)strlen(start);
        if (len >= dst_size) {
            len = dst_size - 1;
        }
        memcpy(dst, start, len);
        dst[len] = '\0';
    } else {
        strncpy(dst, raw, dst_size - 1);
        dst[dst_size - 1] = '\0';
    }
}

/* ==========================================================================
 * 辅助: 从 JSON 数组中提取字符串列表
 * ========================================================================== */

static int extract_string_array(hal_json_t obj, const char *key,
                                char out[][TAG_MAX_ITEM_LEN],
                                int item_size, int max_items)
{
    hal_json_t arr = hal_json_get_array(obj, key);
    if (!arr) {
        return 0;
    }

    int count = hal_json_get_array_size(arr);
    if (count > max_items) {
        count = max_items;
    }

    int actual = 0;
    for (int i = 0; i < count; i++) {
        hal_json_t item = hal_json_get_array_item(arr, i);
        if (!item) {
            continue;
        }
        extract_raw_string(item, out[actual], item_size);
        hal_json_destroy(item);
        actual++;
    }

    hal_json_destroy(arr);
    return actual;
}

/* ==========================================================================
 * 辅助: 安全拷贝字符串字段
 * ========================================================================== */

static void copy_string_field(hal_json_t obj, const char *key,
                              char *dst, int dst_size)
{
    const char *val = hal_json_get_string(obj, key);
    if (val) {
        strncpy(dst, val, dst_size - 1);
        dst[dst_size - 1] = '\0';
    }
}

/* ==========================================================================
 * 各类型解析
 * ========================================================================== */

/**
 * @brief 解析拍万物 (identify) 结果
 *
 * JSON 结构:
 * { "identify": {
 *     "name_ch": "猫", "name_en": "Cat",
 *     "comments_ch": { "characters": [
 *         { "name":"猫", "pronunciation":"māo", "meaning":"...",
 *           "words":["猫咪","花猫"], "sentence":"..." }
 *     ]},
 *     "comments_en": { "name":"Cat", "sentence":"...", "meaning":"..." }
 * }}
 */
static bool parse_identify(hal_json_t obj, tag_identify_result_t *out)
{
    memset(out, 0, sizeof(*out));

    copy_string_field(obj, "name_ch", out->name_ch, sizeof(out->name_ch));
    copy_string_field(obj, "name_en", out->name_en, sizeof(out->name_en));

    /* comments_ch.characters[] */
    hal_json_t comments_ch = hal_json_get_object(obj, "comments_ch");
    if (comments_ch) {
        hal_json_t chars_arr = hal_json_get_array(comments_ch, "characters");
        if (chars_arr) {
            int count = hal_json_get_array_size(chars_arr);
            if (count > TAG_MAX_ARRAY_ITEMS) {
                count = TAG_MAX_ARRAY_ITEMS;
            }
            for (int i = 0; i < count; i++) {
                hal_json_t ch_item = hal_json_get_array_item(chars_arr, i);
                if (!ch_item) {
                    continue;
                }
                tag_character_info_t *c = &out->characters[out->characters_count];
                copy_string_field(ch_item, "name", c->name, sizeof(c->name));
                copy_string_field(ch_item, "pronunciation", c->pronunciation, sizeof(c->pronunciation));
                copy_string_field(ch_item, "meaning", c->meaning, sizeof(c->meaning));
                copy_string_field(ch_item, "sentence", c->sentence, sizeof(c->sentence));
                c->words_count = extract_string_array(ch_item, "words",
                                     c->words, TAG_MAX_ITEM_LEN, TAG_MAX_ARRAY_ITEMS);
                out->characters_count++;
                hal_json_destroy(ch_item);
            }
            hal_json_destroy(chars_arr);
        }
        hal_json_destroy(comments_ch);
    }

    /* comments_en */
    hal_json_t comments_en = hal_json_get_object(obj, "comments_en");
    if (comments_en) {
        copy_string_field(comments_en, "name", out->comments_en.name, sizeof(out->comments_en.name));
        copy_string_field(comments_en, "sentence", out->comments_en.sentence, sizeof(out->comments_en.sentence));
        copy_string_field(comments_en, "meaning", out->comments_en.meaning, sizeof(out->comments_en.meaning));
        hal_json_destroy(comments_en);
    }

    return out->name_ch[0] != '\0';
}

/**
 * @brief 解析拍图识字-中文 (shoot_chinese) 结果
 *
 * JSON keys: name, pronunciation, meaning, words[], example_sentence
 */
static bool parse_chinese(hal_json_t obj, tag_chinese_result_t *out)
{
    memset(out, 0, sizeof(*out));

    copy_string_field(obj, "name", out->name, sizeof(out->name));
    copy_string_field(obj, "pronunciation", out->pronunciation, sizeof(out->pronunciation));
    copy_string_field(obj, "meaning", out->meaning, sizeof(out->meaning));
    copy_string_field(obj, "example_sentence", out->example_sentence, sizeof(out->example_sentence));

    out->words_count = extract_string_array(obj, "words",
                            out->words, TAG_MAX_ITEM_LEN, TAG_MAX_ARRAY_ITEMS);

    return out->name[0] != '\0';
}

/**
 * @brief 解析拍图识字-英文 (shoot_english) 结果
 *
 * JSON keys: name_en, comment, sentence, meaning
 */
static bool parse_english(hal_json_t obj, tag_english_result_t *out)
{
    memset(out, 0, sizeof(*out));

    copy_string_field(obj, "name_en", out->name_en, sizeof(out->name_en));
    copy_string_field(obj, "comment", out->comment, sizeof(out->comment));
    copy_string_field(obj, "sentence", out->sentence, sizeof(out->sentence));
    copy_string_field(obj, "meaning", out->meaning, sizeof(out->meaning));

    return out->name_en[0] != '\0';
}

/**
 * @brief 在 XCUSTOM 容器内按 key 判定类型并解析
 *
 * @param container  XCUSTOM 对应的 JSON 对象
 * @param out_info   [out] 解析结果
 * @return true 命中并解析成功
 */
static bool parse_tag_container(hal_json_t container, tag_msg_info_t *out_info)
{
    hal_json_t identify_obj = hal_json_get_object(container, "identify");
    if (identify_obj) {
        out_info->type = TAG_MSG_TYPE_IDENTIFY;
        bool ok = parse_identify(identify_obj, &out_info->data.identify);
        hal_json_destroy(identify_obj);
        if (ok) {
            BD_LOGI(TAG, "identify: %s (%s)",
                    out_info->data.identify.name_ch,
                    out_info->data.identify.name_en);
        }
        return ok;
    }

    hal_json_t chinese_obj = hal_json_get_object(container, "shoot_chinese");
    if (chinese_obj) {
        out_info->type = TAG_MSG_TYPE_SHOOT_CHINESE;
        bool ok = parse_chinese(chinese_obj, &out_info->data.chinese);
        hal_json_destroy(chinese_obj);
        if (ok) {
            BD_LOGI(TAG, "chinese: %s [%s]",
                    out_info->data.chinese.name,
                    out_info->data.chinese.pronunciation);
        }
        return ok;
    }

    hal_json_t english_obj = hal_json_get_object(container, "shoot_english");
    if (english_obj) {
        out_info->type = TAG_MSG_TYPE_SHOOT_ENGLISH;
        bool ok = parse_english(english_obj, &out_info->data.english);
        hal_json_destroy(english_obj);
        if (ok) {
            BD_LOGI(TAG, "english: %s (%s)",
                    out_info->data.english.name_en,
                    out_info->data.english.comment);
        }
        return ok;
    }

    BD_LOGW(TAG, "unknown tag msg type");
    return false;
}

/* ==========================================================================
 * 公开 API
 * ========================================================================== */

bool tag_msg_parse(const char *event_data, size_t data_len, tag_msg_info_t *out_info)
{
    if (!event_data || data_len == 0 || !out_info) {
        return false;
    }

    memset(out_info, 0, sizeof(*out_info));
    out_info->type = TAG_MSG_TYPE_UNKNOWN;

    /* 在事件数据中定位 JSON 起始位置 '{' */
    const char *json_start = memchr(event_data, '{', data_len);
    if (!json_start) {
        BD_LOGW(TAG, "no JSON found in event data");
        return false;
    }

    /* 提取 JSON 字符串用于解析 */
    size_t json_len = data_len - (size_t)(json_start - event_data);
    char *json_str = (char *)malloc(json_len + 1);
    if (!json_str) {
        return false;
    }
    memcpy(json_str, json_start, json_len);
    json_str[json_len] = '\0';

    /* 解析 JSON */
    hal_json_t root = hal_json_parse(json_str);
    free(json_str);
    if (!root) {
        BD_LOGW(TAG, "JSON parse failed");
        return false;
    }

    bool ok = false;

    /* 新格式外层统一包裹 XCUSTOM:
     * { "XCUSTOM": { "identify"|"shoot_chinese"|"shoot_english": {...} } } */
    hal_json_t container = hal_json_get_object(root, "XCUSTOM");
    if (!container) {
        BD_LOGW(TAG, "no XCUSTOM wrapper found");
        hal_json_destroy(root);
        return false;
    }

    ok = parse_tag_container(container, out_info);

    hal_json_destroy(container);
    hal_json_destroy(root);
    return ok;
}

const char *tag_msg_type_name(tag_msg_type_t type)
{
    switch (type) {
    case TAG_MSG_TYPE_IDENTIFY:      return "identify";
    case TAG_MSG_TYPE_SHOOT_CHINESE: return "shoot_chinese";
    case TAG_MSG_TYPE_SHOOT_ENGLISH: return "shoot_english";
    default:                         return "unknown";
    }
}
