"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createApplyCommand = createApplyCommand;
const errors_1 = require("../../../lib/errors");
const output_1 = require("../../../lib/output");
const mutation_plan_receipts_1 = require("../../../lib/planning/mutation-plan-receipts");
const runtime_contract_1 = require("../../../lib/runtime/runtime-contract");
async function createApplyCommand() {
    const { Command } = await import("commander");
    const command = new Command("apply");
    command
        .description("Explicitly apply one exact revision-bound repository-local mutation plan receipt.")
        .requiredOption("--receipt <path>", "Repository-relative .day-shift/runs/run-*/...json mutation plan receipt.")
        .requiredOption("--expect-command <identity>", "Exact originating command identity expected in the digest-bound receipt.")
        .option("--applied-at <timestamp>", "Optional explicit ISO-8601 apply time; defaults to the current time.")
        .addHelpText("after", [
        "",
        "Boundaries:",
        "  Receipt preview evidence contains no implicit apply authority.",
        "  Apply revalidates digest, command, expiry, exact intended paths, preconditions, and replay policy before the first write.",
        "  Stale, altered, mismatched, replayed, or unsupported receipts write nothing."
    ].join("\n"))
        .action((_, 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 options = commandInstance.opts();
        let result;
        try {
            result = (0, mutation_plan_receipts_1.applyMutationPlanReceiptSync)(repositoryContext.root, {
                receiptPath: options.receipt,
                expectedCommandIdentity: options.expectCommand,
                appliedAt: options.appliedAt
            });
        }
        catch (error) {
            throw normalizeMutationPlanApplyError(error);
        }
        (0, output_1.emitSuccess)({
            command: "apply",
            format,
            text: [
                "Mutation plan receipt apply",
                "",
                `Receipt: ${result.receiptPath}`,
                `Plan identity: ${result.planIdentity}`,
                `Command identity: ${result.commandIdentity}`,
                `Transaction outcome: ${result.transactionOutcome}`,
                `Write outcome: ${result.writeOutcome}`,
                `Intended paths: ${result.intendedPaths.join(", ")}`,
                `Recovery: ${result.recovery}`
            ].join("\n"),
            data: {
                repositoryRoot: repositoryContext.root,
                detectionSource: repositoryContext.detectionSource,
                ...result
            }
        });
    });
    return command;
}
function normalizeMutationPlanApplyError(error) {
    if (!(error instanceof mutation_plan_receipts_1.MutationPlanReceiptError)) {
        return new errors_1.RuntimeError({
            message: "Mutation plan receipt apply failed before a safe result was available.",
            code: "MUTATION_PLAN_RECEIPT_APPLY_FAILED",
            exitCode: errors_1.RuntimeExitCode.ERROR,
            details: [error instanceof Error ? error.message : String(error)],
            cause: error
        });
    }
    const exitCode = error.code === "MUTATION_PLAN_RECEIPT_STALE"
        || error.code === "MUTATION_PLAN_RECEIPT_EXPIRED"
        || error.code === "MUTATION_PLAN_RECEIPT_REPLAYED"
        ? errors_1.RuntimeExitCode.STALE_EVIDENCE
        : error.code === "MUTATION_PLAN_RECEIPT_UNSUPPORTED"
            ? errors_1.RuntimeExitCode.UNSUPPORTED_CAPABILITY
            : error.code === "MUTATION_PLAN_RECEIPT_APPLY_FAILED"
                ? errors_1.RuntimeExitCode.ERROR
                : errors_1.RuntimeExitCode.USAGE;
    return new errors_1.RuntimeError({
        message: error.message,
        code: error.code,
        exitCode,
        details: [
            ...error.details,
            ...(error.conflicts.length === 0
                ? []
                : [`Conflicts: ${JSON.stringify(error.conflicts)}`])
        ],
        cause: error
    });
}
