#!/usr/bin/env -S npx --yes tsx
// =============================================================================
// session_wait_till_worker_idle.ts — Block until a worker slot opens in a pool
//
// Part of: .opencode/skills/auto-agents-system/scripts/
//
// Convenience wrapper around session_wait_till_idle.ts for the worker case.
// Blocks until the number of busy worker sessions in a specific pool drops
// below the desired pool size.
//
// Worker sessions are identified by a tag prefix: a tag must start with
// "{prefix}-" (strict prefix-dash matching) and must NOT end with "-SUP"
// (which would indicate a supervisor session).
//
// This is useful when a supervisor needs to wait for a worker slot to become
// available before dispatching a new worker into the pool.
//
// USAGE:
//   session_wait_till_worker_idle.ts \
//     --tag-prefix PREFIX --pool-size N --timeout SECONDS [--server URL]
//
//   --tag-prefix PREFIX    Tag prefix identifying the worker pool (e.g. AUTO-IMP).
//                          Matches tags that start with "{PREFIX}-" but excludes
//                          tags ending in "-SUP".
//   --pool-size N          Positive integer; the maximum number of concurrent
//                          workers desired.  The script blocks while the busy
//                          worker count >= this value.
//   --timeout SECONDS      Positive integer; maximum seconds to block.
//   --server URL           OpenCode Server base URL (default: http://localhost:4096)
//
// OUTPUT (stdout): JSON object — same schema as session_wait_till_idle.ts
//
// EXIT CODE: Always 0.  The `timed_out` field indicates whether the timeout
//   was reached before the condition was satisfied.
//
// DEPENDENCIES: Node.js >= 18 (native fetch), npx tsx (TypeScript execution)
// =============================================================================
import { fileURLToPath } from 'node:url';
import { parseServerFlag, getFlag } from './session_api.ts';
import { waitTillIdle } from './session_wait_till_idle.ts';

// ─────────────────────────────────────────────────────────────────────────────
// MAIN
// ─────────────────────────────────────────────────────────────────────────────

async function main(): Promise<void> {
  const { server, rest } = parseServerFlag(process.argv);

  if (rest.includes('-h') || rest.includes('--help')) {
    printUsage();
    process.exit(0);
  }

  // Parse tag prefix
  const tagPrefix = getFlag(rest, '--tag-prefix');
  if (!tagPrefix) {
    process.stderr.write('ERROR: --tag-prefix is required\n');
    process.exit(1);
  }

  // Parse pool size
  const rawPoolSize = getFlag(rest, '--pool-size');
  if (!rawPoolSize) {
    process.stderr.write('ERROR: --pool-size is required\n');
    process.exit(1);
  }
  const poolSize = Number(rawPoolSize);
  if (!Number.isInteger(poolSize) || poolSize <= 0) {
    process.stderr.write(
      `ERROR: --pool-size must be a positive integer, got "${rawPoolSize}"\n`,
    );
    process.exit(1);
  }

  // Parse timeout
  const rawTimeout = getFlag(rest, '--timeout');
  if (!rawTimeout) {
    process.stderr.write('ERROR: --timeout is required\n');
    process.exit(1);
  }
  const timeoutSeconds = Number(rawTimeout);
  if (!Number.isInteger(timeoutSeconds) || timeoutSeconds <= 0) {
    process.stderr.write(
      `ERROR: --timeout must be a positive integer, got "${rawTimeout}"\n`,
    );
    process.exit(1);
  }

  process.stderr.write(
    `Waiting for worker pool "${tagPrefix}" to have fewer than ${poolSize} busy worker(s) ` +
    `— timeout: ${timeoutSeconds}s\n`,
  );

  const result = await waitTillIdle({
    server,
    mode: 'workers',
    tagPrefix,
    maxPoolSize: poolSize,
    timeoutSeconds,
  });

  if (result.timed_out) {
    process.stderr.write(
      `Timed out after ${result.elapsed_seconds}s — ${result.busy_count} busy worker(s) ` +
      `in pool "${tagPrefix}" still >= pool size ${result.max_pool_size}\n`,
    );
  } else {
    process.stderr.write(
      `Condition met after ${result.elapsed_seconds}s — ${result.busy_count} busy worker(s) ` +
      `in pool "${tagPrefix}" < pool size ${result.max_pool_size}\n`,
    );
  }

  process.stdout.write(JSON.stringify(result, null, 2) + '\n');
}

function printUsage(): void {
  process.stderr.write(`\
Usage:
  session_wait_till_worker_idle.ts \\
    --tag-prefix PREFIX --pool-size N --timeout SECONDS [--server URL]

REQUIRED:
  --tag-prefix PREFIX    Tag prefix for the worker pool (e.g. AUTO-IMP).
                         Matches tags starting with "{PREFIX}-", excludes
                         tags ending in "-SUP" (supervisor sessions).
  --pool-size N          Positive integer; block while the number of busy
                         workers in this pool >= N
  --timeout SECONDS      Positive integer; maximum seconds to block

OPTIONAL:
  --server URL           OpenCode Server base URL (default: http://localhost:4096)
  -h, --help             Print this message and exit

MATCHING RULES:
  A session is counted as a "busy worker" when ALL of these are true:
    1. Its status is "busy"
    2. Its tag starts with "{PREFIX}-"  (strict prefix-dash matching)
    3. Its tag does NOT end with "-SUP" (excludes supervisors)

EXAMPLES:
  With --tag-prefix AUTO-IMP:
    [AUTO-IMP-ISSUE-42] impl-worker     ← MATCHES (starts with AUTO-IMP-, not -SUP)
    [AUTO-IMP-PR-7] impl-worker         ← MATCHES
    [AUTO-IMP-SUP] impl-supervisor      ← EXCLUDED (ends in -SUP)
    [AUTO-PRMRG-ISSUE-1] merge-worker   ← EXCLUDED (wrong prefix)
`);
}

// ─────────────────────────────────────────────────────────────────────────────
// CLI ENTRY POINT
// ─────────────────────────────────────────────────────────────────────────────

if (process.argv[1] === fileURLToPath(import.meta.url)) {
  main().catch((err: unknown) => {
    process.stderr.write(`ERROR: ${err instanceof Error ? err.message : String(err)}\n`);
    process.exit(1);
  });
}
