import { readFile } from "node:fs/promises";
import { setTimeout } from "node:timers/promises";
import { expect } from "e2e";
import { test, WEB } from "./t3.ts";

const theme = {
  version: 1,
  id: "message-foreground-repro",
  name: "Message foreground repro",
  appearance: "dark",
  colors: {
    canvas: "oklch(0.288241 0.006169 258.356)",
    text: "oklch(0.763576 0 0)",
    messageSurface: "oklch(0.711982 0.172356 297.202)",
    messageForeground: "oklch(0.222003 0.03479 328.979)",
  },
};
const message = "This should be dark text on a purple bubble.\n\n**Bold message text** and *emphasized message text*.\n\n- First list item\n- Second list item with `inline code`\n\n```text\nPlain-text fence keeps its readable foreground.\n```";

test("Sent messages honor the imported theme foreground, including after reload", WEB, async ({ t3, app, screen, browser }) => {
  const project = await t3.project("Theme demo");
  await t3.thread({ project, title: "Message foreground", messages: ["Hello"], model: "multi-turn" });
  await t3.open();
  await screen.getByText("Message foreground", { exact: true }).first().waitFor();
  await app.open("/settings/appearance");
  await screen.getByRole("button", "Use dark mode", { exact: true }).tap();
  await screen.getByRole("button", "Add theme", { exact: true }).tap();
  await screen.getByRole("textbox", "Theme JSON").fill(JSON.stringify(theme, null, 2));
  await screen.getByRole("button", "Add theme", { exact: true }).last().tap();
  await screen.getByRole("button", "Use Message foreground repro theme", { exact: false }).waitFor();
  await app.open("/");
  await screen.getByRole("button", "Message foreground, Done, Theme demo", { exact: true }).tap();
  await screen.getByRole("textbox", "Message Message foreground", { exact: true }).fill(message);
  await screen.getByRole("button", "Submit message", { exact: true }).tap();
  await screen.getByText("second fixture turn complete", { exact: false }).waitFor();
  await browser.locator(".user-message-markdown").waitFor();
  const stableCapture = async (label: string) => {
    for (let attempt = 0; attempt < 6; attempt++) {
      const first = await app.screenshot(`${label}-stability-${attempt}`);
      await setTimeout(500);
      const second = await app.screenshot(label);
      if ((await readFile(first)).equals(await readFile(second))) return;
    }
    throw new Error("The capture did not settle");
  };
  await screen.getByText("Syncing messages…", { exact: true }).waitFor({ state: "hidden" });
  await stableCapture("message-foreground");
  const path = await browser.evaluate(() => location.pathname);
  await app.open(path);
  await browser.locator(".user-message-markdown").waitFor();
  await screen.getByText("Syncing messages…", { exact: true }).waitFor({ state: "hidden" });
  await stableCapture("message-foreground-after-reload");
  const colors = await browser.evaluate(() => {
    const body = document.querySelector(".user-message-markdown")!;
    const probe = document.createElement("span");
    body.append(probe);
    const role = (name: string) => {
      probe.style.color = `var(${name})`;
      return getComputedStyle(probe).color;
    };
    const messageColor = role("--contrast-message-foreground");
    const globalColor = role("--contrast-foreground");
    probe.remove();
    const color = (selector: string) => getComputedStyle(body.querySelector(selector)!).color;
    return {
      prose: color("p") === messageColor,
      bold: color("strong") === messageColor,
      emphasis: color("em") === messageColor,
      list: color("li") === messageColor,
      inlineCode: color(":not(pre) > code") === messageColor,
      fence: color(".chat-markdown-codeblock[data-language='text']") === globalColor,
    };
  });
  expect(colors).toEqual({ prose: true, bold: true, emphasis: true, list: true, inlineCode: true, fence: true });
});
