import * as NodeServices from '@effect/platform-node/NodeServices';
import * as Effect from 'effect/Effect';
import * as Stream from 'effect/Stream';
import * as Option from 'effect/Option';
import * as ChildProcessSpawner from 'effect/process/ChildProcessSpawner';
import { makeAcpClientTerminals } from './src/server/clientTerminals.ts';

const start = performance.now();
const log = (message: string) => console.log(JSON.stringify({ seconds: Number(((performance.now()-start)/1000).toFixed(3)), message }));
await Effect.runPromise(Effect.gen(function* () {
  log('Linux CLI | real ACP client-terminal service | real NodeServices processes');
  log('shellCommands: true; no database or fixtures; 8-second wait deadline');
  const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
  const terminals = yield* makeAcpClientTerminals({ defaultCwd: process.cwd(), shellCommands: true }).pipe(
    Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, {
      ...spawner,
      spawn: (command) => spawner.spawn(command).pipe(Effect.map(child => ({
        ...child,
        exitCode: child.exitCode.pipe(Effect.tap(code => Effect.sync(() => log(`Real command process exited: code ${code}`)))),
        stdout: child.stdout.pipe(Stream.tap(chunk => Effect.sync(() => log(`Real stdout: ${JSON.stringify(Buffer.from(chunk).toString())}`)))),
      }))),
    }),
  );
  const command = "setsid sh -c 'sleep 20' & sleep 1; echo done";
  log(`terminal/create: ${command}`);
  const terminal = yield* terminals.create({ sessionId: 'evidence', command });
  const request = { sessionId: 'evidence', ...terminal };
  log('terminal/wait_for_exit requested');
  const answer = yield* terminals.waitForExit(request).pipe(Effect.timeoutOption('8 seconds'));
  log(Option.isSome(answer) ? `terminal/wait_for_exit answered: ${JSON.stringify(answer.value)}` : '8-second deadline: terminal/wait_for_exit STILL PENDING (None)');
  log(`terminal/output: ${JSON.stringify(yield* terminals.output(request))}`);
  if (Option.isNone(answer)) {
    log('Continue waiting without interrupting or killing the terminal');
    log(`terminal/wait_for_exit finally answered: ${JSON.stringify(yield* terminals.waitForExit(request))}`);
    log(`terminal/output: ${JSON.stringify(yield* terminals.output(request))}`);
  }
  yield* terminals.disposeAll;
  log('Terminal released; reproduction complete');
}).pipe(Effect.provide(NodeServices.layer), Effect.scoped));
