// Scratch reproduction for #25823: real thread shell atoms, synthetic threads.
// usage: node drive.ts <worktree> <threads> <updates> <changedPerUpdate> [mountQuietList=1]
const [wt, nThreadsArg, nUpdatesArg, changedArg, mountArg] = process.argv.slice(2);
const cr = `${wt}/packages/client-runtime/src`;
const { Atom, AtomRegistry } = await import(
  `${wt}/node_modules/.pnpm/effect@4.0.5/node_modules/effect/dist/reactivity/index.js`
);
const Option = await import(`${wt}/node_modules/.pnpm/effect@4.0.5/node_modules/effect/dist/Option.js`);
const { createEnvironmentThreadShellAtoms } = await import(`${cr}/state/threadShell.ts`);
const { PrimaryConnectionTarget } = await import(`${cr}/connection/model.ts`);
const { v2ShellSnapshot, v2ThreadShell } = await import(`${cr}/state/orchestrationV2TestFixtures.ts`);
const { applyShellStreamEvent } = await import(`${cr}/state/shellReducer.ts`);

const nThreads = Number(nThreadsArg), nUpdates = Number(nUpdatesArg), changed = Number(changedArg);
const mountQuiet = mountArg !== "0";
const environmentId = "environment-v2";
const root = v2ThreadShell;
const threads = Array.from({ length: nThreads }, (_, i) =>
  i === 0
    ? root
    : {
        ...root,
        id: `thread:delegated-task:${i}`,
        title: `Subagent ${i}`,
        lineage: { ...root.lineage, parentThreadId: root.id, rootThreadId: root.id, relationshipToParent: "subagent" },
      },
);
let snapshot = { ...v2ShellSnapshot, threads };
const snapshotAtom = Atom.family((_id: string) => Atom.make(snapshot));
const catalogValueAtom = Atom.make({
  isReady: true,
  entries: new Map([[environmentId, {
    target: new PrimaryConnectionTarget({ environmentId, label: "E", httpBaseUrl: "https://e.test", wsBaseUrl: "wss://e.test" }),
    profile: Option.none(), enabled: true,
  }]]),
});
const registry = AtomRegistry.make();
const shells = createEnvironmentThreadShellAtoms({ catalogValueAtom, snapshotAtom });
let notifications = 0;
const unsubs = [registry.subscribe(shells.navigationThreadShellsAtom, () => {}, { immediate: true })];
if (mountQuiet) unsubs.push(registry.subscribe(shells.quietThreadShellsAtom, () => { notifications++; }, { immediate: true }));
// the open thread's own point read, as the chat view does
unsubs.push(registry.subscribe(shells.quietThreadShellAtom({ environmentId, threadId: root.id }), () => {}, { immediate: true }));

let sequence = 0;
const frames: any[] = [];
for (let u = 0; u < nUpdates; u++) {
  let next = snapshot;
  for (let c = 0; c < changed; c++) {
    const i = 1 + ((u * changed + c) % (nThreads - 1));
    sequence++;
    next = applyShellStreamEvent(next, {
      kind: "thread.updated", location: "active", sequence,
      thread: { ...next.threads[i], title: `Subagent ${i} v${u}` },
    });
  }
  snapshot = next;
  frames.push(next);
}
// time only what the client does per shell frame: setting the snapshot
const t0 = performance.now();
for (const frame of frames) registry.set(snapshotAtom(environmentId), frame);
const ms = performance.now() - t0;
const quiet = registry.get(shells.quietThreadShellsAtom);
console.log(JSON.stringify({ threads: nThreads, updates: nUpdates, changedPerUpdate: changed, quietListMounted: mountQuiet,
  quietListNotifications: notifications, notificationsPerUpdate: +(notifications / nUpdates).toFixed(2),
  totalMs: Math.round(ms), msPerUpdate: +(ms / nUpdates).toFixed(2), quietListLength: quiet.length,
  lastTitleCorrect: quiet.find((s: any) => s.id === `thread:delegated-task:${1 + (((nUpdates - 1) * changed + changed - 1) % (nThreads - 1))}`)?.title }));
unsubs.forEach((f) => f());
registry.dispose();
