"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 runtime_contract_1 = require("../../../lib/runtime/runtime-contract");
const registration_1 = require("../registration");
const WORKSPACE_UPGRADE_CONFIRMATION = "apply-workspace-upgrade";
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: ${WORKSPACE_UPGRADE_CONFIRMATION}.`)
        .action((_, commandInstance) => {
        const context = readCommandContext(commandInstance);
        const options = commandInstance.opts();
        if (options.confirm !== WORKSPACE_UPGRADE_CONFIRMATION) {
            throw (0, errors_1.createUsageError)("Workspace upgrade apply requires explicit confirmation.", [
                `Pass --confirm ${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");
}
