/**
 * olam crystallize <world> — Save a world's thoughts to Pleri Plane.
 *
 * Mirrors the MCP server's olam_crystallize tool.
 */
import * as fs from 'node:fs';
import * as path from 'node:path';
import ora from 'ora';
import { loadContext } from '../context.js';
import { printError, printInfo, printHeader } from '../output.js';
import { EXIT_GENERIC_ERROR, EXIT_PLERI_NOT_CONFIGURED } from '../exit-codes.js';
import { getWorldDbPath } from '@olam/core/src/world-paths.js';
export function registerCrystallize(program, options = {}) {
    const cmd = program
        .command('crystallize')
        .description('Crystallize thoughts from a world to Pleri Plane')
        .argument('<world>', 'World ID')
        .action(async (worldId) => {
        const { ctx, error } = await loadContext();
        // PLERI is by definition not configured if Olam itself isn't initialised
        // (no `.olam/` dir = no `pleri:` block = nothing to crystallize against).
        // The fresh-install scenario this epic targets routes through here, so
        // emit the same skip semantics as the no-pleri-block case below.
        if (!ctx && error?.name === 'OlamConfigNotFoundError') {
            process.stderr.write('warn: crystallize requires PLERI_BASE_URL — skipping (Olam is not initialised; run `olam init` to set up a PLERI block, then re-run).\n');
            process.exitCode = EXIT_PLERI_NOT_CONFIGURED;
            return;
        }
        if (!ctx) {
            printError(error?.message ?? 'Olam is not configured. Run `olam init` first.');
            process.exitCode = EXIT_GENERIC_ERROR;
            return;
        }
        if (!ctx.pleriClient) {
            // Optional feature: PLERI not configured. Warn to stderr (so piped
            // scripts can ignore via 2>/dev/null), keep stdout empty (so exit-2
            // is distinguishable from exit-0 success without parsing output),
            // and exit with the named constant so pipelines can decide whether
            // to treat the skip as a failure or a no-op.
            process.stderr.write('warn: crystallize requires PLERI_BASE_URL — skipping (no work performed). ' +
                'Configure pleri in .olam/config.yaml or set PLERI_BASE_URL to enable.\n');
            process.exitCode = EXIT_PLERI_NOT_CONFIGURED;
            return;
        }
        const world = ctx.worldManager.getWorld(worldId);
        if (!world) {
            printError(`World "${worldId}" not found.`);
            process.exitCode = EXIT_GENERIC_ERROR;
            return;
        }
        const thoughtDbPath = getWorldDbPath(world.workspacePath);
        if (!fs.existsSync(thoughtDbPath)) {
            printError(`No thoughts captured yet for "${worldId}". Run a dispatch first.`);
            process.exitCode = EXIT_GENERIC_ERROR;
            return;
        }
        const spinner = ora('Crystallizing thoughts...').start();
        try {
            const { ThoughtLocalStore } = await import('@olam/core/src/thought/local-store.js');
            const { computeGraphChecksum } = await import('@olam/core/src/crystallize/checksum.js');
            const store = new ThoughtLocalStore(thoughtDbPath);
            const nodes = store.getAllNodes();
            const edges = store.getAllEdges();
            store.close();
            if (nodes.length === 0) {
                spinner.warn('Empty thought store. Run a dispatch first.');
                return;
            }
            const checksum = computeGraphChecksum(nodes, edges);
            const result = await ctx.pleriClient.crystallize({
                worldId,
                sessionId: nodes[0].sessionId ?? `session-${Date.now()}`,
                checksum,
                nodes: nodes.map((n) => ({
                    id: n.id,
                    nodeType: n.nodeType,
                    summary: n.summary,
                    content: n.content,
                    sourceRef: n.sourceRef,
                    sequenceNum: n.sequenceNum,
                    createdAt: n.createdAt,
                })),
                edges: edges.map((e) => ({
                    id: e.id,
                    sourceId: e.sourceId,
                    targetId: e.targetId,
                    edgeType: e.edgeType,
                    metadata: e.metadata,
                    createdAt: e.createdAt,
                })),
                metadata: {
                    worldName: world.name,
                    branch: world.branch,
                    repos: world.repos,
                    totalNodes: nodes.length,
                    totalEdges: edges.length,
                },
            });
            if (result === null) {
                spinner.warn('Could not reach Pleri. Request queued for retry.');
                return;
            }
            spinner.succeed('Crystallization complete');
            printHeader('Crystal');
            printInfo('ID', result.crystallizationId);
            printInfo('Nodes', String(result.nodeCount));
            printInfo('Edges', String(result.edgeCount));
            printInfo('New', String(result.isNew));
        }
        catch (err) {
            spinner.fail('Crystallization failed');
            printError(err instanceof Error ? err.message : String(err));
            process.exitCode = EXIT_GENERIC_ERROR;
        }
    });
    if (options.hidden) {
        // commander v13 omits a Command from parent's help listing when its
        // internal `_hidden` flag is true. The flag is normally set via the
        // `hidden: true` option at `.command(name, desc, opts)` registration
        // time, but we register via the chained shape — set the flag after.
        // Confirmed via node_modules/commander/lib/command.js:165 (`cmd._hidden`).
        cmd._hidden = true;
    }
}
//# sourceMappingURL=crystallize.js.map