// Evidence driver for PR #23660. Usage:
//   node --experimental-import-meta-resolve /tmp/ev-23660/ev/driver.ts <worktree> <row>
// Identical across both SHAs; every product module is imported from <worktree>.
import * as NodeChildProcess from "node:child_process";
import * as NodeFS from "node:fs";
import * as NodePath from "node:path";
import { pathToFileURL } from "node:url";

const [worktree, row] = process.argv.slice(2);
if (!worktree || !row) throw new Error("usage: driver.ts <worktree> <row>");
const EV = "/tmp/ev-23660/ev";
// Isolate from this machine's global git config (it rewrites git@github.com: to https).
process.env.GIT_CONFIG_GLOBAL = "/dev/null";
process.env.GIT_CONFIG_NOSYSTEM = "1";
const sha = NodeChildProcess.execFileSync("git", ["-C", worktree, "rev-parse", "HEAD"]).toString().trim();
const side = sha.startsWith("33a1b866") ? "after" : "before";
const out: string[] = [];
const log = (line: string) => {
  out.push(line);
  console.log(line);
};

// ---- fetch stub (installed before any product import) ----
const posts: { url: string; body: string }[] = [];
let existingPr = false;
globalThis.fetch = (async (input: any, init?: any) => {
  const req = input instanceof Request ? input : new Request(input, init);
  const url = new URL(req.url);
  const body = req.method === "GET" || req.method === "HEAD" ? "" : await req.clone().text();
  log(`  fetch: ${req.method} ${url.href} ${body.length > 400 ? body.slice(0, 400) + "…" : body}`);
  if (url.host !== "api.github.com") throw new Error(`stub: refusing non-GitHub host ${url.host}`);
  const json = (status: number, value: unknown) =>
    new Response(JSON.stringify(value), {
      status,
      headers: { "content-type": "application/json", "x-ratelimit-remaining": "4999", "x-ratelimit-limit": "5000" },
    });
  if (req.method === "POST" && url.pathname.endsWith("/graphql")) {
    const nodes = existingPr
      ? [
          {
            number: 4242,
            title: "existing",
            url: "https://github.com/pingdotgg/t3code/pull/4242",
            baseRefName: "main",
            headRefName: "fix",
            headRefOid: "0".repeat(40),
            state: "OPEN",
            isDraft: false,
            mergedAt: null,
            closedAt: null,
            updatedAt: "2026-10-01T00:00:00Z",
            isCrossRepository: true,
            headRepository: { name: "t3code", nameWithOwner: "juliusmarminge/t3code" },
            headRepositoryOwner: { __typename: "User", login: "juliusmarminge" },
          },
        ]
      : [];
    // Batched queries alias each repository field (`_0_repository:repository(...)`).
    const aliases = [...JSON.parse(body).query.matchAll(/(\w+):repository\(/g)].map((m) => m[1]);
    const data: Record<string, unknown> = {};
    for (const alias of aliases.length ? aliases : ["repository"]) data[alias] = { pullRequests: { nodes } };
    return json(200, { data });
  }
  if (req.method === "POST" && /^\/repos\/[^/]+\/[^/]+\/pulls$/.test(url.pathname)) {
    posts.push({ url: url.href, body });
    return json(422, {
      message: "Validation Failed",
      errors: [{ resource: "PullRequest", field: "head", code: "invalid" }],
    });
  }
  if (req.method !== "GET") return json(422, { message: "stub: write refused" });
  return json(404, { message: "Not Found" });
}) as typeof fetch;

// ---- module loading from the worktree ----
const serverDir = NodePath.join(worktree, "apps/server");
const parent = pathToFileURL(NodePath.join(serverDir, "package.json")).href;
const mod = (spec: string) =>
  import(spec.startsWith(".") ? pathToFileURL(NodePath.join(serverDir, "src", spec)).href : (import.meta as any).resolve(spec, parent));

const Effect = await mod("effect/Effect");
const Layer = await mod("effect/Layer");
const { ChildProcessSpawner } = await mod("effect/process");
const { FetchHttpClient } = await mod("effect/http");
const NodeServices = await mod("@effect/platform-node/NodeServices");
const HostProcess = await mod("@t3tools/shared/HostProcess");
const SourceControlRateLimit = await mod("@t3tools/source-control-core/server/SourceControlRateLimit");
const GitManager = await mod("./git/GitManager.ts");
const GitVcsDriver = await mod("./vcs/GitVcsDriver.ts");
const VcsProcess = await mod("./vcs/VcsProcess.ts");
const VcsDriverRegistry = await mod("./vcs/VcsDriverRegistry.ts");
const VcsProjectConfig = await mod("./vcs/VcsProjectConfig.ts");
const SourceControlProviderRegistry = await mod("./sourceControl/SourceControlProviderRegistry.ts");
const BuiltInDrivers = await mod("./sourceControl/builtInDrivers.ts");
const ServerConfig = await mod("./config.ts");
const ServerSettings = await mod("./serverSettings.ts");
const TextGeneration = await mod("./textGeneration/TextGeneration.ts");
const ProviderRegistry = await mod("./provider/ProviderRegistry.ts");
const ProjectSetupScriptRunner = await mod("./project/ProjectSetupScriptRunner.ts");
const ProjectionStore = await mod("./orchestration-v2/ProjectionStore.ts");
const ProjectStore = await mod("./orchestration-v2/ProjectStore.ts");
const SqlitePersistence = await mod("./persistence/Sqlite.ts");

// ---- fixtures ----
const F = "juliusmarminge/t3code";
const U = "pingdotgg/t3code";
const https = (r: string) => `https://github.com/${r}.git`;
const scp = (r: string) => `git@github.com:${r}.git`;
type Row = {
  layout: string;
  remotes: Record<string, string>;
  marks?: Record<string, string>;
  tracks: string;
  ghRepo?: string;
  mode?: "create" | "status" | "existing";
  insteadOf?: boolean;
};
const rows: Record<string, Row> = {
  "1": { layout: "origin=F upstream=U, upstream.gh-resolved=base, tracks origin/fix", remotes: { origin: https(F), upstream: https(U) }, marks: { upstream: "base" }, tracks: "origin" },
  "1b": { layout: "origin=F upstream=U, no mark, tracks origin/fix (scp-style URLs)", remotes: { origin: scp(F), upstream: scp(U) }, tracks: "origin" },
  "1c": { layout: "origin=F upstream=U, origin.gh-resolved=pingdotgg/t3code, tracks origin/fix", remotes: { origin: https(F), upstream: https(U) }, marks: { origin: U }, tracks: "origin" },
  "1d": { layout: "origin=F upstream=U, origin.gh-resolved=base, tracks origin/fix", remotes: { origin: https(F), upstream: https(U) }, marks: { origin: "base" }, tracks: "origin" },
  "2": { layout: "GH_REPO=U, origin=F only, tracks origin/fix", remotes: { origin: https(F) }, tracks: "origin", ghRepo: U },
  "2b": { layout: "GH_REPO=F, row-1 layout", remotes: { origin: https(F), upstream: https(U) }, marks: { upstream: "base" }, tracks: "origin", ghRepo: F },
  "2c": { layout: "GH_REPO=not-a-repo, row-1 layout", remotes: { origin: https(F), upstream: https(U) }, marks: { upstream: "base" }, tracks: "origin", ghRepo: "not-a-repo" },
  "3": { layout: "origin=U only, tracks origin/fix", remotes: { origin: https(U) }, tracks: "origin" },
  "4": { layout: "origin=F upstream=U, upstream.gh-resolved=base, tracks upstream/fix", remotes: { origin: https(F), upstream: https(U) }, marks: { upstream: "base" }, tracks: "upstream" },
  "4b": { layout: "origin=F upstream=U, origin.gh-resolved=base, tracks upstream/fix", remotes: { origin: https(F), upstream: https(U) }, marks: { origin: "base" }, tracks: "upstream" },
  "5": { layout: "row-1 layout; manager.status + findOpenPr (spawn spy)", remotes: { origin: https(F), upstream: https(U) }, marks: { upstream: "base" }, tracks: "origin", mode: "status" },
  "5b": { layout: "row-1 layout; open PR exists; create_pr (spawn spy)", remotes: { origin: https(F), upstream: https(U) }, marks: { upstream: "base" }, tracks: "origin", mode: "existing" },
  "6": { layout: "origin=gitlab.com/x/y, upstream=U + mark, tracks origin/fix", remotes: { origin: "https://gitlab.com/x/y.git", upstream: https(U) }, marks: { upstream: "base" }, tracks: "origin" },
  "7": { layout: "no origin: fork=F, upstream=U + mark, tracks fork/fix", remotes: { fork: https(F), upstream: https(U) }, marks: { upstream: "base" }, tracks: "fork" },
  "8": { layout: "origin=F upstream=U + mark, tracks remote `local` (bare path URL)", remotes: { origin: https(F), upstream: https(U), local: "LOCAL" }, marks: { upstream: "base" }, tracks: "local" },
  "10": { layout: "row-1 layout but url.<bare>.insteadOf (negative control)", remotes: { origin: https(F), upstream: https(U) }, marks: { upstream: "base" }, tracks: "origin", insteadOf: true },
};
const spec = rows[row];
if (!spec) throw new Error(`unknown row ${row}`);

const root = NodePath.join(EV, side, row);
NodeFS.rmSync(root, { recursive: true, force: true });
NodeFS.mkdirSync(root, { recursive: true });
const git = (cwd: string, ...args: string[]) =>
  NodeChildProcess.execFileSync("git", args, { cwd, env: { ...process.env, GIT_TERMINAL_PROMPT: "0" } }).toString();
const work = NodePath.join(root, "work");
NodeFS.mkdirSync(work);
git(work, "init", "-q", "-b", "main");
git(work, "config", "user.email", "ev@example.com");
git(work, "config", "user.name", "ev");
git(work, "config", "commit.gpgsign", "false");
NodeFS.writeFileSync(NodePath.join(work, "README.md"), "base\n");
git(work, "add", ".");
git(work, "commit", "-qm", "base");
for (const [name, url] of Object.entries(spec.remotes)) {
  const bare = NodePath.join(root, `${name}.git`);
  git(root, "init", "-q", "--bare", bare);
  const visible = url === "LOCAL" ? bare : url;
  git(work, "remote", "add", name, visible);
  if (visible !== bare) git(work, "config", spec.insteadOf ? `url.${bare}.insteadOf` : `url.${bare}.pushInsteadOf`, visible);
  git(work, "push", "-q", name, "main");
}
for (const [name, value] of Object.entries(spec.marks ?? {})) git(work, "config", `remote.${name}.gh-resolved`, value);
git(work, "checkout", "-q", "-b", "fix");
NodeFS.writeFileSync(NodePath.join(work, "fix.txt"), "fix\n");
git(work, "add", ".");
git(work, "commit", "-qm", "fix the thing");
git(work, "push", "-q", "-u", spec.tracks, "fix");

log(`=== row ${row} | ${side} | SHA ${sha}`);
log(`layout: ${spec.layout}`);
log(`GH_REPO: ${spec.ghRepo ?? "(unset)"}`);
log("git remote -v:");
for (const l of git(work, "remote", "-v").trim().split("\n")) log(`  ${l}`);
log("gh-resolved / url config:");
for (const l of git(work, "config", "--get-regexp", "^(remote\\..*\\.gh-resolved|url\\..*|branch\\.fix\\..*)$").trim().split("\n")) log(`  ${l}`);

// ---- layers ----
const spawned: string[] = [];
const spySpawner = Layer.effect(
  ChildProcessSpawner.ChildProcessSpawner,
  Effect.gen(function* () {
    const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
    return ChildProcessSpawner.make((command: any) => {
      if (command._tag === "StandardCommand") spawned.push(`${NodePath.basename(command.command)} ${command.args.join(" ")}`);
      return spawner.spawn(command);
    });
  }),
).pipe(Layer.provide(NodeServices.layer));

const environment = {
  GH_TOKEN: "stub",
  PATH: `${EV}/bin:${process.env.PATH}`,
  HOME: process.env.HOME,
  GIT_CONFIG_GLOBAL: "/dev/null",
  GIT_CONFIG_NOSYSTEM: "1",
  ...(spec.ghRepo ? { GH_REPO: spec.ghRepo } : {}),
};
const layerServerConfig = ServerConfig.layerTest(root, { prefix: "ev-23660-" });
const layerGitDriver = GitVcsDriver.layer.pipe(Layer.provide(spySpawner));
const layerRegistry = SourceControlProviderRegistry.layer.pipe(
  Layer.provideMerge(BuiltInDrivers.layer),
  Layer.provideMerge(layerGitDriver),
  Layer.provideMerge(VcsDriverRegistry.layer.pipe(Layer.provide(VcsProjectConfig.layer))),
);
const layerManagerDeps = Layer.mergeAll(
  Layer.succeed(TextGeneration.TextGeneration, {
    generatePrContent: () => Effect.succeed({ title: "Fix the thing", body: "body" }),
    generateCommitMessage: () => Effect.succeed({ subject: "fix", body: "" }),
    generateBranchName: () => Effect.succeed({ branch: "fix" }),
    generateThreadTitle: () => Effect.succeed({ title: "t" }),
  }),
  Layer.mock(ProviderRegistry.ProviderRegistry)({ getProviders: Effect.succeed([]) }),
  Layer.succeed(ProjectSetupScriptRunner.ProjectSetupScriptRunner, {
    runForThread: () => Effect.succeed({ status: "no-script" }),
  }),
).pipe(
  Layer.provideMerge(layerRegistry),
  Layer.provideMerge(SourceControlRateLimit.layer),
  Layer.provideMerge(FetchHttpClient.layer),
  Layer.provideMerge(ServerSettings.ServerSettingsService.layerTest()),
  Layer.provideMerge(Layer.merge(ProjectionStore.layer, ProjectStore.layer).pipe(Layer.provideMerge(SqlitePersistence.layerMemory))),
  Layer.provideMerge(VcsProcess.layer),
  Layer.provideMerge(layerServerConfig),
  Layer.provideMerge(NodeServices.layer),
);

if (spec.mode === "existing") existingPr = true;
const program = Effect.gen(function* () {
  const manager = yield* GitManager.make;
  const mark = spawned.length;
  if (spec.mode === "status") {
    const status = yield* manager.status({ cwd: work });
    log(`status.pr: ${JSON.stringify(status.pr ?? null)}`);
    return { tag: "status", value: status.pr ?? null };
  }
  const result = yield* manager.runStackedAction({ cwd: work, action: "create_pr", actionId: `ev-${row}` });
  void mark;
  return { tag: "ok", value: result.pr ?? result };
}).pipe(
  Effect.scoped,
  Effect.provide(layerManagerDeps),
  Effect.provideService(HostProcess.Environment, environment),
);
const exit = await Effect.runPromiseExit(program);

log("POSTs to /repos/*/pulls:");
if (posts.length === 0) log("  (none)");
for (const p of posts) {
  const body = JSON.parse(p.body);
  log(`  POST ${p.url} head=${JSON.stringify(body.head)} base=${JSON.stringify(body.base)}`);
}
const newRead = spawned.filter((a) => /\(url\|gh-resolved\)\$/.test(a));
const providerRead = spawned.filter((a) => /\.gh-resolved\$/.test(a) && !/\(url\|gh-resolved\)/.test(a));
log(`spawn spy: ${spawned.length} git spawns; GitManager '(url|gh-resolved)$' reads: ${newRead.length} (provider git reads go through VcsProcess and are not spied)`);
for (const a of newRead) log(`  new-read argv: ${a}`);
for (const a of spawned.filter((x) => /config|remote -v/.test(x))) log(`  config/remote spawn: ${a}`);
const ghLog = NodePath.join(EV, "gh-calls.log");
log(`fake gh invocations so far: ${NodeFS.existsSync(ghLog) ? NodeFS.readFileSync(ghLog, "utf8").trim().split("\n").filter(Boolean).length : 0}`);
if (exit._tag === "Success") log(`outcome: success ${JSON.stringify(exit.value).slice(0, 400)}`);
else {
  if (process.env.EV_DEBUG) console.error(exit.cause);
  const text = String(exit.cause).split("\n").slice(0, 3).join(" | ");
  log(`outcome: failure ${text.slice(0, 600)}`);
}
log(
  `RESULT row=${row} side=${side} post=${posts.length ? new URL(posts[0].url).pathname.replace(/^\/repos\//, "").replace(/\/pulls$/, "") : "-"} head=${posts.length ? JSON.parse(posts[0].body).head : "-"} newRead=${newRead.length} exit=${exit._tag}`,
);
log("");
NodeFS.appendFileSync(NodePath.join(EV, `transcript-${side}.txt`), out.join("\n") + "\n");
process.exit(0);
