import assert from "node:assert/strict";
import { test } from "bun:test";
import { renderToStaticMarkup } from "react-dom/server";

import { MarkdownRenderer } from "./MarkdownRenderer";
import { MessageMarkdown, PlainMessageText } from "./MessageMarkdown";

test("message markdown module renders through the shared third-party renderer immediately", async () => {
  const source = await Bun.file(new URL("./MessageMarkdown.tsx", import.meta.url)).text();

  assert.doesNotMatch(source, /from "react-markdown"/u);
  assert.doesNotMatch(source, /setTimeout/u);
  assert.doesNotMatch(source, /PlainMessageText>\{children\}<\/PlainMessageText/u);
  assert.match(source, /<MarkdownRenderer>\{children\}<\/MarkdownRenderer>/u);
});

test("markdown renderer renders GFM tables and inline code through the shared third-party component", () => {
  const html = renderToStaticMarkup(
    <MarkdownRenderer>{"| Key | Value |\n| --- | --- |\n| **status** | `ok` |"}</MarkdownRenderer>
  );

  assert.match(html, /<table>/u);
  assert.match(html, /<strong>status<\/strong>/u);
  assert.match(html, /<code>ok<\/code>/u);
});

test("message markdown escapes raw HTML instead of injecting handwritten HTML", () => {
  const html = renderToStaticMarkup(<MarkdownRenderer>{"<script>alert(1)</script>"}</MarkdownRenderer>);

  assert.doesNotMatch(html, /<script>/u);
  assert.match(html, /&lt;script&gt;alert\(1\)&lt;\/script&gt;/u);
});

test("message markdown preserves source newlines for final response display", () => {
  const html = renderToStaticMarkup(<MessageMarkdown>{"第一行\n\n第二行"}</MessageMarkdown>);

  assert.match(html, /class="message-body"/u);
  assert.match(html, /<p>第一行<\/p>/u);
  assert.match(html, /<p>第二行<\/p>/u);
});

test("plain first-screen fallback escapes raw HTML", () => {
  const html = renderToStaticMarkup(<PlainMessageText>{"<script>alert(1)</script>"}</PlainMessageText>);

  assert.doesNotMatch(html, /<script>/u);
  assert.match(html, /&lt;script&gt;alert\(1\)&lt;\/script&gt;/u);
});
