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

const run = (command: string, args: string[], cwd?: string) =>
  execFileSync(command, args, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();

test("glab mr new durably links the created merge request to its thread", WEB, async ({ t3, app, screen, browser }) => {
  const project = await t3.project("gitlab-alias-proof", { "README.md": "GitLab alias proof\n" });
  const remote = JSON.parse(run("glab", ["api", "projects", "--method", "POST", "-f", `name=t3-alias-proof-${Date.now()}`, "-f", "visibility=private", "-f", "initialize_with_readme=false"]));
  const recording = join(APP_DIR, "apps/server/scripts/dev-replay/command_output_transcript.ndjson");
  const original = readFileSync(recording, "utf8");
  try {
    run("git", ["remote", "add", "origin", remote.http_url_to_repo], project);
    run("git", ["push", "-u", "origin", "main"], project);
    run("git", ["checkout", "-b", "feature/alias-new"], project);
    writeFileSync(join(project, "alias.txt"), "MR new alias\n");
    run("git", ["add", "alias.txt"], project);
    run("git", ["-c", "user.name=Scenario", "-c", "user.email=scenario@example.invalid", "commit", "-m", "Verify merge request alias"], project);
    run("git", ["push", "-u", "origin", "feature/alias-new"], project);
    const command = "glab mr new --fill --yes --target-branch main";
    const output = run("glab", ["mr", "new", "--fill", "--yes", "--target-branch", "main"], project);
    const url = output.match(/https:\/\/gitlab.com\/\S+\/-\/merge_requests\/\d+/)?.[0];
    if (!url) throw new Error("glab did not print the created merge request URL");
    // Replay the actual successful command result through the real ACP adapter and server.
    const rows = original.trim().split("\n").map((line) => JSON.parse(line));
    rows[2].frame.params.update.title = command;
    rows[2].frame.params.update.rawInput = { command };
    rows[3].frame.params.update.rawOutput = `${output}\n`;
    rows[4].frame.params.update.content.text = "Created the merge request with glab mr new. No link tool was called.";
    writeFileSync(recording, rows.map((row) => JSON.stringify(row)).join("\n") + "\n");
    const thread = await t3.thread({ project, title: "GitLab mr new alias", model: "command-output", messages: ["Run only glab mr new --fill --yes --target-branch main; do not call link_pull_request."] });
    await t3.open(thread);
    await screen.getByRole("button", "Worked for", { exact: false }).tap();
    await screen.getByRole("button", /^glab mr new --fill/).tap();
    await screen.getByText(url, { exact: false }).first().waitFor();
    await app.screenshot("command-result");
    await browser.keyboard.press("Control+k");
    await screen.getByRole("combobox").fill("Show linked pull requests");
    await screen.getByText("Searching messages...", { exact: false }).waitFor({ state: "hidden" });
    const state = JSON.parse(run(process.execPath, ["apps/server/src/bin.ts", "thread", "show", thread.threadId, "--json", "--base-dir", T3_HOME], APP_DIR));
    await browser.keyboard.press("Enter");
    if ((state.thread.pullRequests ?? []).length > 0) {
      await screen.getByRole("dialog", "Command palette").waitFor({ state: "hidden" });
      await screen.getByText("Verify merge request alias", { exact: true }).last().waitFor();
    }
    await app.screenshot("durable-link");
    await expect((state.thread.pullRequests ?? []).some((link: { source: string; url: string }) => link.source === "created" && link.url === url)).toBe(true);
  } finally {
    writeFileSync(recording, original);
    run("glab", ["api", `projects/${remote.id}`, "--method", "DELETE"]);
  }
});
