/**
 * CLI - Main CLI Class
 * Orchestrates all CLI commands using Commander
 */
import { AddCommand } from './commands/AddCommand.js';
import { BroadcastWorkCommand } from './commands/BroadcastWorkCommand.js';
import { BulletproofKeyGenerateCommand } from './commands/BulletproofKeyGenerateCommand.js';
import { ConfigCommand } from './commands/ConfigCommand.js';
import { ContainerProxiesCommand } from './commands/ContainerProxiesCommand.js';
import { ContainerWorkersCommand } from './commands/ContainerWorkersCommand.js';
import { AddMigrationCommand, CreateCommand, CreateMigrationCommand, } from './commands/CreateCommand.js';
import { D1LearnCommand } from './commands/D1LearnCommand.js';
import { D1MigrateCommand } from './commands/D1MigrateCommand.js';
import { D1ProxyCommand } from './commands/D1ProxyCommand.js';
import { DbSeedCommand } from './commands/DbSeedCommand.js';
import { DebugCommand } from './commands/DebugCommand.js';
import { DeployCommand } from './commands/DeployCommand.js';
import { DeployContainerProxiesCommand } from './commands/DeployContainerProxiesCommand.js';
import { DeployContainersProxyCommand } from './commands/DeployContainersProxyCommand.js';
import { DeployContainerWorkersCommand } from './commands/DeployContainerWorkersCommand.js';
import { DockerCommand } from './commands/DockerCommand.js';
import { DockerPushCommand } from './commands/DockerPushCommand.js';
import { DoctorArchitectureCommand } from './commands/DoctorArchitectureCommand.js';
import { FixCommand } from './commands/FixCommand.js';
import { InitContainerCommand } from './commands/InitContainerCommand.js';
import { InitContainersProxyCommand } from './commands/InitContainersProxyCommand.js';
import { InitEcosystemCommand } from './commands/InitEcosystemCommand.js';
import { InitProducerCommand } from './commands/InitProducerCommand.js';
import { InitProxyCommand } from './commands/InitProxyCommand.js';
import { JwtDevCommand } from './commands/JwtDevCommand.js';
import { KeyGenerateCommand } from './commands/KeyGenerateCommand.js';
import { KvProxyCommand } from './commands/KvProxyCommand.js';
import { MakeMailTemplateCommand } from './commands/MakeMailTemplateCommand.js';
import { MakeNotificationTemplateCommand } from './commands/MakeNotificationTemplateCommand.js';
import { MigrateCommand } from './commands/MigrateCommand.js';
import { MigrateWorkerCommand } from './commands/MigrateWorkerCommand.js';
import { MongoDBProxyCommand } from './commands/MongoDBProxyCommand.js';
import { MySqlProxyCommand } from './commands/MySqlProxyCommand.js';
import { NewCommand } from './commands/NewCommand.js';
import { NotificationWorkCommand } from './commands/NotificationWorkCommand.js';
import { PluginCommand } from './commands/PluginCommand.js';
import { PostgresProxyCommand } from './commands/PostgresProxyCommand.js';
import { PrepareCommand } from './commands/PrepareCommand.js';
import { ProxyCommand } from './commands/ProxyCommand.js';
import { PublishCommand } from './commands/PublishCommand.js';
import { PutCommand } from './commands/PutCommand.js';
import { QACommand } from './commands/QACommand.js';
import { QueueCommand } from './commands/QueueCommand.js';
import { QueueRecoveryCommand } from './commands/QueueRecoveryCommand.js';
import { RedisProxyCommand } from './commands/RedisProxyCommand.js';
import { ResourceControlCommand } from './commands/ResourceControlCommand.js';
import { RoutesCommand } from './commands/RoutesCommand.js';
import { ScheduleListCommand } from './commands/ScheduleListCommand.js';
import { ScheduleRunCommand } from './commands/ScheduleRunCommand.js';
import { ScheduleStartCommand } from './commands/ScheduleStartCommand.js';
import { SecretsCommand } from './commands/SecretsCommand.js';
import { SimulateCommand } from './commands/SimulateCommand.js';
import { SmtpProxyCommand } from './commands/SmtpProxyCommand.js';
import { SqlServerProxyCommand } from './commands/SqlServerProxyCommand.js';
import { StartCommand } from './commands/StartCommand.js';
import { TemplatesCommand } from './commands/TemplatesCommand.js';
import { UpgradeCommand } from './commands/UpgradeCommand.js';
import { ErrorHandler } from './ErrorHandler.js';
import { OptionalCliCommandRegistry } from './OptionalCliCommandRegistry.js';
import { VersionChecker } from './services/VersionChecker.js';
import { esmDirname } from '../common/index.js';
import { Logger } from '../config/logger.js';
import { ErrorFactory } from '../exceptions/ZintrustError.js';
import { readFileSync } from '../node-singletons/fs.js';
import { join } from '../node-singletons/path.js';
import { Command } from 'commander';
const __dirname = esmDirname(import.meta.url);
const isCommandProvider = (command) => {
    return (typeof command === 'object' &&
        command !== null &&
        'getCommand' in command &&
        typeof command.getCommand === 'function');
};
const buildCommandRegistry = () => {
    return [
        NewCommand.create(),
        UpgradeCommand.create(),
        PrepareCommand,
        InitContainerCommand.create(),
        InitContainersProxyCommand.create(),
        InitProxyCommand.create(),
        InitProducerCommand.create(),
        InitEcosystemCommand.create(),
        DoctorArchitectureCommand.create(),
        AddCommand.create(),
        CreateCommand.create(),
        CreateMigrationCommand.create(),
        AddMigrationCommand.create(),
        StartCommand.create(),
        DockerCommand.create(),
        DockerPushCommand.create(),
        QueueCommand.create(),
        QueueRecoveryCommand.create(),
        ScheduleListCommand.create(),
        ScheduleRunCommand.create(),
        ScheduleStartCommand.create(),
        BroadcastWorkCommand.create(),
        NotificationWorkCommand.create(),
        ResourceControlCommand,
        MigrateWorkerCommand.create(),
        MigrateCommand.create(),
        DbSeedCommand.create(),
        D1LearnCommand.create(),
        D1MigrateCommand.create(),
        DebugCommand.create(),
        SecretsCommand.create(),
        ConfigCommand.create(),
        ContainerWorkersCommand.create(),
        ContainerProxiesCommand.create(),
        PluginCommand.create(),
        PublishCommand.create(),
        PutCommand.create(),
        DeployCommand.create(),
        DeployContainersProxyCommand.create(),
        DeployContainerWorkersCommand.create(),
        DeployContainerProxiesCommand.create(),
        QACommand(),
        FixCommand.create(),
        KeyGenerateCommand.create(),
        BulletproofKeyGenerateCommand.create(),
        SimulateCommand,
        TemplatesCommand,
        MakeMailTemplateCommand.create(),
        MakeNotificationTemplateCommand.create(),
        RoutesCommand.create(),
        JwtDevCommand,
        ProxyCommand.create(),
        D1ProxyCommand.create(),
        KvProxyCommand.create(),
        MySqlProxyCommand.create(),
        PostgresProxyCommand.create(),
        MongoDBProxyCommand.create(),
        SqlServerProxyCommand.create(),
        RedisProxyCommand.create(),
        SmtpProxyCommand.create(),
        ...OptionalCliCommandRegistry.list(),
    ];
};
/**
 * Load version from package.json
 */
const loadVersion = () => {
    try {
        const packagePath = join(__dirname, '../../package.json');
        const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));
        return typeof packageJson.version === 'string' ? packageJson.version : '1.0.0';
    }
    catch (error) {
        ErrorFactory.createCliError('Failed to load version from package.json', error);
        // Use default version if package.json not found
        return '1.0.0';
    }
};
/**
 * Setup program metadata
 */
const setupProgram = (program, version) => {
    program
        .name('zintrust')
        .description('ZinTrust Framework CLI - Build production-grade TypeScript APIs')
        .version(version, '-v, --version', 'Output version number')
        .helpOption('-h, --help', 'Display help for command')
        .usage('[command] [options]');
    // Global error handling
    program.exitOverride();
};
/**
 * Register all available commands
 */
const registerCommands = (program) => {
    const commands = buildCommandRegistry();
    for (const command of commands) {
        if (isCommandProvider(command)) {
            program.addCommand(command.getCommand());
        }
        else {
            program.addCommand(command);
        }
    }
    // Help command
    program
        .command('help [command]')
        .description('Display help for a command')
        .action((commandName) => {
        if (commandName) {
            const cmd = program.commands.find((c) => c.name() === commandName);
            if (cmd) {
                cmd.help();
            }
            else {
                Logger.error(`Unknown command: ${commandName}`);
                program.help();
            }
        }
        else {
            program.help();
        }
    });
};
/**
 * Check if error is a commander error that can be safely ignored
 */
const isIgnorableCommanderError = (error) => {
    if (error instanceof Error &&
        'code' in error &&
        typeof error.code === 'string' &&
        error.code.startsWith('commander.')) {
        const commanderError = error;
        return typeof commanderError.exitCode === 'number' && commanderError.exitCode === 0;
    }
    return false;
};
/**
 * Get exit code from error
 */
const getExitCode = (error) => {
    if (error instanceof Error &&
        'exitCode' in error &&
        typeof error.exitCode === 'number') {
        return error.exitCode;
    }
    return 1;
};
/**
 * Handle CLI execution error
 */
const handleExecutionError = (error, version, log = true) => {
    if (isIgnorableCommanderError(error)) {
        return;
    }
    if (error === version) {
        return;
    }
    const exitCode = getExitCode(error);
    if (error instanceof Error) {
        ErrorHandler.handle(error, undefined, log);
    }
    // Check for commander-specific errors that need special handling
    if (error instanceof Error &&
        'code' in error &&
        typeof error.code === 'string' &&
        error.code.startsWith('commander.')) {
        ErrorFactory.createCliError('CLI execution failed', error);
        process.exit(exitCode);
        return;
    }
    throw ErrorFactory.createCliError('Unhandled CLI execution error', error);
};
/**
 * Run CLI with arguments
 */
const runCLI = async (program, version, args) => {
    try {
        // If version is requested, let Commander print it (no banner, fast/clean output).
        if (args.includes('-v') || args.includes('--version')) {
            await program.parseAsync(['node', 'zintrust', ...args]);
            return;
        }
        // Always show banner for normal commands
        ErrorHandler.banner(version);
        // Run version check in background (non-blocking)
        VersionChecker.runVersionCheck().catch((error) => {
            // Version check should never crash the CLI
            Logger.debug('Version check encountered an error', error);
        });
        // Show help if no arguments provided
        if (args.length === 0) {
            program.help();
            return;
        }
        // Convert global aliases to subcommand format
        // e.g., `zin -sim my-app` -> `zin simulate my-app`
        let processedArgs = args;
        if (args[0] === '-sim' || args[0] === '--sim') {
            processedArgs = ['simulate', ...args.slice(1)];
        }
        await program.parseAsync(['node', 'zintrust', ...processedArgs]);
    }
    catch (error) {
        // Handle all errors with proper logging and exit logic
        handleExecutionError(error, version, false);
    }
};
/**
 * CLI - Main CLI Class
 * Orchestrates all CLI commands using Commander
 *
 * Notes:
 * - `CLI.create()` is the preferred API (used by current bin scripts/tests).
 * - `new CLI()` remains supported for backward compatibility with older bin scripts.
 */
export const CLI = Object.freeze({
    create() {
        const program = new Command();
        const version = loadVersion();
        setupProgram(program, version);
        registerCommands(program);
        const run = async (args) => runCLI(program, version, args);
        const getProgram = () => program;
        return Object.freeze({
            run,
            getProgram,
        });
    },
});
