import { expect } from "e2e";
import { APP_DIR, T3_HOME } from "../e2e.config.ts";
import { run } from "./shell.ts";
import { runPromise, test, WEB } from "./t3.ts";

test("A stale scheduled worktree base names master and its project", WEB, async ({ t3, app, screen, browser }) => {
  const project = await t3.project("demo-repo");
  const git = (...args: string[]) => runPromise(run("git", args, { cwd: project }));
  await git("branch", "-m", "dev");
  await git("branch", "master");
  const remote = `${project}/../remote.git`;
  await git("init", "--bare", remote);
  await git("remote", "add", "origin", remote);
  await git("push", "-u", "origin", "dev", "master");
  await runPromise(run("git", ["symbolic-ref", "HEAD", "refs/heads/dev"], { cwd: remote }));
  // Redact fixture paths and the ephemeral webhook credential in public captures.
  await browser.addInitScript((fixturePath: string) => {
    const scrub = () => {
      if (!document.documentElement) return;
      const walker = document.createTreeWalker(document.documentElement, NodeFilter.SHOW_TEXT);
      for (let node = walker.nextNode(); node; node = walker.nextNode()) {
        if (node.nodeValue?.includes(fixturePath)) node.nodeValue = node.nodeValue.replaceAll(fixturePath, "[fixture path redacted]");
      }
      for (const input of document.querySelectorAll<HTMLInputElement>('[aria-label="Webhook URL"], #pairing-token')) input.style.color = "transparent";
    };
    new MutationObserver(scrub).observe(document, { subtree: true, childList: true, characterData: true });
  }, project);
  await t3.open("/settings/scheduled-tasks");
  await screen.getByRole("button", "New task", { exact: true }).tap();
  await screen.getByLabel("Name", { exact: true }).fill("Stale base task");
  await screen.getByLabel("Workspace", { exact: true }).tap();
  await screen.getByRole("option", "Create a new worktree", { exact: true }).tap();
  await screen.getByLabel("Base branch", { exact: true }).tap();
  await screen.getByText("master", { exact: true }).first().tap();
  await screen.getByLabel("Prompt", { exact: true }).fill("Say hello");
  await screen.getByRole("button", "On webhook", { exact: true }).tap();
  await screen.getByRole("button", "Create task", { exact: true }).tap();
  await screen.getByRole("button", "Actions for Stale base task").tap();
  await screen.getByRole("menuitem", "Edit", { exact: true }).tap();
  const webhook = await screen.getByLabel("Webhook URL", { exact: true }).inputValue();
  await screen.getByRole("button", "Save task", { exact: true }).tap();
  await git("branch", "-D", "master");
  await git("push", "origin", "--delete", "master");
  const response = await fetch(webhook, { method: "POST", headers: { "Content-Type": "application/json" }, body: "{}" });
  if (response.status !== 202) throw new Error(`Webhook returned ${response.status}`);
  const listed = await runPromise(run(process.execPath, ["apps/server/src/bin.ts", "thread", "list", "--project", project, "--json", "--base-dir", T3_HOME], { cwd: APP_DIR, env: { PATH: process.env.PATH, HOME: process.env.HOME } }));
  const threads = JSON.parse(listed.stdout);
  const thread = threads.find((t: {title: string}) => t.title === "Stale base task");
  if (!thread) throw new Error("Webhook did not create its thread");
  await t3.open(thread);
  await screen.getByRole("button", "Retry", { exact: true }).waitFor({ state: "visible" });
  await app.screenshot("missing-base-error");
  await expect(screen.getByText('Base ref "master" does not resolve to a commit in project "demo-repo"', { exact: false }).first()).toBeVisible();
});
