/**
 * olam dispatch <world> <prompt> — Send a task to a running world.
 *
 * Mirrors the MCP server's olam_dispatch tool, delegating to the
 * same container API for persistent Claude session dispatch.
 */
import ora from 'ora';
import pc from 'picocolors';
import { loadContext } from '../context.js';
import { printError, printInfo, printHeader } from '../output.js';
import { DEEP_MODE_SUFFIX, COMPLEX_PROMPT_RE } from '@olam/core/src/orchestrator/dispatch.js';
import { resolveWorld, suggestWorlds, validateMode, DISPATCH_MODES } from './dispatch-resolve.js';
export function registerDispatch(program) {
    program
        .command('dispatch')
        .description('Send a prompt to a world for execution')
        .argument('<world>', 'World ID or name')
        .argument('<prompt>', 'Task prompt')
        .option('--mode <mode>', `Execution mode: ${DISPATCH_MODES.join(', ')}`, 'auto')
        .option('--max-turns <n>', 'Maximum turns', parseInt)
        .action(async (world, prompt, opts) => {
        // Validate --mode up front: a typo (`--mode dep`) used to fall
        // through to non-deep behaviour silently. Fail loud instead.
        const modeResult = validateMode(opts.mode);
        if ('error' in modeResult) {
            printError(modeResult.error);
            process.exitCode = 1;
            return;
        }
        const mode = modeResult.mode;
        const { ctx, error } = await loadContext();
        if (!ctx) {
            printError(error?.message ?? 'Olam is not configured. Run `olam init` first.');
            process.exitCode = 1;
            return;
        }
        const worlds = ctx.worldManager.listWorlds();
        // Accept either a world ID (existing contract) or a name — operators
        // usually remember the name, not the generated id.
        const worldMeta = resolveWorld(worlds, world);
        if (!worldMeta) {
            printError(`World "${world}" not found.`);
            const suggestions = suggestWorlds(worlds, world);
            if (suggestions.length > 0) {
                console.error(pc.dim('\n  Did you mean:'));
                for (const s of suggestions) {
                    console.error(`    ${pc.bold(s.name)} ${pc.dim(`(${s.id})`)}  ${pc.dim(s.status)}`);
                }
            }
            console.error(pc.dim('\n  Run `olam list` to see all worlds.'));
            process.exitCode = 1;
            return;
        }
        const worldId = worldMeta.id;
        // D3: warn-not-block version pin check (once per world per session).
        {
            const { checkVersionPin } = await import('@olam/core/src/world/version-pin.js');
            checkVersionPin(worldId, worldMeta.workspacePath);
        }
        if (worldMeta.status !== 'running') {
            printError(`World "${worldMeta.name}" (${worldId}) is ${worldMeta.status}. Only running worlds accept dispatches.`);
            if (worldMeta.status === 'paused') {
                console.error(pc.dim(`\n  Resume it first: olam resume ${worldId}`));
            }
            else if (worldMeta.status === 'destroyed') {
                console.error(pc.dim('\n  This world was destroyed. Create a fresh one with `olam create`.'));
            }
            else {
                console.error(pc.dim(`\n  Check what it's doing: olam status ${worldId}`));
            }
            process.exitCode = 1;
            return;
        }
        const spinner = ora('Dispatching...').start();
        try {
            const computeWorld = await ctx.computeProvider.getWorld(worldId);
            if (!computeWorld) {
                spinner.fail('Compute world not found');
                printError('The world may have been destroyed externally.');
                process.exitCode = 1;
                return;
            }
            // Start Claude session if needed
            await computeWorld.exec('curl -s -X POST http://localhost:8080/api/claude/start');
            // Enhance prompt based on mode (shared regex with MCP server)
            let finalPrompt = prompt;
            if (mode === 'deep') {
                finalPrompt += DEEP_MODE_SUFFIX;
            }
            else if (mode === 'auto') {
                const isComplex = prompt.length > 100 ||
                    COMPLEX_PROMPT_RE.test(prompt);
                if (isComplex) {
                    finalPrompt += DEEP_MODE_SUFFIX;
                }
            }
            // Write intent node (mirrors MCP server's world-dispatch.ts)
            const intentPayloadFile = '/tmp/olam-dispatch-intent.json';
            await computeWorld.exec(`cat > ${intentPayloadFile} << 'OLAM_EOF'\n${JSON.stringify({
                tool_name: '__intent__',
                tool_input: { prompt: finalPrompt },
                hook_event_name: 'intent',
            })}\nOLAM_EOF`);
            await computeWorld.exec(`curl -s -X POST -H "Content-Type: application/json" -d @${intentPayloadFile} http://localhost:8080/hooks/thought`);
            // Send prompt via temp file to avoid shell injection
            const dispatchPayloadFile = '/tmp/olam-dispatch.json';
            await computeWorld.exec(`cat > ${dispatchPayloadFile} << 'OLAM_EOF'\n${JSON.stringify({ prompt: finalPrompt })}\nOLAM_EOF`);
            const result = await computeWorld.exec(`curl -s -X POST -H "Content-Type: application/json" -d @${dispatchPayloadFile} http://localhost:8080/dispatch`);
            if (result.exitCode !== 0) {
                throw new Error(result.stderr || 'Dispatch POST failed');
            }
            spinner.succeed('Dispatch sent');
            const dashboardPort = 19080 + worldMeta.portOffset;
            const terminalPort = 17681 + worldMeta.portOffset;
            printHeader('Dispatch');
            printInfo('World', `${worldMeta.name} (${worldId})`);
            printInfo('Mode', mode);
            printInfo('Dashboard', `http://localhost:${dashboardPort}`);
            printInfo('Terminal', `http://localhost:${terminalPort}`);
            const containerName = `olam-${worldId}-devbox`;
            console.log(`\n${pc.dim(`Watch live: docker exec -it ${containerName} tmux attach -t claude-main -r`)}`);
        }
        catch (err) {
            spinner.fail('Dispatch failed');
            printError(err instanceof Error ? err.message : String(err));
            process.exitCode = 1;
        }
    });
}
//# sourceMappingURL=dispatch.js.map