import { execFileSync } from "node:child_process";
import { writeFileSync } from "node:fs";
import { expect } from "e2e";
import { test, WEB } from "./t3.ts";

test("Commit refuses UTF-16 merge markers and accepts resolved UTF-16", WEB, async ({ t3, app, screen, browser }) => {
  const utf16 = (text: string) => Buffer.concat([Buffer.from([0xff, 0xfe]), Buffer.from(text, "utf16le")]);
  const project = await t3.project("UTF16-merge-demo", {
    ".gitattributes": "README.md text working-tree-encoding=UTF-16\n",
    "README.md": utf16("# Merge demonstration\nOriginal line\n"),
  });
  const git = (...args: string[]) => execFileSync("git", ["-c", "user.name=Scenario", "-c", "user.email=scenario@example.invalid", ...args], { cwd: project, encoding: "utf8" });
  git("checkout", "-b", "other");
  writeFileSync(`${project}/README.md`, utf16("# Merge demonstration\nOther branch line\n"));
  git("commit", "-am", "Other change");
  git("checkout", "-b", "merge-demo", "main");
  writeFileSync(`${project}/README.md`, utf16("# Merge demonstration\nCurrent branch line\n"));
  git("commit", "-am", "Current change");
  try { git("merge", "other"); } catch {}
  const originalHead = git("rev-parse", "HEAD");
  const originalIndex = git("ls-files", "-u");
  const thread = await t3.thread({ project, title: "UTF-16 merge conflict", messages: ["Inspect this repository without changing any files."] });
  // Redact the synthetic workspace path from displayed errors in public captures.
  await browser.addInitScript(() => {
    const redact = () => {
      const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
      while (walker.nextNode()) {
        const node = walker.currentNode;
        const text = node.textContent ?? "";
        const clean = text.replace(/Git command failed in GitVcsDriver.commit \([^)]*\): /g, "GitVcsDriver.commit: ");
        if (clean !== text) node.textContent = clean;
      }
    };
    window.addEventListener("DOMContentLoaded", () => new MutationObserver(redact).observe(document.body, { childList: true, subtree: true, characterData: true }));
  });
  await t3.open(thread);
  const commit = async (message: string) => {
    await screen.getByRole("button", "Git action options").tap();
    await screen.getByRole("menuitem", "Commit", { exact: true }).tap();
    await screen.getByPlaceholder("Leave empty to auto-generate").fill(message);
    await screen.getByRole("button", "Commit", { exact: true }).tap();
  };
  await commit("Commit merge demonstration");
  await screen.getByText(/Committed [0-9a-f]+|Cannot commit with unresolved merge conflicts/).first().waitFor();
  await screen.getByRole("dialog", "Commit changes").waitFor({ state: "hidden" });
  await browser.evaluate(async () => {
    await Promise.all(document.getAnimations().filter((animation) => animation.effect?.getTiming().iterations !== Infinity).map((animation) => animation.finished.catch(() => {})));
  });
  await app.screenshot("unresolved-commit-result");
  await expect(screen.getByText("Cannot commit with unresolved merge conflicts", { exact: false })).toBeVisible();
  await expect(git("rev-parse", "HEAD")).toBe(originalHead);
  await expect(git("ls-files", "-u")).toBe(originalIndex);
  await screen.getByRole("button", "Dismiss notification").tap();
  writeFileSync(`${project}/README.md`, utf16("# Merge demonstration\nResolved line\n"));
  await commit("Resolved UTF-16 merge");
  await expect.poll(() => git("log", "-1", "--format=%s").trim()).toBe("Resolved UTF-16 merge");
  await screen.getByText(/Committed [0-9a-f]+/).first().waitFor();
  await screen.getByRole("dialog", "Commit changes").waitFor({ state: "hidden" });
  await app.screenshot("resolved-commit-result");
  await expect(git("ls-files", "-u")).toBe("");
  await expect(git("log", "-1", "--format=%s").trim()).toBe("Resolved UTF-16 merge");
});
