import { expect } from "e2e";
import { execFileSync, spawnSync } from "node:child_process";
import { writeFileSync, existsSync, unlinkSync } from "node:fs";
import { test, WEB } from "./t3.ts";
const scratch = "/tmp/factory-pr-19764-evidence-3";
const git = (cwd: string, ...args: string[]) => execFileSync("git", args, { cwd, encoding: "utf8" }).trim();
const mode = process.env.SSH_PROOF_CONTROL ?? "stall";
test(`SSH fetch control: ${mode}`, WEB, async ({ t3, app, screen, browser }) => {
  await browser.setViewport({ width: 1600, height: 1100 });
  const stableCapture = async (label: string) => {
    await browser.mouse.move(1400, 800);
    await browser.mouse.down();
    await browser.mouse.up();
    await browser.mouse.move(1, 700);
    let previous = await app.screenshot(`${label}-settle-0`);
    for (let i = 1; i <= 12; i++) {
      await browser.evaluate(() => new Promise((resolve) => setTimeout(resolve, 500)));
      const next = await app.screenshot(`${label}-settle-${i}`);
      if (spawnSync("compare", ["-metric", "AE", previous, next, "null:"]).status === 0) {
        console.log(`Stable capture ${label}: ${next}`);
        return next;
      }
      previous = next;
    }
    throw new Error(`Capture never became pixel-identical: ${label}`);
  };
  writeFileSync(`${scratch}/remote-mode`, ["stall", "fail"].includes(mode) ? mode : "normal");
  if (["stall", "fail", "ref-lock-release", "ref-lock-held"].includes(mode)) writeFileSync(`${scratch}/approve`, "approve");
  else if (existsSync(`${scratch}/approve`)) unlinkSync(`${scratch}/approve`);
  const project = await t3.project(`SSH control ${mode}`, { "README.md": "Synthetic SSH fetch control\n", ...(mode === "gitmodules" ? { ".gitmodules": "" } : {}) });
  git(project, "clone", "--bare", project, `${project}-remote.git`);
  git(project, "remote", "add", "origin", `approval-proof:${project}-remote.git`);
  git(project, "update-ref", "refs/remotes/origin/main", "HEAD");
  git(project, "config", "branch.main.remote", "origin");
  git(project, "config", "branch.main.merge", "refs/heads/main");
  if (mode === "core-command") git(project, "config", "core.sshCommand", "ssh");
  if (mode === "variant") git(project, "config", "ssh.variant", "ssh");
  if (mode === "submodule") git(project, "config", "submodule.synthetic.url", "approval-proof:synthetic");
  await t3.open();
  await screen.getByRole("combobox", "Workspace").tap();
  await screen.getByRole("option", "New worktree").tap();
  await screen.getByRole("textbox").fill("Give me a short tour");
  await screen.getByText("From main (remote)", { exact: true }).first().waitFor();
  await stableCapture(`${mode}-before-fetch`);
  let expectedRemote = "";
  if (mode.startsWith("ref-lock")) {
    const oldHead = git(project, "rev-parse", "HEAD");
    git(project, "-c", "user.name=Scenario", "-c", "user.email=scenario@example.invalid", "commit", "--allow-empty", "-m", "Synthetic remote update");
    expectedRemote = git(project, "rev-parse", "HEAD");
    git(project, "push", `${project}-remote.git`, "HEAD:main");
    git(project, "reset", "--hard", oldHead);
    writeFileSync(`${project}/.git/refs/remotes/origin/main.lock`, "synthetic concurrent fetch lock");
    writeFileSync(`${scratch}/remote-mode`, mode);
  }
  await screen.getByRole("textbox").press("Enter");
  if (mode === "ref-lock-release") {
    await screen.getByText("This turn is a replay.", { exact: false }).waitFor({ timeout: 60000 });
    await screen.getByRole("button", "Stop generation").waitFor({ state: "hidden", timeout: 60000 });
    await stableCapture("ref-lock-retry-agent-finished");
    expect(git(project, "rev-parse", "origin/main")).toBe(expectedRemote);
    return;
  }
  await screen.getByText("Worktree setup failed", { exact: true }).waitFor({ state: "visible", timeout: 60000 });
  const notification = screen.getByRole("button", "Dismiss notification");
  if (await notification.count()) await notification.first().tap();
  const dismissError = screen.getByRole("button", "Dismiss error");
  if (await dismissError.count()) await dismissError.tap();
  await stableCapture(`${mode}-fetch-error`);
  const failure = await browser.evaluate(() => document.body.innerText);
  expect(failure).toContain(mode === "fail" ? "Git could not access the remote repository." : mode === "ref-lock-held" ? "Git could not update a local reference." : "Git command timed out.");
  expect(failure).not.toContain("SSH key authorization timed out.");
  expect(failure).not.toContain("debug1:");
  expect(failure).not.toContain("debug2:");
  expect(failure).not.toContain("debug3:");
});
