"use strict";
/**
 * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
 * SPDX-License-Identifier: MIT
 */
import { EMOJI_MAP, CHART_TYPE_NAMES } from './types';
import { escapeAttr, formatMillisecondsToISO8601, normalizeTimeFormat } from './card-utils';
import { safeParse } from '../utils';
export const MODE = { Concise: 0, Detailed: 1 };
const elementConverters = new Map([
    ['plain_text', (c, _elem, prop) => c.convertPlainText(prop)],
    ['markdown', (c, _elem, prop) => c.convertMarkdown(prop)],
    ['markdown_v1', (c, elem, prop) => c.convertMarkdownV1(elem, prop)],
    ['text', (c, _elem, prop) => c.convertPlainText(prop)],
    ['div', (c, _elem, prop, id) => c.convertDiv(prop, id)],
    ['note', (c, _elem, prop) => c.convertNote(prop)],
    ['hr', () => '---'],
    ['br', () => '\n'],
    ['column_set', (c, _elem, prop, _id, depth) => c.convertColumnSet(prop, depth)],
    ['column', (c, _elem, prop, _id, depth) => c.convertColumn(prop, depth)],
    ['person', (c, _elem, prop, id) => c.convertPerson(prop, id)],
    ['person_v1', (c, _elem, prop, id) => c.convertPersonV1(prop, id)],
    ['person_list', (c, _elem, prop) => c.convertPersonList(prop)],
    ['avatar', (c, _elem, prop, id) => c.convertAvatar(prop, id)],
    ['at', (c, _elem, prop) => c.convertAt(prop)],
    ['at_all', () => '@所有人'],
    ['button', (c, _elem, prop, id) => c.convertButton(prop, id)],
    ['actions', (c, _elem, prop) => c.convertActions(prop)],
    ['action', (c, _elem, prop) => c.convertActions(prop)],
    ['overflow', (c, _elem, prop) => c.convertOverflow(prop)],
    ['select_static', (c, _elem, prop, id) => c.convertSelect(prop, id, false)],
    ['multi_select_static', (c, _elem, prop, id) => c.convertSelect(prop, id, true)],
    ['select_person', (c, _elem, prop, id) => c.convertSelect(prop, id, false)],
    ['multi_select_person', (c, _elem, prop, id) => c.convertSelect(prop, id, true)],
    ['select_img', (c, _elem, prop, id) => c.convertSelectImg(prop, id)],
    ['input', (c, _elem, prop, id) => c.convertInput(prop, id)],
    ['date_picker', (c, _elem, prop, id) => c.convertDatePicker(prop, id, 'date')],
    ['picker_time', (c, _elem, prop, id) => c.convertDatePicker(prop, id, 'time')],
    ['picker_datetime', (c, _elem, prop, id) => c.convertDatePicker(prop, id, 'datetime')],
    ['checker', (c, _elem, prop, id) => c.convertChecker(prop, id)],
    ['img', (c, _elem, prop, id) => c.convertImage(prop, id)],
    ['image', (c, _elem, prop, id) => c.convertImage(prop, id)],
    ['img_combination', (c, _elem, prop) => c.convertImgCombination(prop)],
    ['table', (c, _elem, prop) => c.convertTable(prop)],
    ['chart', (c, _elem, prop, id) => c.convertChart(prop, id)],
    ['audio', (c, _elem, prop, id) => c.convertAudio(prop, id)],
    ['video', (c, _elem, prop, id) => c.convertVideo(prop, id)],
    ['collapsible_panel', (c, _elem, prop, id) => c.convertCollapsiblePanel(prop, id)],
    ['form', (c, _elem, prop, id) => c.convertForm(prop, id)],
    ['interactive_container', (c, _elem, prop, id) => c.convertInteractiveContainer(prop, id)],
    ['text_tag', (c, _elem, prop) => c.convertTextTag(prop)],
    ['number_tag', (c, _elem, prop) => c.convertNumberTag(prop)],
    ['link', (c, _elem, prop) => c.convertLink(prop)],
    ['emoji', (c, _elem, prop) => c.convertEmoji(prop)],
    ['local_datetime', (c, _elem, prop) => c.convertLocalDatetime(prop)],
    ['list', (c, _elem, prop) => c.convertList(prop)],
    ['blockquote', (c, _elem, prop) => c.convertBlockquote(prop)],
    ['code_block', (c, _elem, prop) => c.convertCodeBlock(prop)],
    ['code_span', (c, _elem, prop) => c.convertCodeSpan(prop)],
    ['heading', (c, _elem, prop) => c.convertHeading(prop)],
    ['fallback_text', (c, _elem, prop) => c.convertFallbackText(prop)],
    ['repeat', (c, _elem, prop) => c.convertRepeat(prop)],
    ['card_header', () => ''],
    ['custom_icon', () => ''],
    ['standard_icon', () => ''],
]);
export class CardConverter {
    mode;
    attachment;
    constructor(mode) {
        this.mode = mode;
    }
    convert(input) {
        const card = safeParse(input.json_card);
        if (!card) {
            return { content: '<card>\n[无法解析卡片内容]\n</card>', schema: 0 };
        }
        if (input.json_attachment) {
            this.attachment = safeParse(input.json_attachment);
        }
        let schema = input.card_schema ?? 0;
        if (schema === 0) {
            const s = card.schema;
            schema = typeof s === 'number' ? s : 1;
        }
        const header = card.header;
        const title = header ? this.extractHeaderTitle(header, schema) : '';
        const body = this.extractBody(card, schema);
        const bodyContent = body ? this.convertBody(body, schema) : '';
        let out = title ? `<card title="${escapeAttr(title)}">\n` : '<card>\n';
        if (bodyContent)
            out += bodyContent + '\n';
        out += '</card>';
        return { content: out, schema };
    }
    extractBody(card, _schema) {
        if (card.body && typeof card.body === 'object') {
            return card.body;
        }
        return undefined;
    }
    extractHeaderTitle(header, _schema) {
        const prop = header.property;
        if (prop) {
            const titleElem = prop.title;
            if (titleElem)
                return this.extractTextContent(titleElem);
        }
        else {
            const titleElem = header.title;
            if (titleElem)
                return this.extractTextContent(titleElem);
        }
        return '';
    }
    convertBody(body, _schema) {
        let elements;
        const prop = body.property;
        if (prop) {
            const e = prop.elements;
            if (Array.isArray(e) && e.length > 0)
                elements = e;
        }
        if (!elements || elements.length === 0) {
            const e = body.elements;
            if (Array.isArray(e))
                elements = e;
        }
        if (!elements || elements.length === 0)
            return '';
        return this.convertElements(elements, 0);
    }
    convertElements(elements, depth) {
        const results = [];
        for (const elem of elements) {
            if (typeof elem !== 'object' || elem === null)
                continue;
            const result = this.convertElement(elem, depth);
            if (result)
                results.push(result);
        }
        return results.join('\n');
    }
    convertElement(elem, depth) {
        const tag = elem.tag ?? '';
        const id = elem.id ?? '';
        const prop = this.extractProperty(elem);
        const fn = elementConverters.get(tag);
        if (fn)
            return fn(this, elem, prop, id, depth);
        return this.convertUnknown(prop, tag);
    }
    extractProperty(elem) {
        if (elem.property && typeof elem.property === 'object') {
            return elem.property;
        }
        return elem;
    }
    extractTextContent(textElem) {
        if (textElem == null)
            return '';
        if (typeof textElem === 'string')
            return textElem;
        if (typeof textElem === 'object') {
            const m = textElem;
            if (m.property && typeof m.property === 'object') {
                return this.extractTextFromProperty(m.property);
            }
            return this.extractTextFromProperty(m);
        }
        return '';
    }
    extractTextFromProperty(prop) {
        const i18n = prop.i18nContent;
        if (i18n && typeof i18n === 'object') {
            for (const lang of ['zh_cn', 'en_us', 'ja_jp']) {
                const t = i18n[lang];
                if (typeof t === 'string' && t)
                    return t;
            }
        }
        if (typeof prop.content === 'string')
            return prop.content;
        const elements = prop.elements;
        if (Array.isArray(elements) && elements.length > 0) {
            const texts = [];
            for (const elem of elements) {
                if (typeof elem === 'object' && elem !== null) {
                    const t = this.extractTextContent(elem);
                    if (t)
                        texts.push(t);
                }
            }
            return texts.join('');
        }
        if (typeof prop.text === 'string')
            return prop.text;
        return '';
    }
    convertPlainText(prop) {
        const content = prop.content;
        if (!content)
            return '';
        const style = this.extractTextStyle(prop);
        return this.applyTextStyle(content, style);
    }
    convertMarkdown(prop) {
        const elements = prop.elements;
        if (Array.isArray(elements) && elements.length > 0) {
            return this.convertMarkdownElements(elements);
        }
        if (typeof prop.content === 'string')
            return prop.content;
        return '';
    }
    convertMarkdownV1(elem, prop) {
        const elements = prop.elements;
        if (Array.isArray(elements) && elements.length > 0) {
            return this.convertMarkdownElements(elements);
        }
        const fallback = elem.fallback;
        if (fallback && typeof fallback === 'object') {
            return this.convertElement(fallback, 0);
        }
        if (typeof prop.content === 'string')
            return prop.content;
        return '';
    }
    convertMarkdownElements(elements) {
        const parts = [];
        for (const elem of elements) {
            if (typeof elem !== 'object' || elem === null)
                continue;
            const result = this.convertElement(elem, 0);
            if (result)
                parts.push(result);
        }
        return parts.join('');
    }
    convertDiv(prop, _id) {
        const results = [];
        const textElem = prop.text;
        if (textElem && typeof textElem === 'object') {
            const text = this.convertElement(textElem, 0);
            if (text)
                results.push(text);
        }
        const fields = prop.fields;
        if (Array.isArray(fields) && fields.length > 0) {
            const fieldTexts = [];
            for (const field of fields) {
                if (typeof field !== 'object' || field === null)
                    continue;
                const fm = field;
                const te = fm.text;
                if (te && typeof te === 'object') {
                    const ft = this.convertElement(te, 0);
                    if (ft)
                        fieldTexts.push(ft);
                }
            }
            if (fieldTexts.length > 0)
                results.push(fieldTexts.join('\n'));
        }
        const extraElem = prop.extra;
        if (extraElem && typeof extraElem === 'object') {
            const extra = this.convertElement(extraElem, 0);
            if (extra)
                results.push(extra);
        }
        return results.join('\n');
    }
    convertNote(prop) {
        const elements = prop.elements;
        if (!Array.isArray(elements) || elements.length === 0)
            return '';
        const texts = [];
        for (const elem of elements) {
            if (typeof elem !== 'object' || elem === null)
                continue;
            const text = this.convertElement(elem, 0);
            if (text)
                texts.push(text);
        }
        if (texts.length === 0)
            return '';
        return `📝 ${texts.join(' ')}`;
    }
    convertLink(prop) {
        const content = prop.content || '链接';
        let url = '';
        const urlObj = prop.url;
        if (urlObj && typeof urlObj === 'object') {
            url = urlObj.url || '';
        }
        if (url)
            return `[${content}](${url})`;
        return content;
    }
    convertEmoji(prop) {
        const key = prop.key || '';
        return EMOJI_MAP[key] ?? `:${key}:`;
    }
    convertLocalDatetime(prop) {
        const milliseconds = prop.milliseconds;
        const fallbackText = prop.fallbackText;
        if (milliseconds) {
            const formatted = formatMillisecondsToISO8601(milliseconds);
            if (formatted)
                return formatted;
        }
        return fallbackText || '';
    }
    convertList(prop) {
        const items = prop.items;
        if (!Array.isArray(items) || items.length === 0)
            return '';
        const lines = [];
        for (const item of items) {
            if (typeof item !== 'object' || item === null)
                continue;
            const im = item;
            const level = im.level || 0;
            const listType = im.type || '';
            const order = im.order || 0;
            const indent = '  '.repeat(level);
            const marker = listType === 'ol' ? `${Math.floor(order)}.` : '-';
            const elements = im.elements;
            if (Array.isArray(elements)) {
                const content = this.convertMarkdownElements(elements);
                lines.push(`${indent}${marker} ${content}`);
            }
        }
        return lines.join('\n');
    }
    convertBlockquote(prop) {
        let content = '';
        if (typeof prop.content === 'string') {
            content = prop.content;
        }
        else {
            const elements = prop.elements;
            if (Array.isArray(elements)) {
                content = this.convertMarkdownElements(elements);
            }
        }
        if (!content)
            return '';
        return content
            .split('\n')
            .map((line) => `> ${line}`)
            .join('\n');
    }
    convertCodeBlock(prop) {
        const language = prop.language || 'plaintext';
        let code = '';
        const contents = prop.contents;
        if (Array.isArray(contents)) {
            for (const line of contents) {
                if (typeof line !== 'object' || line === null)
                    continue;
                const lm = line;
                const lineContents = lm.contents;
                if (Array.isArray(lineContents)) {
                    for (const c of lineContents) {
                        if (typeof c !== 'object' || c === null)
                            continue;
                        const cm = c;
                        if (typeof cm.content === 'string')
                            code += cm.content;
                    }
                }
            }
        }
        return `\`\`\`${language}\n${code}\`\`\``;
    }
    convertCodeSpan(prop) {
        const content = prop.content || '';
        return `\`${content}\``;
    }
    convertHeading(prop) {
        let level = prop.level || 1;
        if (level < 1)
            level = 1;
        if (level > 6)
            level = 6;
        let content = '';
        if (typeof prop.content === 'string') {
            content = prop.content;
        }
        else {
            const elements = prop.elements;
            if (Array.isArray(elements)) {
                content = this.convertMarkdownElements(elements);
            }
        }
        return `${'#'.repeat(level)} ${content}`;
    }
    convertFallbackText(prop) {
        const textElem = prop.text;
        if (textElem && typeof textElem === 'object') {
            return this.extractTextContent(textElem);
        }
        const elements = prop.elements;
        if (Array.isArray(elements)) {
            return this.convertMarkdownElements(elements);
        }
        return '';
    }
    convertTextTag(prop) {
        const textElem = prop.text;
        let text = '';
        if (textElem && typeof textElem === 'object') {
            text = this.extractTextContent(textElem);
        }
        if (!text)
            return '';
        return `「${text}」`;
    }
    convertNumberTag(prop) {
        const textElem = prop.text;
        let text = '';
        if (textElem && typeof textElem === 'object') {
            text = this.extractTextContent(textElem);
        }
        if (!text)
            return '';
        const urlObj = prop.url;
        if (urlObj && typeof urlObj === 'object') {
            const url = urlObj.url;
            if (url)
                return `[${text}](${url})`;
        }
        return text;
    }
    convertUnknown(prop, tag) {
        if (!prop) {
            if (this.mode === MODE.Detailed)
                return `[未知内容](tag:${tag})`;
            return '[未知内容]';
        }
        const paths = ['content', 'text', 'title', 'label', 'placeholder'];
        for (const path of paths) {
            if (prop[path] != null) {
                const text = this.extractTextContent(prop[path]);
                if (text)
                    return text;
            }
        }
        const elements = prop.elements;
        if (Array.isArray(elements) && elements.length > 0) {
            return this.convertElements(elements, 0);
        }
        if (this.mode === MODE.Detailed)
            return `[未知内容](tag:${tag})`;
        return '[未知内容]';
    }
    convertColumnSet(prop, depth) {
        const columns = prop.columns;
        if (!Array.isArray(columns) || columns.length === 0)
            return '';
        const results = [];
        for (const col of columns) {
            if (typeof col !== 'object' || col === null)
                continue;
            const result = this.convertElement(col, depth + 1);
            if (result)
                results.push(result);
        }
        return results.join('\n\n');
    }
    convertColumn(prop, depth) {
        const elements = prop.elements;
        if (!Array.isArray(elements) || elements.length === 0)
            return '';
        return this.convertElements(elements, depth);
    }
    convertForm(prop, _id) {
        let out = '<form>\n';
        const elements = prop.elements;
        if (Array.isArray(elements)) {
            out += this.convertElements(elements, 0);
        }
        out += '\n</form>';
        return out;
    }
    convertCollapsiblePanel(prop, _id) {
        const expanded = prop.expanded === true;
        let title = '详情';
        const header = prop.header;
        if (header && typeof header === 'object') {
            const titleElem = header.title;
            if (titleElem) {
                const t = this.extractTextContent(titleElem);
                if (t)
                    title = t;
            }
        }
        const shouldExpand = expanded || this.mode === MODE.Detailed;
        if (shouldExpand) {
            let out = `▼ ${title}\n`;
            const elements = prop.elements;
            if (Array.isArray(elements)) {
                const content = this.convertElements(elements, 1);
                for (const line of content.split('\n')) {
                    if (line)
                        out += `    ${line}\n`;
                }
            }
            out += '▲';
            return out;
        }
        return `▶ ${title}`;
    }
    convertInteractiveContainer(prop, _id) {
        let url = '';
        const actions = prop.actions;
        if (Array.isArray(actions) && actions.length > 0) {
            const action = actions[0];
            if (action && typeof action === 'object') {
                const actionType = action.type;
                if (actionType === 'open_url') {
                    const actionData = action.action;
                    if (actionData && typeof actionData === 'object') {
                        url = actionData.url || '';
                    }
                }
            }
        }
        let out = '<clickable';
        if (url)
            out += ` url="${escapeAttr(url)}"`;
        if (this.mode === MODE.Detailed && _id)
            out += ` id="${_id}"`;
        out += '>\n';
        const elements = prop.elements;
        if (Array.isArray(elements)) {
            out += this.convertElements(elements, 0);
        }
        out += '\n</clickable>';
        return out;
    }
    convertRepeat(prop) {
        const elements = prop.elements;
        if (Array.isArray(elements)) {
            return this.convertElements(elements, 0);
        }
        return '';
    }
    convertButton(prop, _id) {
        let buttonText = '';
        const textElem = prop.text;
        if (textElem && typeof textElem === 'object') {
            buttonText = this.extractTextContent(textElem);
        }
        if (!buttonText)
            buttonText = '按钮';
        const disabled = prop.disabled === true;
        if (disabled && this.mode === MODE.Concise) {
            return `[${buttonText} ✗]`;
        }
        const actions = prop.actions;
        if (Array.isArray(actions)) {
            for (const action of actions) {
                if (typeof action !== 'object' || action === null)
                    continue;
                const am = action;
                if (am.type === 'open_url') {
                    const ad = am.action;
                    if (ad && typeof ad === 'object') {
                        const url = ad.url;
                        if (url)
                            return `[${buttonText}](${url})`;
                    }
                }
            }
        }
        if (disabled && this.mode === MODE.Detailed) {
            let result = `[${buttonText} ✗]`;
            const tips = prop.disabledTips;
            if (tips && typeof tips === 'object') {
                const tipsText = this.extractTextContent(tips);
                if (tipsText)
                    result += `(tips:"${tipsText}")`;
            }
            return result;
        }
        return `[${buttonText}]`;
    }
    convertActions(prop) {
        const actions = prop.actions;
        if (!Array.isArray(actions) || actions.length === 0)
            return '';
        const results = [];
        for (const action of actions) {
            if (typeof action !== 'object' || action === null)
                continue;
            const result = this.convertElement(action, 0);
            if (result)
                results.push(result);
        }
        return results.join(' ');
    }
    convertSelect(prop, _id, isMulti) {
        const options = prop.options || [];
        const selectedValues = new Set();
        if (isMulti) {
            const vals = prop.selectedValues;
            if (Array.isArray(vals)) {
                for (const v of vals) {
                    if (typeof v === 'string')
                        selectedValues.add(v);
                }
            }
        }
        else {
            const initialOption = prop.initialOption;
            if (typeof initialOption === 'string')
                selectedValues.add(initialOption);
            const initialIndex = prop.initialIndex;
            if (typeof initialIndex === 'number' && initialIndex >= 0 && initialIndex < options.length) {
                const opt = options[initialIndex];
                if (opt && typeof opt === 'object') {
                    const val = opt.value;
                    if (val)
                        selectedValues.add(val);
                }
            }
        }
        const optionTexts = [];
        let hasSelected = false;
        for (const opt of options) {
            if (typeof opt !== 'object' || opt === null)
                continue;
            const om = opt;
            let optText = '';
            const textElem = om.text;
            if (textElem && typeof textElem === 'object') {
                optText = this.extractTextContent(textElem);
            }
            if (!optText)
                optText = om.value || '';
            if (!optText)
                continue;
            const value = om.value || '';
            if (selectedValues.has(value)) {
                optText = '✓' + optText;
                hasSelected = true;
            }
            optionTexts.push(optText);
        }
        if (optionTexts.length === 0) {
            let placeholder = '请选择';
            const phElem = prop.placeholder;
            if (phElem && typeof phElem === 'object') {
                const ph = this.extractTextContent(phElem);
                if (ph)
                    placeholder = ph;
            }
            optionTexts.push(placeholder + ' ▼');
        }
        else if (!hasSelected) {
            optionTexts[optionTexts.length - 1] += ' ▼';
        }
        let result = `{${optionTexts.join(' / ')}}`;
        if (this.mode === MODE.Detailed) {
            const attrs = [];
            if (isMulti)
                attrs.push('multi');
            if (_id.includes('person') || prop.type === 'person')
                attrs.push('type:person');
            if (attrs.length > 0)
                result += `(${attrs.join(' ')})`;
        }
        return result;
    }
    convertSelectImg(prop, _id) {
        const options = prop.options;
        if (!Array.isArray(options))
            return '';
        const selectedValues = new Set();
        const vals = prop.selectedValues;
        if (Array.isArray(vals)) {
            for (const v of vals) {
                if (typeof v === 'string')
                    selectedValues.add(v);
            }
        }
        const optTexts = [];
        for (let i = 0; i < options.length; i++) {
            const opt = options[i];
            if (!opt || typeof opt !== 'object')
                continue;
            const value = opt.value || '';
            let text = `🖼️图${i + 1}`;
            if (selectedValues.has(value))
                text = '✓' + text;
            optTexts.push(text);
        }
        return `{${optTexts.join(' / ')}}`;
    }
    convertInput(prop, _id) {
        let label = '';
        const labelElem = prop.label;
        if (labelElem && typeof labelElem === 'object') {
            label = this.extractTextContent(labelElem);
        }
        const defaultValue = prop.defaultValue || '';
        let placeholder = '';
        const phElem = prop.placeholder;
        if (phElem && typeof phElem === 'object') {
            placeholder = this.extractTextContent(phElem);
        }
        let result;
        if (defaultValue) {
            result = defaultValue + '___';
        }
        else if (placeholder) {
            result = placeholder + '_____';
        }
        else {
            result = '_____';
        }
        if (label)
            result = label + ': ' + result;
        const inputType = prop.inputType;
        if (inputType === 'multiline_text') {
            result = result.replace(/_____/g, '...');
        }
        return result;
    }
    convertDatePicker(prop, _id, pickerType) {
        let emoji;
        let value = '';
        switch (pickerType) {
            case 'date':
                emoji = '📅';
                value = prop.initialDate || '';
                break;
            case 'time':
                emoji = '🕐';
                value = prop.initialTime || '';
                break;
            case 'datetime':
                emoji = '📅';
                value = prop.initialDatetime || '';
                break;
            default:
                emoji = '📅';
        }
        if (value)
            value = normalizeTimeFormat(value);
        if (!value) {
            let placeholder = '选择';
            const phElem = prop.placeholder;
            if (phElem && typeof phElem === 'object') {
                const ph = this.extractTextContent(phElem);
                if (ph)
                    placeholder = ph;
            }
            value = placeholder;
        }
        return `${emoji} ${value}`;
    }
    convertChecker(prop, _id) {
        const checked = prop.checked === true;
        const checkMark = checked ? '[x]' : '[ ]';
        let text = '';
        const textElem = prop.text;
        if (textElem && typeof textElem === 'object') {
            text = this.extractTextContent(textElem);
        }
        let result = `${checkMark} ${text}`;
        if (this.mode === MODE.Detailed && _id) {
            result += `(id:${_id})`;
        }
        return result;
    }
    convertOverflow(prop) {
        const options = prop.options;
        if (!Array.isArray(options) || options.length === 0)
            return '';
        const optTexts = [];
        for (const opt of options) {
            if (typeof opt !== 'object' || opt === null)
                continue;
            const om = opt;
            const textElem = om.text;
            if (textElem && typeof textElem === 'object') {
                const text = this.extractTextContent(textElem);
                if (text)
                    optTexts.push(text);
            }
        }
        return `⋮ ${optTexts.join(', ')}`;
    }
    convertPerson(prop, _id) {
        const userID = prop.userID || '';
        if (!userID)
            return '';
        let personName = '';
        if (this.attachment) {
            const persons = this.attachment.persons;
            if (persons && typeof persons === 'object') {
                const person = persons[userID];
                if (person && typeof person === 'object') {
                    const content = person.content;
                    if (content)
                        personName = content;
                }
            }
        }
        if (!personName) {
            const notation = prop.notation;
            if (notation && typeof notation === 'object') {
                personName = this.extractTextContent(notation);
            }
        }
        if (personName) {
            if (this.mode === MODE.Detailed)
                return `@${personName}(open_id:${userID})`;
            return `@${personName}`;
        }
        if (this.mode === MODE.Detailed)
            return `@用户(open_id:${userID})`;
        return `@${userID}`;
    }
    convertPersonV1(prop, _id) {
        const userID = prop.userID || '';
        if (!userID)
            return '';
        let personName = '';
        if (this.attachment) {
            const persons = this.attachment.persons;
            if (persons && typeof persons === 'object') {
                const person = persons[userID];
                if (person && typeof person === 'object') {
                    const content = person.content;
                    if (content)
                        personName = content;
                }
            }
        }
        if (personName) {
            if (this.mode === MODE.Detailed)
                return `@${personName}(open_id:${userID})`;
            return `@${personName}`;
        }
        if (this.mode === MODE.Detailed)
            return `@用户(open_id:${userID})`;
        return `@${userID}`;
    }
    convertPersonList(prop) {
        const persons = prop.persons;
        if (!Array.isArray(persons) || persons.length === 0)
            return '';
        const names = [];
        for (const person of persons) {
            if (typeof person !== 'object' || person === null)
                continue;
            const pm = person;
            const personID = pm.id || '';
            const name = '用户';
            if (this.mode === MODE.Detailed && personID) {
                names.push(`@${name}(id:${personID})`);
            }
            else {
                names.push(`@${name}`);
            }
        }
        return names.join(', ');
    }
    convertAvatar(prop, _id) {
        const userID = prop.userID || '';
        let result = '👤';
        if (this.mode === MODE.Detailed && userID) {
            result += `(id:${userID})`;
        }
        return result;
    }
    convertAt(prop) {
        const userID = prop.userID || '';
        if (!userID)
            return '';
        let userName = '';
        let actualUserID = '';
        if (this.attachment) {
            const atUsers = this.attachment.at_users;
            if (atUsers && typeof atUsers === 'object') {
                const userInfo = atUsers[userID];
                if (userInfo && typeof userInfo === 'object') {
                    const content = userInfo.content;
                    if (content)
                        userName = content;
                    const uid = userInfo.user_id;
                    if (uid)
                        actualUserID = uid;
                }
            }
        }
        if (userName) {
            if (this.mode === MODE.Detailed) {
                if (actualUserID)
                    return `@${userName}(user_id:${actualUserID})`;
                return `@${userName}(open_id:${userID})`;
            }
            return `@${userName}`;
        }
        if (this.mode === MODE.Detailed) {
            if (actualUserID)
                return `@用户(user_id:${actualUserID})`;
            return `@用户(open_id:${userID})`;
        }
        return `@${userID}`;
    }
    convertImage(prop, _id) {
        let alt = '图片';
        const altElem = prop.alt;
        if (altElem && typeof altElem === 'object') {
            const altText = this.extractTextContent(altElem);
            if (altText)
                alt = altText;
        }
        const titleElem = prop.title;
        if (titleElem && typeof titleElem === 'object') {
            const titleText = this.extractTextContent(titleElem);
            if (titleText)
                alt = titleText;
        }
        let result = `🖼️ ${alt}`;
        if (this.mode === MODE.Detailed) {
            const imageID = prop.imageID;
            if (imageID) {
                const token = this.getImageToken(imageID);
                if (token) {
                    result += `(img_token:${token})`;
                }
                else {
                    result += `(img_key:${imageID})`;
                }
            }
        }
        return result;
    }
    convertImgCombination(prop) {
        const imgList = prop.imgList;
        if (!Array.isArray(imgList) || imgList.length === 0)
            return '';
        let result = `🖼️ ${imgList.length}张图片`;
        if (this.mode === MODE.Detailed) {
            const keys = [];
            for (const img of imgList) {
                if (typeof img !== 'object' || img === null)
                    continue;
                const im = img;
                const imageID = im.imageID;
                if (imageID)
                    keys.push(imageID);
            }
            if (keys.length > 0)
                result += `(keys:${keys.join(',')})`;
        }
        return result;
    }
    convertChart(prop, _id) {
        let title = '图表';
        let chartType = '';
        const chartSpec = prop.chartSpec;
        if (chartSpec && typeof chartSpec === 'object') {
            const titleObj = chartSpec.title;
            if (titleObj && typeof titleObj === 'object') {
                const text = titleObj.text;
                if (text)
                    title = text;
            }
            const ct = chartSpec.type;
            if (ct) {
                chartType = ct;
                const typeName = CHART_TYPE_NAMES[chartType];
                if (typeName)
                    title = `${title}${typeName}`;
            }
        }
        const summary = this.extractChartSummary(prop, chartType);
        let result = `📊 ${title}`;
        if (summary)
            result += `\n数据摘要: ${summary}`;
        return result;
    }
    extractChartSummary(prop, chartType) {
        const chartSpec = prop.chartSpec;
        if (!chartSpec || typeof chartSpec !== 'object')
            return '';
        const dataObj = chartSpec.data;
        if (!dataObj || typeof dataObj !== 'object')
            return '';
        const values = dataObj.values;
        if (!Array.isArray(values) || values.length === 0)
            return '';
        switch (chartType) {
            case 'line':
            case 'bar':
            case 'area':
                return this.extractLineBarSummary(chartSpec, values);
            case 'pie':
                return this.extractPieSummary(chartSpec, values);
            default:
                return this.extractGenericSummary(values);
        }
    }
    extractLineBarSummary(chartSpec, values) {
        const xField = chartSpec.xField;
        const yField = chartSpec.yField;
        if (!xField || !yField || values.length === 0) {
            return this.extractGenericSummary(values);
        }
        const parts = [];
        for (const v of values) {
            if (typeof v !== 'object' || v === null)
                continue;
            const vm = v;
            parts.push(`${vm[xField]}:${vm[yField]}`);
        }
        return parts.length > 0 ? parts.join(', ') : this.extractGenericSummary(values);
    }
    extractPieSummary(chartSpec, values) {
        const categoryField = chartSpec.categoryField;
        const valueField = chartSpec.valueField;
        if (!categoryField || !valueField || values.length === 0) {
            return this.extractGenericSummary(values);
        }
        const parts = [];
        for (const v of values) {
            if (typeof v !== 'object' || v === null)
                continue;
            const vm = v;
            parts.push(`${vm[categoryField]}:${vm[valueField]}`);
        }
        return parts.length > 0 ? parts.join(', ') : this.extractGenericSummary(values);
    }
    extractGenericSummary(values) {
        return `${values.length}个数据点`;
    }
    convertAudio(prop, _id) {
        let result = '🎵 音频';
        if (this.mode === MODE.Detailed) {
            const fileID = prop.fileID || prop.audioID || '';
            if (fileID)
                result += `(key:${fileID})`;
        }
        return result;
    }
    convertVideo(prop, _id) {
        let result = '🎬 视频';
        if (this.mode === MODE.Detailed) {
            const fileID = prop.fileID || prop.videoID || '';
            if (fileID)
                result += `(key:${fileID})`;
        }
        return result;
    }
    convertTable(prop) {
        const columns = prop.columns;
        if (!Array.isArray(columns) || columns.length === 0)
            return '';
        const rows = prop.rows || [];
        const colNames = [];
        const colKeys = [];
        for (const col of columns) {
            if (typeof col !== 'object' || col === null)
                continue;
            const cm = col;
            let displayName = cm.displayName || '';
            const name = cm.name || '';
            if (!displayName)
                displayName = name;
            colNames.push(displayName);
            colKeys.push(name);
        }
        const lines = [];
        lines.push('| ' + colNames.join(' | ') + ' |');
        lines.push('|' + colNames.map(() => '------|').join(''));
        for (const row of rows) {
            if (typeof row !== 'object' || row === null)
                continue;
            const rm = row;
            const cells = [];
            for (const key of colKeys) {
                let cellValue = '';
                const cellData = rm[key];
                if (cellData && typeof cellData === 'object') {
                    if (cellData.data != null) {
                        cellValue = this.extractTableCellValue(cellData.data);
                    }
                }
                cells.push(cellValue);
            }
            lines.push('| ' + cells.join(' | ') + ' |');
        }
        return lines.join('\n');
    }
    extractTableCellValue(data) {
        if (typeof data === 'string')
            return data;
        if (typeof data === 'number')
            return data.toFixed(2);
        if (Array.isArray(data)) {
            const texts = [];
            for (const item of data) {
                if (typeof item === 'object' && item !== null) {
                    const im = item;
                    if (typeof im.text === 'string')
                        texts.push(`「${im.text}」`);
                }
            }
            return texts.join(' ');
        }
        if (typeof data === 'object' && data !== null) {
            return this.extractTextContent(data);
        }
        return '';
    }
    extractTextStyle(prop) {
        const style = {
            bold: false,
            italic: false,
            strikethrough: false,
        };
        const textStyle = prop.textStyle;
        if (!textStyle || typeof textStyle !== 'object')
            return style;
        const attrs = textStyle.attributes;
        if (Array.isArray(attrs)) {
            for (const attr of attrs) {
                if (typeof attr !== 'string')
                    continue;
                switch (attr) {
                    case 'bold':
                        style.bold = true;
                        break;
                    case 'italic':
                        style.italic = true;
                        break;
                    case 'strikethrough':
                        style.strikethrough = true;
                        break;
                }
            }
        }
        return style;
    }
    applyTextStyle(content, style) {
        if (!content)
            return content;
        if (style.strikethrough)
            content = `~~${content}~~`;
        if (style.italic)
            content = `*${content}*`;
        if (style.bold)
            content = `**${content}**`;
        return content;
    }
    getImageToken(imageID) {
        if (!this.attachment)
            return '';
        const images = this.attachment.images;
        if (!images || typeof images !== 'object')
            return '';
        const imageInfo = images[imageID];
        if (!imageInfo || typeof imageInfo !== 'object')
            return '';
        return imageInfo.token || '';
    }
}
