import { TextMessagePart } from '../../../main/aikernel/messages';

async function renderCodeBlock(code: string, lang?: string): Promise<string> {
    const fence = '```';
    const source = lang ? `${fence}${lang}\n${code}\n${fence}` : `${fence}\n${code}\n${fence}`;
    const part = new TextMessagePart(source);
    await part.render();
    return part.rendered || '';
}

describe('代码块渲染(pre/code + CSS 计数器行号)', () => {
    test('输出 pre/code 结构且不再使用逐行表格', async () => {
        const html = await renderCodeBlock('const a = 1;\nconst b = 2;', 'javascript');
        expect(html).toContain('<pre class="code-block-pre font-mono"><code class="code-lines">');
        expect(html).toContain('<span class="code-line font-mono">');
        expect(html).not.toContain('<table');
        expect(html).not.toContain('td');
    });

    test('行数与代码行一一对应,行号不在 HTML 文本中(由 CSS 计数器生成)', async () => {
        const html = await renderCodeBlock('line-one\nline-two\nline-three', 'plaintext');
        const lineSpans = html.match(/<span class="code-line font-mono">/g) || [];
        expect(lineSpans).toHaveLength(3);
        expect(html).not.toMatch(/>(\d+)<\/span>/);
        expect(html).toContain('line-one');
        expect(html).toContain('line-three');
    });

    test('每行保留 hljs 高亮标记', async () => {
        const html = await renderCodeBlock('const a = 1;', 'javascript');
        expect(html).toContain('hljs-');
    });

    test('跨行注释的每个代码行都包含闭合的高亮标签', async () => {
        const html = await renderCodeBlock('/**\n * comment\n */\nconst value = 1;', 'typescript');
        const expectedCommentLines = [
            '<span class="code-line font-mono"><span class="hljs-comment">/**</span></span>',
            '<span class="code-line font-mono"><span class="hljs-comment"> * comment</span></span>',
            '<span class="code-line font-mono"><span class="hljs-comment"> */</span></span>'
        ];

        for (const line of expectedCommentLines) {
            expect(html).toContain(line);
        }
    });

    test('空行渲染为占位空格,保持行框高度', async () => {
        const html = await renderCodeBlock('first\n\nthird', 'plaintext');
        const lineSpans = html.match(/<span class="code-line font-mono">[^<]*<\/span>/g) || [];
        expect(lineSpans.some((span) => span.includes('> <'))).toBe(true);
    });

    test('可预览语言保留 data-previewable 与 data-raw-code 属性', async () => {
        const html = await renderCodeBlock('<p>hi</p>', 'html');
        expect(html).toContain('data-previewable="true"');
        expect(html).toContain('data-preview-lang="html"');
        const rawCode = Buffer.from('<p>hi</p>').toString('base64');
        expect(html).toContain(`data-raw-code="${rawCode}"`);
    });

    test('mermaid 代码块仍输出占位容器,不受新结构影响', async () => {
        const html = await renderCodeBlock('graph TD;\nA-->B;', 'mermaid');
        expect(html).toContain('mermaid-block');
        expect(html).not.toContain('code-lines');
    });
});