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

// Git transfer bytes are observed from the real server, not inferred from its command arguments.
test("New worktree reuses cached submodule history and remains independent", WEB, async ({ t3, app, screen }) => {
  const evidence = process.env.SUBMODULE_PROOF_DIR!;
  const trace = process.env.GIT_TRACE_PACKFILE!;
  const env = { ...process.env, GIT_TRACE_PACKFILE: "", GIT_TRACE_PACKET: "", GIT_TRACE: "", GIT_ALLOW_PROTOCOL: "file", GIT_AUTHOR_DATE: "2026-01-01T00:00:00Z", GIT_COMMITTER_DATE: "2026-01-01T00:00:00Z" };
  const git = (cwd: string, ...args: string[]) => execFileSync("git", args, { cwd, env, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
  const commit = (cwd: string, message: string) => git(cwd, "-c", "user.name=Scenario", "-c", "user.email=scenario@example.invalid", "commit", "-qm", message);
  const source = await t3.project("submodule-history", { "t3.json": JSON.stringify({ defaultThreadEnvMode: "worktree", worktreeSubmodules: "top-level" }) });
  await t3.open();
  const seed = join(dirname(source), "history-seed");
  mkdirSync(seed);
  git(seed, "init", "-q", "-b", "main");
  let state = 123456789;
  for (let revision = 0; revision < 24; revision++) {
    const blob = Buffer.alloc(512 * 1024);
    for (let i = 0; i < blob.length; i++) { state ^= state << 13; state ^= state >>> 17; state ^= state << 5; blob[i] = state & 255; }
    writeFileSync(join(seed, "history.bin"), blob);
    writeFileSync(join(seed, "README.md"), `Synthetic submodule revision ${revision}\n`);
    git(seed, "add", "."); commit(seed, `History ${revision}`);
  }
  const remote = join(dirname(source), "history.git");
  git(seed, "clone", "-q", "--bare", seed, remote);
  git(source, "-c", "protocol.file.allow=always", "submodule", "add", "-q", `file://${remote}`, "history");
  git(source, "add", "."); commit(source, "Add initialized history submodule");
  const parentRemote = join(dirname(source), "project.git");
  git(source, "clone", "-q", "--bare", source, parentRemote);
  git(source, "remote", "add", "origin", `file://${parentRemote}`);
  git(source, "fetch", "-q", "origin");
  git(source, "branch", "--set-upstream-to=origin/main", "main");
  const recorded = git(source, "rev-parse", "HEAD:history");
  writeFileSync(trace, "");
  await t3.open();
  await screen.getByRole("textbox").fill("Prepare a new worktree and inspect the initialized history submodule.");
  await app.screenshot("new-worktree-selected");
  await screen.getByRole("button", "Submit message").tap();
  await expect(screen.getByText("This turn is a replay.", { exact: false })).toBeVisible({ timeout: 120_000 });
  await expect(screen.getByRole("button", "Stop generation")).toBeHidden({ timeout: 120_000 });
  const worktrees = git(source, "worktree", "list", "--porcelain").split("\n").filter((line) => line.startsWith("worktree ")).map((line) => line.slice(9));
  const destination = worktrees.find((path) => path !== source)!;
  if (!destination) throw new Error("The app did not create a worktree");
  const submodule = join(destination, "history");
  const checkedOut = git(submodule, "rev-parse", "HEAD");
  const transferredBytes = existsSync(trace) ? statSync(trace).size : 0;
  const sourceCache = join(source, ".git/modules/history");
  renameSync(sourceCache, `${sourceCache}.held`);
  let fsck = "";
  let readable = false;
  let historical = false;
  try {
    fsck = git(submodule, "fsck", "--full");
    readable = readFileSync(join(submodule, "history.bin")).length === 512 * 1024;
    historical = git(submodule, "show", "HEAD~23:README.md") === "Synthetic submodule revision 0";
  } finally { renameSync(`${sourceCache}.held`, sourceCache); }
  const alternatePath = git(submodule, "rev-parse", "--git-path", "objects/info/alternates");
  const alternates = existsSync(alternatePath) ? readFileSync(alternatePath, "utf8") : "";
  const sha = git(APP_DIR, "rev-parse", "HEAD");
  const run = join(evidence, `${sha.slice(0, 10)}-${Date.now()}`);
  mkdirSync(run, { recursive: true });
  const report = { commit: sha, historyRevisions: 24, syntheticHistoryBytes: 24 * 512 * 1024, transferredPackBytes: transferredBytes, recordedGitlink: recorded, destinationHead: checkedOut, sourceCacheMovedAside: true, fsckExitCode: 0, fsckOutput: fsck, currentFileReadable: readable, oldestRevisionReadable: historical, alternates };
  writeFileSync(join(run, "observations.json"), JSON.stringify(report, null, 2));
  console.log("SUBMODULE OBSERVATIONS", JSON.stringify(report));
  await app.screenshot("worktree-ready");
  expect(checkedOut).toBe(recorded);
  expect(readable && historical).toBe(true);
  expect(alternates).toBe("");
  expect(transferredBytes).toBeLessThan(1024 * 1024);
});
