import { execFileSync } from "node:child_process";
import { randomUUID } from "node:crypto";
import { Client } from "pg";
import { setTimeout as delay } from "node:timers/promises";
import { SandboxAgent } from "sandbox-agent";
import { PostgresSessionPersistDriver } from "@sandbox-agent/persist-postgres";
import { startDockerSandbox } from "@sandbox-agent/example-shared/docker";
import { detectAgent } from "@sandbox-agent/example-shared";

// --- Postgres setup (Docker or DATABASE_URL) ---

let containerId: string | undefined;
let connectionString: string;

if (process.env.DATABASE_URL) {
  connectionString = process.env.DATABASE_URL;
} else {
  const name = `persist-example-${randomUUID().slice(0, 8)}`;
  containerId = execFileSync("docker", [
    "run", "-d", "--rm", "--name", name,
    "-e", "POSTGRES_USER=postgres", "-e", "POSTGRES_PASSWORD=postgres", "-e", "POSTGRES_DB=sandbox",
    "-p", "127.0.0.1::5432", "postgres:16-alpine",
  ], { encoding: "utf8" }).trim();
  const port = execFileSync("docker", ["port", containerId, "5432/tcp"], { encoding: "utf8" })
    .trim().split("\n")[0]?.match(/:(\d+)$/)?.[1];
  connectionString = `postgres://postgres:postgres@127.0.0.1:${port}/sandbox`;
  console.log(`Postgres on port ${port}`);

  const deadline = Date.now() + 30_000;
  while (Date.now() < deadline) {
    const c = new Client({ connectionString });
    try { await c.connect(); await c.query("SELECT 1"); await c.end(); break; }
    catch { try { await c.end(); } catch {} await delay(250); }
  }
}

try {
  const persist = new PostgresSessionPersistDriver({ connectionString });

  console.log("Starting sandbox...");
  const sandbox = await startDockerSandbox({
    port: 3000,
    setupCommands: [
      "sandbox-agent install-agent claude",
      "sandbox-agent install-agent codex",
    ],
  });

  const sdk = await SandboxAgent.connect({ baseUrl: sandbox.baseUrl, persist });

  const session = await sdk.createSession({ agent: detectAgent() });
  console.log(`Created session ${session.id}`);

  await session.prompt([{ type: "text", text: "Say hello in one sentence." }]);
  console.log("Prompt complete.");

  const sessions = await sdk.listSessions();
  console.log(`\nSessions (${sessions.items.length}):`);
  for (const s of sessions.items) {
    console.log(`  ${s.id}  agent=${s.agent}`);
  }

  const events = await sdk.getEvents({ sessionId: session.id });
  console.log(`\nSession history (${events.items.length} events):`);
  for (const e of events.items) {
    console.log(`  [${e.eventIndex}] ${e.sender}: ${JSON.stringify(e.payload).slice(0, 120)}`);
  }

  await persist.close();
  await sdk.dispose();
  await sandbox.cleanup();
} finally {
  if (containerId) {
    try { execFileSync("docker", ["rm", "-f", containerId], { stdio: "ignore" }); } catch {}
  }
}
