// Usage: node scan.ts <worktree> <claudeHome> <codexHome> <scans>
// Runs <scans> scans on ONE scanner instance built like layerScannerTest in
// apps/server/src/project/AgentSessionScanner.test.ts and prints JSON.
import { createRequire } from "node:module";
import { pathToFileURL } from "node:url";
import { execFileSync } from "node:child_process";

const [worktree, claudeHomePath, codexHomePath, scansArg] = process.argv.slice(2);
const server = `${worktree}/apps/server`;
const req = createRequire(`${server}/package.json`);
const imp = (m: string) => import(pathToFileURL(req.resolve(m)).href);
const src = (m: string) => import(pathToFileURL(`${server}/src/${m}`).href);

const Effect = await imp("effect/Effect");
const Layer = await imp("effect/Layer");
const NodeServices = await imp("@effect/platform-node/NodeServices");
const ServerConfig = await src("config.ts");
const ServerSettings = await src("serverSettings.ts");
const ProjectStore = await src("orchestration-v2/ProjectStore.ts");
const Scanner = await src("project/AgentSessionScanner.ts");

const layer = Scanner.layer.pipe(
  Layer.provide(
    Layer.mergeAll(
      ServerSettings.layerTest({
        providerInstances: {
          claudeAgent: { driver: "claudeAgent", config: { homePath: claudeHomePath } },
          codex: { driver: "codex", config: { homePath: codexHomePath } },
        },
      }),
      ServerConfig.layerTest(claudeHomePath, { prefix: "ev23690-config-" }),
      Layer.mock(ProjectStore.ProjectStoreV2)({ listShells: () => Effect.succeed([]) }),
    ),
  ),
  Layer.provideMerge(NodeServices.layer),
);

const program = Effect.gen(function* () {
  const scanner = yield* Scanner.AgentSessionScanner;
  const out = [];
  for (let i = 1; i <= Number(scansArg ?? 1); i++) {
    // EV_MARK=1: exec a marker so strace output can be split per scan.
    if (process.env.EV_MARK === "1") execFileSync("/bin/true", [`ev-scan-marker-${i}`]);
    const t0 = performance.now();
    const result = yield* scanner.scan;
    const ms = Math.round(performance.now() - t0);
    process.stderr.write(`scan ${i}: ${ms} ms\n`);
    out.push({ scan: i, ms, result });
  }
  return out;
});

const out = await Effect.runPromise(program.pipe(Effect.provide(layer), Effect.scoped));
const strip = (r: unknown) =>
  JSON.parse(JSON.stringify(r, (k, v) => (k === "lastActiveAt" || k === "mtimeMs" || k === "scannedAt" ? undefined : v)));
console.log(JSON.stringify(out.map((o) => ({ ...o, result: strip(o.result) })), null, 2));
process.exit(0);
