import { execFileSync } from "node:child_process";
import { writeFileSync, existsSync, unlinkSync } from "node:fs";
import { expect } from "e2e";
import { test, WEB } from "./t3.ts";

test("Remote selection attaches HEAD despite a same-named tag or a prior config lock", WEB, async ({ t3, app, screen, browser }) => {
  const project = await t3.project("remote-branch-proof");
  const git = (...args: string[]) => execFileSync("git", args, { cwd: project, encoding: "utf8" }).trim();
  git("init", "--bare", "--quiet", ".git/remote.git");
  git("remote", "add", "upstream", `${project}/.git/remote.git`);
  git("push", "--quiet", "upstream", "main:refs/heads/v1.2", "main:refs/heads/feature");
  git("fetch", "--quiet", "upstream");
  git("branch", "--track", "v1.2", "upstream/v1.2");
  git("tag", "v1.2");
  const branchPicker = () => screen.getByRole("region", "Version Control").getByRole("combobox");
  const select = async (name: string) => {
    await branchPicker().tap();
    await screen.getByRole("option").filter({ hasText: name }).tap();
  };
  let terminalOpen = false;
  const capture = async (label: string, remote: string, branch: string) => {
    writeFileSync(`${project}/.git/proof.sh`, [
      `echo REMOTE BRANCH SELECTION: ${remote}`,
      `echo Expected HEAD: refs/heads/${branch}`,
      "echo Actual HEAD:",
      "git symbolic-ref --quiet HEAD || echo DETACHED",
      "echo Local branch and upstream:",
      `git for-each-ref --format='%(refname) -> %(upstream)' refs/heads/${branch}`,
      "echo Verification complete",
      `touch .git/${label}-done`,
    ].join("\n"));
    if (!terminalOpen) {
      await screen.getByRole("button", "Toggle terminal drawer").tap();
      terminalOpen = true;
    }
    await screen.getByRole("textbox", "Terminal input").waitFor({ state: "attached" });
    await screen.getByRole("textbox", "Terminal input").focus();
    await browser.keyboard.type("clear; sh .git/proof.sh");
    await browser.keyboard.press("Enter");
    await expect.poll(() => existsSync(`${project}/.git/${label}-done`)).toBe(true);
    await app.screenshot(label);
  };
  await t3.open();
  await select("upstream/v1.2");
  await expect.poll(() => git("rev-parse", "--symbolic-full-name", "HEAD")).not.toBe("refs/heads/main");
  const tagHead = git("rev-parse", "--symbolic-full-name", "HEAD");
  await capture("same-named-tag", "upstream/v1.2", "v1.2");

  await screen.getByRole("button", "Toggle terminal drawer").tap();
  terminalOpen = false;
  await select("main");
  await expect.poll(() => git("rev-parse", "--symbolic-full-name", "HEAD")).toBe("refs/heads/main");
  writeFileSync(`${project}/.git/config.lock`, "held by reproduction\n");
  await select("upstream/feature");
  await screen.getByText("Failed to switch ref.", { exact: true }).waitFor();
  const leftover = git("for-each-ref", "--format=%(refname)", "refs/heads/feature");
  unlinkSync(`${project}/.git/config.lock`);
  await screen.getByText("Failed to switch ref.", { exact: true }).waitFor({ state: "hidden" });
  await select("upstream/feature");
  await expect.poll(() => git("rev-parse", "--symbolic-full-name", "HEAD")).not.toBe("refs/heads/main");
  await capture("retry-after-config-lock", "upstream/feature", "feature");
  expect({ tagHead, branchLeftAfterFailedTracking: leftover, retryHead: git("rev-parse", "--symbolic-full-name", "HEAD"), retryUpstream: git("for-each-ref", "--format=%(upstream)", "refs/heads/feature") }).toEqual({
    tagHead: "refs/heads/v1.2", branchLeftAfterFailedTracking: "", retryHead: "refs/heads/feature", retryUpstream: "refs/remotes/upstream/feature",
  });
});
