import { expect } from "e2e";
import { execFileSync } from "node:child_process";
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
import { join } from "node:path";
import { APP_DIR } from "../e2e.config.ts";
import { test, WEB } from "./t3.ts";

test("Relative file link opens a file in a gitignored nested worktree", WEB, async ({ t3, app, screen, browser }) => {
  const project = await t3.project("File link demo", {
    ".gitignore": ".worktrees/\n",
    "backend/lib/bar.py": "def bar():\n    return 'SUBFOLDER_FILE_OPENED'\n",
  });
  const worktree = join(project, ".worktrees/x");
  execFileSync("git", ["worktree", "add", "-b", "file-link-demo", worktree], { cwd: project });
  mkdirSync(join(worktree, "src"), { recursive: true });
  writeFileSync(join(worktree, "src/foo.py"), "def foo():\n    return 'WORKTREE_FILE_OPENED'\n");
  execFileSync("git", ["add", "src/foo.py"], { cwd: worktree });
  execFileSync("git", ["-c", "user.name=Scenario", "-c", "user.email=scenario@example.invalid", "commit", "-m", "Add worktree file"], { cwd: worktree });
  const transcript = join(APP_DIR, "apps/server/scripts/dev-replay/showcase_transcript.ndjson");
  const original = readFileSync(transcript, "utf8");
  const frames = [
    { type: "expect_outbound", frame: { kind: "request", method: "session/prompt" } },
    { type: "emit_inbound", frame: { kind: "notification", method: "session/update", params: { sessionId: "demo", update: { sessionUpdate: "agent_message_chunk", content: { type: "text", text: "The worktree file is `src/foo.py`. The subfolder file is `lib/bar.py`." } } } } },
    { type: "emit_inbound", frame: { kind: "response", method: "session/prompt", result: { stopReason: "end_turn" } } },
  ];
  try {
    writeFileSync(transcript, frames.map((frame) => JSON.stringify(frame)).join("\n") + "\n");
    await t3.thread({ project, title: "Relative file links", messages: ["Show the worktree and subfolder file links."], model: "showcase" });
  } finally { writeFileSync(transcript, original); }
  await t3.open();
  await screen.getByRole("button", "Relative file links, Done, File link demo").tap();
  await screen.getByRole("link", "foo.py").tap();
  // Let the viewer finish its read before capturing either the error or the file.
  await screen.getByText(/WORKTREE_FILE_OPENED|The file could not be accessed or read/).first().waitFor({ state: "visible" });
  await browser.keyboard.press("Escape");
  await browser.evaluate(() => { (document.activeElement as HTMLElement)?.blur(); });
  let previous = await app.screenshot("worktree-file-link");
  let stable = false;
  for (let i = 0; i < 10; i++) {
    await new Promise((resolve) => setTimeout(resolve, 500));
    const current = await app.screenshot("worktree-file-link-stable");
    if (readFileSync(previous).equals(readFileSync(current))) { stable = true; break; }
    previous = current;
  }
  if (!stable) throw new Error("Capture was not stable");
  await expect(screen.getByText("WORKTREE_FILE_OPENED", { exact: false })).toBeVisible();
});
