import { execFileSync } from "node:child_process";
import { createServer, type Socket } from "node:net";
import { expect } from "e2e";
import { test, WEB } from "./t3.ts";

test("Side chat opens after cancelled worktree setup and a completed checkout run", WEB, async ({ t3, app, screen, browser }) => {
  const sockets = new Set<Socket>();
  const remote = createServer((socket) => { sockets.add(socket); socket.on("close", () => sockets.delete(socket)); });
  await new Promise<void>((resolve) => remote.listen(0, "127.0.0.1", resolve));
  try {
    const project = await t3.project("Interrupted setup");
    const git = (...args: string[]) => execFileSync("git", args, { cwd: project });
    git("branch", "-m", "dev");
    const port = (remote.address() as { port: number }).port;
    git("remote", "add", "origin", `http://127.0.0.1:${port}/repo.git`);
    git("update-ref", "refs/remotes/origin/dev", "HEAD");
    git("config", "branch.dev.remote", "origin");
    git("config", "branch.dev.merge", "refs/heads/dev");
    await t3.open();
    await screen.getByRole("combobox", "Workspace").tap();
    await screen.getByRole("option", "New worktree").tap();
    await screen.getByRole("textbox").fill("Say hello");
    await screen.getByRole("textbox").press("Enter");
    await screen.getByText("Fetch base branch", { exact: false }).first().waitFor();
    await app.screenshot("fetching-base-branch");
    await screen.getByRole("button", "Cancel", { exact: true }).tap();
    await screen.getByText("Worktree setup cancelled", { exact: false }).first().waitFor();
    await screen.getByRole("textbox").fill("Reply with the word ok");
    await screen.getByRole("textbox").press("Enter");
    await screen.getByText("This turn is a replay.", { exact: false }).first().waitFor({ timeout: 120000 });
    await screen.getByRole("button", "Stop generation").waitFor({ state: "hidden" });
    await screen.getByRole("textbox").fill("/side");
    await app.screenshot("side-chat-after-checkout-run");
    await expect(screen.getByText("Available once the thread's worktree is set up.", { exact: false })).toBeHidden();
    await screen.getByRole("textbox").press("Escape");
    await screen.getByRole("textbox").fill("/side Say hello in this side chat");
    await screen.getByRole("textbox").press("Enter");
    await expect(browser.locator("[data-side-chat-pane]")).toBeVisible();
    await app.screenshot("side-chat-open");
  } finally {
    for (const socket of sockets) socket.destroy();
    await new Promise<void>((resolve) => remote.close(() => resolve()));
  }
});
