/**
 * V3 CLI Start Command
 * System startup for KynjalFlow orchestration
 */
import { output } from '../output.js';
import { confirm } from '../prompt.js';
import { callMCPTool, MCPClientError } from '../mcp-client.js';
import * as fs from 'fs';
import * as path from 'path';
// Default configuration
const DEFAULT_PORT = 3000;
const DEFAULT_TOPOLOGY = 'hierarchical-mesh';
const DEFAULT_MAX_AGENTS = 15;
// Check if project is initialized
function isInitialized(cwd) {
    const configPath = path.join(cwd, '.claude-flow', 'config.yaml');
    return fs.existsSync(configPath);
}
// Simple YAML parser for config (basic implementation)
function parseSimpleYaml(content) {
    const result = {};
    const lines = content.split('\n');
    const stack = [
        { indent: -1, obj: result }
    ];
    for (const line of lines) {
        // Skip comments and empty lines
        if (line.trim().startsWith('#') || line.trim() === '')
            continue;
        const match = line.match(/^(\s*)(\w+):\s*(.*)$/);
        if (!match)
            continue;
        const indent = match[1].length;
        const key = match[2];
        let value = match[3].trim();
        // Parse value
        if (value === '' || value === undefined) {
            value = {};
        }
        else if (value === 'true') {
            value = true;
        }
        else if (value === 'false') {
            value = false;
        }
        else if (value === 'null') {
            value = null;
        }
        else if (!isNaN(Number(value)) && value !== '') {
            value = Number(value);
        }
        else if (typeof value === 'string' && value.startsWith('"') && value.endsWith('"')) {
            value = value.slice(1, -1);
        }
        // Find parent based on indentation
        while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
            stack.pop();
        }
        const parent = stack[stack.length - 1].obj;
        if (typeof value === 'object' && value !== null) {
            parent[key] = value;
            stack.push({ indent, obj: value, key });
        }
        else {
            parent[key] = value;
        }
    }
    return result;
}
// Load configuration
function loadConfig(cwd) {
    const configPath = path.join(cwd, '.claude-flow', 'config.yaml');
    if (!fs.existsSync(configPath))
        return null;
    try {
        const content = fs.readFileSync(configPath, 'utf-8');
        return parseSimpleYaml(content);
    }
    catch {
        return null;
    }
}
// Main start action
const startAction = async (ctx) => {
    const daemon = ctx.flags.daemon;
    const port = ctx.flags.port || DEFAULT_PORT;
    const topology = ctx.flags.topology || DEFAULT_TOPOLOGY;
    const skipMcp = ctx.flags['skip-mcp'];
    const cwd = ctx.cwd;
    // Check initialization
    if (!isInitialized(cwd)) {
        output.printError('KynjalFlow is not initialized in this directory');
        output.printInfo('Run "claude-flow init" first to initialize');
        return { success: false, exitCode: 1 };
    }
    // Load configuration
    const config = loadConfig(cwd);
    const swarmConfig = config?.swarm || {};
    const mcpConfig = config?.mcp || {};
    const finalTopology = topology || swarmConfig.topology || DEFAULT_TOPOLOGY;
    const maxAgents = swarmConfig.maxAgents || DEFAULT_MAX_AGENTS;
    const autoStartMcp = mcpConfig.autoStart !== false && !skipMcp;
    const mcpPort = port || mcpConfig.serverPort || DEFAULT_PORT;
    output.writeln();
    output.writeln(output.bold('Starting KynjalFlow V3'));
    output.writeln();
    const spinner = output.createSpinner({ text: 'Initializing system...' });
    try {
        // Step 1: Initialize swarm
        spinner.start();
        spinner.setText('Initializing V3 swarm...');
        const swarmResult = await callMCPTool('swarm_init', {
            topology: finalTopology,
            maxAgents,
            autoScaling: swarmConfig.autoScale !== false,
            v3Mode: true
        });
        spinner.succeed(`Swarm initialized (${finalTopology})`);
        // Step 2: Start MCP server if configured
        let mcpResult = null;
        if (autoStartMcp) {
            spinner.setText('Starting MCP server...');
            spinner.start();
            try {
                mcpResult = await callMCPTool('mcp_start', {
                    port: mcpPort,
                    transport: mcpConfig.transportType || 'stdio',
                    tools: mcpConfig.tools || ['agent', 'swarm', 'memory', 'task']
                });
                spinner.succeed(`MCP server started on port ${mcpPort}`);
            }
            catch (error) {
                spinner.fail('MCP server failed to start');
                output.printWarning(error instanceof MCPClientError
                    ? error.message
                    : String(error));
                // Continue without MCP
            }
        }
        // Step 3: Run health check
        spinner.setText('Running health checks...');
        spinner.start();
        const healthResult = await callMCPTool('swarm_health', {
            swarmId: swarmResult.swarmId
        });
        if (healthResult.status === 'healthy') {
            spinner.succeed('Health checks passed');
        }
        else {
            spinner.fail(`Health check: ${healthResult.status}`);
        }
        // Success output
        output.writeln();
        output.printSuccess('KynjalFlow V3 is running!');
        output.writeln();
        // Status display
        output.printBox([
            `Swarm ID:  ${swarmResult.swarmId}`,
            `Topology:  ${finalTopology}`,
            `Max Agents: ${maxAgents}`,
            `MCP Server: ${autoStartMcp ? `localhost:${mcpPort}` : 'disabled'}`,
            `Mode:      ${daemon ? 'Daemon' : 'Foreground'}`,
            `Health:    ${healthResult.status}`
        ].join('\n'), 'System Status');
        output.writeln();
        output.writeln(output.bold('Quick Commands:'));
        output.printList([
            `${output.highlight('claude-flow status')} - View system status`,
            `${output.highlight('claude-flow agent spawn -t coder')} - Spawn an agent`,
            `${output.highlight('claude-flow swarm status')} - View swarm details`,
            `${output.highlight('claude-flow stop')} - Stop the system`
        ]);
        // Daemon mode
        if (daemon) {
            output.writeln();
            output.printInfo('Running in daemon mode. Use "claude-flow stop" to stop.');
            // Store PID for daemon management
            const daemonPidPath = path.join(cwd, '.claude-flow', 'daemon.pid');
            fs.writeFileSync(daemonPidPath, String(process.pid));
            // Detach from parent process for true daemon behavior
            if (process.platform !== 'win32') {
                // Unix-like systems: create new session
                try {
                    process.stdin.unref?.();
                    process.stdout.unref?.();
                    process.stderr.unref?.();
                }
                catch {
                    // Ignore errors if streams can't be unref'd
                }
            }
            // Keep process alive in daemon mode
            const keepAlive = setInterval(() => {
                // Heartbeat - check if we should still be running
                if (!fs.existsSync(daemonPidPath)) {
                    clearInterval(keepAlive);
                    process.exit(0);
                }
            }, 5000);
            keepAlive.unref(); // Don't prevent process from exiting if no other work
        }
        const result = {
            swarmId: swarmResult.swarmId,
            topology: finalTopology,
            maxAgents,
            mcp: mcpResult ? {
                port: mcpPort,
                transport: mcpConfig.transportType || 'stdio'
            } : null,
            health: healthResult.status,
            daemon,
            startedAt: new Date().toISOString()
        };
        if (ctx.flags.format === 'json') {
            output.printJson(result);
        }
        return { success: true, data: result };
    }
    catch (error) {
        spinner.fail('Startup failed');
        if (error instanceof MCPClientError) {
            output.printError(`Failed to start: ${error.message}`);
        }
        else {
            output.printError(`Unexpected error: ${String(error)}`);
        }
        return { success: false, exitCode: 1 };
    }
};
// Stop subcommand
const stopCommand = {
    name: 'stop',
    description: 'Stop the KynjalFlow system',
    options: [
        {
            name: 'force',
            short: 'f',
            description: 'Force stop without graceful shutdown',
            type: 'boolean',
            default: false
        },
        {
            name: 'timeout',
            description: 'Shutdown timeout in seconds',
            type: 'number',
            default: 30
        }
    ],
    action: async (ctx) => {
        const force = ctx.flags.force;
        const timeout = ctx.flags.timeout;
        output.writeln();
        output.writeln(output.bold('Stopping KynjalFlow'));
        output.writeln();
        if (!force && ctx.interactive) {
            const confirmed = await confirm({
                message: 'Are you sure you want to stop KynjalFlow?',
                default: false
            });
            if (!confirmed) {
                output.printInfo('Operation cancelled');
                return { success: true };
            }
        }
        const spinner = output.createSpinner({ text: 'Stopping system...' });
        spinner.start();
        try {
            // Stop MCP server
            spinner.setText('Stopping MCP server...');
            try {
                await callMCPTool('mcp_stop', { graceful: !force, timeout });
                spinner.succeed('MCP server stopped');
            }
            catch {
                spinner.fail('MCP server was not running');
            }
            // Stop swarm
            spinner.setText('Stopping swarm...');
            spinner.start();
            try {
                await callMCPTool('swarm_stop', {
                    graceful: !force,
                    timeout,
                    saveState: true
                });
                spinner.succeed('Swarm stopped');
            }
            catch {
                spinner.fail('Swarm was not running');
            }
            // Clean up daemon PID
            const daemonPidPath = path.join(ctx.cwd, '.claude-flow', 'daemon.pid');
            if (fs.existsSync(daemonPidPath)) {
                fs.unlinkSync(daemonPidPath);
            }
            output.writeln();
            output.printSuccess('KynjalFlow stopped successfully');
            return {
                success: true,
                data: { stopped: true, force, stoppedAt: new Date().toISOString() }
            };
        }
        catch (error) {
            spinner.fail('Stop failed');
            output.printError(`Failed to stop: ${error instanceof Error ? error.message : String(error)}`);
            return { success: false, exitCode: 1 };
        }
    }
};
// Restart subcommand
const restartCommand = {
    name: 'restart',
    description: 'Restart the KynjalFlow system',
    options: [
        {
            name: 'force',
            short: 'f',
            description: 'Force restart',
            type: 'boolean',
            default: false
        }
    ],
    action: async (ctx) => {
        output.writeln();
        output.writeln(output.bold('Restarting KynjalFlow'));
        output.writeln();
        // Stop first
        const stopCtx = { ...ctx, flags: { ...ctx.flags } };
        const stopResult = await stopCommand.action(stopCtx);
        if (stopResult && !stopResult.success) {
            output.printWarning('Stop failed, attempting to start anyway...');
        }
        // Wait briefly
        await new Promise(resolve => setTimeout(resolve, 1000));
        // Start again
        const startResult = await startAction(ctx);
        return {
            success: startResult.success,
            data: {
                restarted: startResult.success,
                restartedAt: new Date().toISOString()
            }
        };
    }
};
// Quick start subcommand
const quickCommand = {
    name: 'quick',
    aliases: ['q'],
    description: 'Quick start with default settings',
    action: async (ctx) => {
        // Initialize if needed
        if (!isInitialized(ctx.cwd)) {
            output.printInfo('Project not initialized, running init first...');
            output.writeln();
            // Call init with minimal settings
            const { initCommand } = await import('./init.js');
            const initCtx = {
                ...ctx,
                flags: { ...ctx.flags, minimal: true }
            };
            await initCommand.action(initCtx);
            output.writeln();
        }
        // Start with defaults
        return startAction({
            ...ctx,
            flags: { ...ctx.flags, topology: 'mesh' }
        });
    }
};
// Main start command
export const startCommand = {
    name: 'start',
    description: 'Start the KynjalFlow orchestration system',
    subcommands: [stopCommand, restartCommand, quickCommand],
    options: [
        {
            name: 'daemon',
            short: 'd',
            description: 'Run as daemon in background',
            type: 'boolean',
            default: false
        },
        {
            name: 'port',
            short: 'p',
            description: 'MCP server port',
            type: 'number',
            default: DEFAULT_PORT
        },
        {
            name: 'topology',
            short: 't',
            description: 'Swarm topology (hierarchical-mesh, mesh, hierarchical, ring, star)',
            type: 'string',
            choices: ['hierarchical-mesh', 'mesh', 'hierarchical', 'ring', 'star']
        },
        {
            name: 'skip-mcp',
            description: 'Skip starting MCP server',
            type: 'boolean',
            default: false
        }
    ],
    examples: [
        { command: 'claude-flow start', description: 'Start with configuration defaults' },
        { command: 'claude-flow start --daemon', description: 'Start as background daemon' },
        { command: 'claude-flow start --port 3001', description: 'Start MCP on custom port' },
        { command: 'claude-flow start --topology mesh', description: 'Start with mesh topology' },
        { command: 'claude-flow start --skip-mcp', description: 'Start without MCP server' },
        { command: 'claude-flow start quick', description: 'Quick start with defaults' },
        { command: 'claude-flow start stop', description: 'Stop the running system' }
    ],
    action: startAction
};
export default startCommand;
//# sourceMappingURL=start.js.map