import { createHash } from 'node:crypto';
import { writeFile } from 'node:fs/promises';
import { embedded, Image, SandboxCreateOptions, type CuaLike } from '@trycua/cua';

const SOURCE_TEXT = 'pear\napple\npear\nbanana\n';
const SOURCE_PATH = '/tmp/first-cloud-fleet.txt';
const SCREENSHOT = 'first-cloud-fleet.png';

export async function runTutorial(cua: CuaLike, image: string): Promise<void> {
  // on: 'cloud' runs it in the cloud. No name: the claim is released
  // with the sandbox. The managed pool (cua-auto-*) is created for this image
  // on first use and reused afterwards.
  const sandbox = await cua.sandboxes().create(
    SandboxCreateOptions.create({ on: 'cloud', image, cpus: 4, memoryMb: 4096n })
  );
  try {
    console.log(`Claimed ${sandbox.name()}`);
    const env = await sandbox.spacesd(undefined);

    const bytes = new TextEncoder().encode(SOURCE_TEXT);
    await env.upload(SOURCE_PATH, bytes.buffer as ArrayBuffer, undefined);
    const result = await env.sh(`sha256sum ${SOURCE_PATH}`, undefined);
    if (!result.exit.success) throw new Error(new TextDecoder().decode(result.stderr));

    const guestDigest = new TextDecoder().decode(result.stdout).split(/\s+/)[0];
    const localDigest = createHash('sha256').update(SOURCE_TEXT).digest('hex');
    if (guestDigest !== localDigest) {
      throw new Error(`Verification failed: guest=${guestDigest} local=${localDigest}`);
    }
    console.log(`Verified SHA-256: ${guestDigest}`);

    const screenshot = await env.screenshot(undefined);
    await writeFile(SCREENSHOT, Buffer.from(screenshot.image));
    console.log(`Screenshot: ${SCREENSHOT}`);
  } finally {
    await sandbox.delete_();
    console.log('Claim released');
  }
}

if (import.meta.url === `file://${process.argv[1]}`) {
  // Uses FLEETS_TOKEN or CUA_CLIENT_ID/CUA_CLIENT_SECRET, else the `cua auth login` session.
  const cua = embedded({ fleetFromSession: true });
  // Unset: the canonical Linux desktop, ghcr.io/trycua/linux:24.04.
  runTutorial(cua, process.env.CUA_FLEET_IMAGE ?? Image.linux()).catch((error: unknown) => {
    console.error(error);
    process.exitCode = 1;
  });
}
