"use strict";
/**
 * Init Command
 * Issue #96: npm install CLI support
 * Issue #119: Interactive init support
 * Initialize CommandMate configuration
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.initCommand = initCommand;
const fs_1 = require("fs");
const os_1 = require("os");
const types_1 = require("../types");
const logger_1 = require("../utils/logger");
const preflight_1 = require("../utils/preflight");
const env_setup_1 = require("../utils/env-setup");
const prompt_1 = require("../utils/prompt");
const security_logger_1 = require("../utils/security-logger");
const logger = new logger_1.CLILogger();
/**
 * Create default configuration (non-interactive mode)
 * Issue #135: Use getDefaultDbPath() for dynamic DB path resolution
 */
function createDefaultConfig() {
    return {
        CM_ROOT_DIR: (0, env_setup_1.sanitizePath)(process.env.CM_ROOT_DIR || env_setup_1.DEFAULT_ROOT_DIR),
        CM_PORT: env_setup_1.ENV_DEFAULTS.CM_PORT,
        CM_BIND: env_setup_1.ENV_DEFAULTS.CM_BIND,
        CM_DB_PATH: (0, env_setup_1.getDefaultDbPath)(), // Issue #135: Use absolute path
        CM_LOG_LEVEL: env_setup_1.ENV_DEFAULTS.CM_LOG_LEVEL,
        CM_LOG_FORMAT: env_setup_1.ENV_DEFAULTS.CM_LOG_FORMAT,
    };
}
/**
 * Prompt user for configuration (interactive mode)
 * Issue #119: Interactive init support
 */
async function promptForConfig() {
    logger.info('--- Required Settings ---');
    logger.blank();
    // CM_ROOT_DIR
    const rootDirInput = await (0, prompt_1.prompt)('Repository root directory (CM_ROOT_DIR)', {
        default: env_setup_1.DEFAULT_ROOT_DIR.replace((0, os_1.homedir)(), '~'),
    });
    const rootDir = (0, prompt_1.resolvePath)(rootDirInput || env_setup_1.DEFAULT_ROOT_DIR);
    // Check if path exists
    if (!(0, fs_1.existsSync)(rootDir)) {
        logger.warn(`Directory does not exist: ${rootDir}`);
        const createDir = await (0, prompt_1.confirm)('Directory will be validated when adding repositories. Continue?', {
            default: true,
        });
        if (!createDir) {
            throw new Error('Setup cancelled by user');
        }
    }
    logger.blank();
    logger.info('--- Server Settings ---');
    logger.blank();
    // CM_PORT
    const portInput = await (0, prompt_1.prompt)('Server port (CM_PORT)', {
        default: String(env_setup_1.ENV_DEFAULTS.CM_PORT),
        validate: prompt_1.validatePort,
    });
    const port = parseInt(portInput || String(env_setup_1.ENV_DEFAULTS.CM_PORT), 10);
    // External access
    const enableExternal = await (0, prompt_1.confirm)('Enable external access (bind to 0.0.0.0)?', {
        default: false,
    });
    let bind = env_setup_1.ENV_DEFAULTS.CM_BIND;
    let authToken;
    if (enableExternal) {
        bind = '0.0.0.0';
        const envSetup = new env_setup_1.EnvSetup();
        authToken = envSetup.generateAuthToken();
        logger.blank();
        logger.success('External access enabled');
        logger.info(`  Bind address: 0.0.0.0`);
        logger.info(`  Auth token generated: ${authToken.substring(0, 8)}...`);
    }
    // CM_DB_PATH - Issue #135: Use getDefaultDbPath() for absolute path
    const defaultDbPath = (0, env_setup_1.getDefaultDbPath)();
    const dbPathInput = await (0, prompt_1.prompt)('Database path (CM_DB_PATH)', {
        default: defaultDbPath,
    });
    const dbPath = dbPathInput || defaultDbPath;
    return {
        CM_ROOT_DIR: rootDir,
        CM_PORT: port,
        CM_BIND: bind,
        CM_AUTH_TOKEN: authToken,
        CM_DB_PATH: dbPath,
        CM_LOG_LEVEL: env_setup_1.ENV_DEFAULTS.CM_LOG_LEVEL,
        CM_LOG_FORMAT: env_setup_1.ENV_DEFAULTS.CM_LOG_FORMAT,
    };
}
/**
 * Display configuration summary
 * Issue #119: Show settings after configuration
 */
function displayConfigSummary(config, envPath) {
    logger.blank();
    logger.info('==================================');
    logger.info('Configuration Summary');
    logger.info('==================================');
    logger.blank();
    logger.info(`  CM_ROOT_DIR:  ${config.CM_ROOT_DIR}`);
    logger.info(`  CM_PORT:      ${config.CM_PORT}`);
    logger.info(`  CM_BIND:      ${config.CM_BIND}`);
    if (config.CM_AUTH_TOKEN) {
        logger.info(`  CM_AUTH_TOKEN: ${config.CM_AUTH_TOKEN.substring(0, 8)}... (generated)`);
    }
    logger.info(`  CM_DB_PATH:   ${config.CM_DB_PATH}`);
    logger.blank();
    logger.info(`  Config file:  ${envPath}`);
    logger.blank();
    if (config.CM_AUTH_TOKEN) {
        logger.warn('IMPORTANT: Save your auth token securely!');
        logger.info(`  Token: ${config.CM_AUTH_TOKEN}`);
        logger.blank();
    }
}
/**
 * Execute init command
 */
async function initCommand(options) {
    try {
        logger.header('CommandMate Init');
        logger.blank();
        // Step 1: Preflight checks
        logger.info('Checking system dependencies...');
        const preflightChecker = new preflight_1.PreflightChecker();
        const preflightResult = await preflightChecker.checkAll();
        // Display results
        for (const result of preflightResult.results) {
            if (result.status === 'ok') {
                logger.success(`${result.name}: ${result.version || 'OK'}`);
            }
            else if (result.status === 'missing') {
                logger.error(`${result.name}: Not found`);
                logger.info(`  ${preflight_1.PreflightChecker.getInstallHint(result.name)}`);
            }
            else if (result.status === 'version_mismatch') {
                logger.warn(`${result.name}: ${result.version} (minimum required version not met)`);
            }
        }
        if (!preflightResult.success) {
            logger.blank();
            logger.error('Required dependencies are missing. Please install them and try again.');
            (0, security_logger_1.logSecurityEvent)({
                timestamp: new Date().toISOString(),
                command: 'init',
                action: 'failure',
                details: 'Preflight check failed',
            });
            process.exit(types_1.ExitCode.DEPENDENCY_ERROR);
            return;
        }
        logger.blank();
        logger.success('All required dependencies found');
        logger.blank();
        // Step 2: Get environment path
        const envPath = (0, env_setup_1.getEnvPath)();
        const envSetup = new env_setup_1.EnvSetup(envPath);
        // Backup existing .env if force mode
        if (options.force) {
            const backupPath = await envSetup.backupExisting();
            if (backupPath) {
                logger.info(`Backed up existing .env to ${backupPath}`);
            }
        }
        // Step 3: Create configuration
        let config;
        // Determine if interactive mode should be used
        // Use interactive mode if:
        // - Not using --defaults flag
        // - Running in a TTY (interactive terminal)
        const useInteractive = !options.defaults && (0, prompt_1.isInteractive)();
        if (useInteractive) {
            config = await promptForConfig();
            (0, prompt_1.closeReadline)(); // Close readline after prompts
        }
        else {
            config = createDefaultConfig();
        }
        // Validate configuration
        const validationResult = envSetup.validateConfig(config);
        if (!validationResult.valid) {
            logger.error('Configuration validation failed:');
            for (const error of validationResult.errors) {
                logger.error(`  - ${error}`);
            }
            (0, security_logger_1.logSecurityEvent)({
                timestamp: new Date().toISOString(),
                command: 'init',
                action: 'failure',
                details: `Validation failed: ${validationResult.errors.join(', ')}`,
            });
            process.exit(types_1.ExitCode.CONFIG_ERROR);
            return;
        }
        // Step 4: Create .env file
        logger.blank();
        logger.info('--- Generating .env ---');
        logger.blank();
        logger.info('Creating .env file...');
        await envSetup.createEnvFile(config, { force: options.force });
        logger.success('.env file created');
        // Step 5: Initialize database message
        logger.info('Initializing database...');
        // Note: Database initialization is handled by the server on startup
        logger.success('Database will be initialized on first server start');
        // Display configuration summary
        displayConfigSummary(config, envPath);
        logger.success('CommandMate initialized successfully!');
        logger.blank();
        logger.info('Next steps:');
        if (!useInteractive) {
            logger.info('  1. Edit .env to customize your configuration');
            logger.info('  2. Run "commandmate start" to start the server');
        }
        else {
            logger.info('  1. Run "commandmate start" to start the server');
        }
        logger.blank();
        (0, security_logger_1.logSecurityEvent)({
            timestamp: new Date().toISOString(),
            command: 'init',
            action: 'success',
            details: `Configuration initialized (interactive: ${useInteractive})`,
        });
        process.exit(types_1.ExitCode.SUCCESS);
    }
    catch (error) {
        (0, prompt_1.closeReadline)(); // Ensure readline is closed on error
        const message = error instanceof Error ? error.message : String(error);
        logger.error(`Initialization failed: ${message}`);
        (0, security_logger_1.logSecurityEvent)({
            timestamp: new Date().toISOString(),
            command: 'init',
            action: 'failure',
            details: message,
        });
        process.exit(types_1.ExitCode.UNEXPECTED_ERROR);
    }
}
