"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCompletionCommand = createCompletionCommand;
const errors_1 = require("../../../lib/errors");
const output_1 = require("../../../lib/output");
const completion_1 = require("../../../lib/completion");
async function createCompletionCommand() {
    const { Command } = await import('commander');
    const command = new Command('completion');
    command.description('Generate, install, uninstall, or resolve shell completions.');
    command
        .command('script')
        .description('Print a sourceable Day Shift completion script.')
        .requiredOption('--shell <shell>', 'Target shell: bash, zsh, or fish.')
        .action((_, commandInstance) => {
        const shell = requireSupportedShell(commandInstance.opts().shell);
        process.stdout.write(`${(0, completion_1.createCompletionScript)(shell)}\n`);
    });
    command
        .command('install')
        .description('Install or update a Day Shift-managed shell completion integration.')
        .requiredOption('--shell <shell>', 'Target shell: bash, zsh, or fish.')
        .option('--dry-run', 'Show intended completion integration changes without writing files.')
        .option('--force', 'Allow replacing an unmanaged shell-native completion file.')
        .action((_, commandInstance) => {
        const shell = requireSupportedShell(commandInstance.opts().shell);
        const format = requireOutputFormat(commandInstance);
        const plan = (0, completion_1.installCompletionIntegration)({
            shell,
            dryRun: commandInstance.opts().dryRun,
            force: commandInstance.opts().force,
        });
        if (plan.action === 'blocked') {
            throw (0, errors_1.createUsageError)(plan.reason, [`Target path: ${plan.targetPath}`, 'No files were changed.']);
        }
        (0, output_1.emitSuccess)({
            command: 'completion install',
            format,
            text: renderCompletionInstallText(plan),
            data: plan,
        });
    });
    command
        .command('uninstall')
        .description('Remove only the Day Shift-managed shell completion integration.')
        .requiredOption('--shell <shell>', 'Target shell: bash, zsh, or fish.')
        .option('--dry-run', 'Show intended removal without writing files.')
        .action((_, commandInstance) => {
        const shell = requireSupportedShell(commandInstance.opts().shell);
        const format = requireOutputFormat(commandInstance);
        const plan = (0, completion_1.uninstallCompletionIntegration)({
            shell,
            dryRun: commandInstance.opts().dryRun,
        });
        (0, output_1.emitSuccess)({
            command: 'completion uninstall',
            format,
            text: renderCompletionUninstallText(plan),
            data: plan,
        });
    });
    command
        .command('complete')
        .description('Resolve completion candidates for a shell line without executing the target command.')
        .requiredOption('--shell <shell>', 'Target shell: bash, zsh, or fish.')
        .requiredOption('--line <line>', 'Current command line.')
        .requiredOption('--cursor <offset>', 'Cursor offset within the current command line.', parseCursor)
        .action((_, commandInstance) => {
        const shell = requireSupportedShell(commandInstance.opts().shell);
        const result = (0, completion_1.resolveCompletionRequest)({
            shell,
            line: commandInstance.opts().line,
            cursor: commandInstance.opts().cursor,
        });
        const text = (0, completion_1.formatCompletionCandidatesForShell)(shell, result.candidates);
        if (text.length > 0) {
            process.stdout.write(`${text}\n`);
        }
    });
    return command;
}
function requireSupportedShell(value) {
    if (typeof value === 'string' && (0, completion_1.isSupportedCompletionShell)(value)) {
        return value;
    }
    throw (0, errors_1.createUsageError)(`Unsupported completion shell: ${String(value)}.`, [
        `Supported shells: ${completion_1.SUPPORTED_COMPLETION_SHELLS.join(', ')}`,
    ]);
}
function requireOutputFormat(commandInstance) {
    const requestedFormat = commandInstance.optsWithGlobals().format;
    const format = (0, output_1.resolveOutputFormat)(requestedFormat);
    if (format === null) {
        throw (0, errors_1.createUsageError)('Output format must be one of: text, json.', [`Received: ${String(requestedFormat)}`]);
    }
    return format;
}
function parseCursor(value) {
    const parsed = Number(value);
    if (!Number.isInteger(parsed) || parsed < 0) {
        throw (0, errors_1.createUsageError)('Completion cursor must be a non-negative integer.', [
            `Received: ${value}`,
            `Exit behavior: exits with usage code ${errors_1.RuntimeExitCode.USAGE} before completion resolution runs.`,
        ]);
    }
    return parsed;
}
function renderCompletionInstallText(plan) {
    return [
        (0, output_1.renderTerminalHeading)('Completion Install', 'title'),
        (0, output_1.renderTerminalSection)({
            heading: 'Summary',
            fields: [
                { label: 'Shell', value: plan.shell },
                { label: 'Action', value: plan.action },
                { label: 'Changed', value: plan.changed },
                { label: 'Target path', value: plan.targetPath },
                { label: 'Reason', value: plan.reason },
            ],
        }),
        '',
        (0, output_1.renderTerminalSection)({
            heading: 'Write Boundary',
            lines: [
                plan.dryRun
                    ? (0, output_1.renderTerminalBoundary)({ kind: 'dry-run' })
                    : plan.changed
                        ? (0, output_1.renderTerminalBoundary)({
                            kind: 'write-applied',
                            target: plan.targetPath,
                            targetLabel: 'Completion target',
                        })
                        : (0, output_1.renderTerminalBoundary)({
                            kind: 'mutating-no-op',
                            target: plan.targetPath,
                            targetLabel: 'Completion target',
                            reason: plan.reason,
                        }),
            ],
        }),
    ].join('\n');
}
function renderCompletionUninstallText(plan) {
    return [
        (0, output_1.renderTerminalHeading)('Completion Uninstall', 'title'),
        (0, output_1.renderTerminalSection)({
            heading: 'Summary',
            fields: [
                { label: 'Shell', value: plan.shell },
                { label: 'Action', value: plan.action },
                { label: 'Changed', value: plan.changed },
                { label: 'Target path', value: plan.targetPath },
                { label: 'Reason', value: plan.reason },
            ],
        }),
        '',
        (0, output_1.renderTerminalSection)({
            heading: 'Write Boundary',
            lines: [
                plan.dryRun
                    ? (0, output_1.renderTerminalBoundary)({ kind: 'dry-run' })
                    : plan.changed
                        ? (0, output_1.renderTerminalBoundary)({
                            kind: 'write-applied',
                            target: plan.targetPath,
                            targetLabel: 'Completion target',
                        })
                        : (0, output_1.renderTerminalBoundary)({
                            kind: 'mutating-no-op',
                            target: plan.targetPath,
                            targetLabel: 'Completion target',
                            reason: plan.reason,
                        }),
            ],
        }),
    ].join('\n');
}
