"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createWorkspaceUpgradeCommand = createWorkspaceUpgradeCommand;
const errors_1 = require("../../../lib/errors");
const recoverable_mutation_1 = require("../../../lib/filesystem/recoverable-mutation");
const config_store_1 = require("../../../lib/config/config-store");
const output_1 = require("../../../lib/output");
const prompt_upgrade_1 = require("../../../lib/prompts/prompt-upgrade");
const cli_constants_1 = require("../../../lib/config/cli-constants");
const runtime_contract_1 = require("../../../lib/runtime/runtime-contract");
const registration_1 = require("../registration");
async function createWorkspaceUpgradeCommand() {
    const { Command } = await import('commander');
    const command = new Command('upgrade');
    command.description('Preview or apply managed workspace content upgrades without writing user prompts.');
    (0, registration_1.registerCommand)(command, await createWorkspaceUpgradePreviewCommand());
    (0, registration_1.registerCommand)(command, await createWorkspaceUpgradeApplyCommand());
    return command;
}
async function createWorkspaceUpgradePreviewCommand() {
    const { Command } = await import('commander');
    return new Command('preview')
        .description('Preview latest-layer prompt delivery without writing files.')
        .option('--latest-mode <mode>', 'Latest delivery mode: materialize, disabled, or legacy-not-materialized.', 'materialize')
        .action((_, commandInstance) => {
        const context = readCommandContext(commandInstance);
        const mode = parseLatestMode(commandInstance.opts().latestMode);
        const plan = createPlanOrUsageError({
            repositoryRoot: context.repositoryRoot,
            config: context.config,
            mode,
        });
        (0, output_1.emitSuccess)({
            command: 'workspace upgrade preview',
            format: context.format,
            text: renderUpgradeText(plan, false, [], null),
            data: {
                repositoryRoot: context.repositoryRoot,
                detectionSource: context.detectionSource,
                upgrade: publicUpgradePlan(plan),
                readOnly: true,
                writeApplied: false,
            },
        });
    });
}
async function createWorkspaceUpgradeApplyCommand() {
    const { Command } = await import('commander');
    return new Command('apply')
        .description('Apply a preview-bound latest-layer prompt upgrade without writing user prompts.')
        .option('--latest-mode <mode>', 'Latest delivery mode used by the matching preview.', 'materialize')
        .requiredOption('--preview-hash <sha256>', 'Exact hash returned by workspace upgrade preview.')
        .requiredOption('--confirm <token>', `Required confirmation token: ${cli_constants_1.CLI_WORKSPACE_UPGRADE_CONFIRMATION}.`)
        .action((_, commandInstance) => {
        const context = readCommandContext(commandInstance);
        const options = commandInstance.opts();
        if (options.confirm !== cli_constants_1.CLI_WORKSPACE_UPGRADE_CONFIRMATION) {
            throw (0, errors_1.createUsageError)('Workspace upgrade apply requires explicit confirmation.', [
                `Pass --confirm ${cli_constants_1.CLI_WORKSPACE_UPGRADE_CONFIRMATION}.`,
                'No latest or user prompt files were changed.',
            ]);
        }
        const mode = parseLatestMode(options.latestMode);
        let result;
        try {
            result = (0, prompt_upgrade_1.applyPromptUpgradePlanSync)({
                repositoryRoot: context.repositoryRoot,
                config: context.config,
                mode,
                previewHash: readRequiredString(options.previewHash, '--preview-hash'),
            });
        }
        catch (error) {
            throw upgradeUsageError(error);
        }
        (0, output_1.emitSuccess)({
            command: 'workspace upgrade apply',
            format: context.format,
            text: renderUpgradeText(result.plan, result.writeApplied, result.updatedPaths, result.mutation.outcome),
            data: {
                repositoryRoot: context.repositoryRoot,
                detectionSource: context.detectionSource,
                upgrade: publicUpgradePlan(result.plan, result.writeApplied),
                mutationOutcome: result.mutation.outcome,
                writeApplied: result.writeApplied,
                updatedPaths: result.updatedPaths,
                userLayerWriteCount: result.userLayerWriteCount,
            },
        });
    });
}
function readCommandContext(commandInstance) {
    const format = (0, output_1.resolveOutputFormat)(commandInstance.optsWithGlobals().format);
    if (format === null) {
        throw (0, errors_1.createUsageError)('Output format must be one of: text, json.', []);
    }
    const repositoryContext = (0, runtime_contract_1.createRepositoryContext)((0, runtime_contract_1.detectRepositoryRoot)(), false);
    const config = (0, config_store_1.readResolvedConfig)(repositoryContext).resolved.values;
    return {
        repositoryRoot: repositoryContext.root,
        detectionSource: repositoryContext.detectionSource,
        config,
        format,
    };
}
function createPlanOrUsageError(options) {
    try {
        return (0, prompt_upgrade_1.createPromptUpgradePlan)(options);
    }
    catch (error) {
        throw upgradeUsageError(error);
    }
}
function upgradeUsageError(error) {
    if (error instanceof recoverable_mutation_1.RecoverableMutationError) {
        return error;
    }
    return (0, errors_1.createUsageError)(error instanceof Error ? error.message : 'Workspace prompt upgrade was rejected.', [
        'Rerun workspace upgrade preview after correcting the reported evidence.',
        'No user prompt content is an upgrade write target.',
    ]);
}
function parseLatestMode(value) {
    const mode = typeof value === 'string' ? value : '';
    if (!prompt_upgrade_1.PROMPT_UPGRADE_MODES.includes(mode)) {
        throw (0, errors_1.createUsageError)(`Unsupported latest prompt delivery mode '${String(value)}'.`, [
            `Supported modes: ${prompt_upgrade_1.PROMPT_UPGRADE_MODES.join(', ')}.`,
        ]);
    }
    return mode;
}
function readRequiredString(value, option) {
    if (typeof value !== 'string' || value.trim().length === 0) {
        throw (0, errors_1.createUsageError)(`${option} requires a non-empty value.`, []);
    }
    return value;
}
function publicUpgradePlan(plan, writeApplied = plan.writeApplied) {
    const { mutationPlan: _mutationPlan, ...safePlan } = plan;
    return { ...safePlan, writeApplied };
}
function renderUpgradeText(plan, writeApplied, updatedPaths, mutationOutcome) {
    return [
        (0, output_1.renderTerminalHeading)('Workspace Prompt Upgrade', 'title'),
        (0, output_1.renderTerminalSection)({
            heading: 'Summary',
            fields: [
                { label: 'Mode', value: plan.mode },
                { label: 'Preview hash', value: plan.previewHash },
                { label: 'Prompt assets', value: plan.assets.length },
                { label: 'Latest writes needed', value: plan.assets.filter((asset) => asset.writeNeeded).length },
                { label: 'User-layer writes', value: plan.userLayerWriteCount },
                { label: 'Mutation outcome', value: mutationOutcome ?? 'preview only' },
            ],
        }),
        '',
        (0, output_1.renderTerminalCompactList)({
            heading: 'Latest Prompt Assets',
            entries: plan.assets.map((asset) => ({
                label: asset.destinationPath,
                fields: [
                    { label: 'Source', value: asset.sourcePath },
                    { label: 'Write needed', value: asset.writeNeeded },
                ],
            })),
            emptyMessage: 'No latest prompt bodies are selected for this delivery mode.',
        }),
        '',
        (0, output_1.renderTerminalSection)({
            heading: 'Write Boundary',
            lines: [
                writeApplied
                    ? (0, output_1.renderTerminalBoundary)({ kind: 'write-applied', target: updatedPaths.join(', ') })
                    : (0, output_1.renderTerminalBoundary)({ kind: 'dry-run' }),
            ],
        }),
    ].join('\n');
}
