"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTaskAttemptAbortCommand = createTaskAttemptAbortCommand;
const errors_1 = require("../../../lib/errors");
const output_1 = require("../../../lib/output");
const task_attempts_1 = require("../../../lib/planning/task-attempts");
const runtime_contract_1 = require("../../../lib/runtime/runtime-contract");
const global_format_1 = require("../global-format");
async function createTaskAttemptAbortCommand() {
    const { Command } = await import("commander");
    const command = new Command("attempt-abort");
    command
        .description("Preview or atomically archive and reset one revision-bound invalid no-evidence current attempt.")
        .requiredOption("--task-definition <path>", "Repository-relative canonical task-definition.md path.")
        .requiredOption("--attempt-id <identity>", "Exact current attempt identity to abort.")
        .requiredOption("--task-revision <revision>", "Exact 64-character task revision observed before abort.")
        .requiredOption("--recorded-by <actor>", "Non-empty attempt-abort actor.")
        .requiredOption("--recorded-at <timestamp>", "ISO-8601 attempt-abort time with explicit timezone.")
        .requiredOption("--reason <text>", "Non-empty audit reason for aborting the invalid attempt.")
        .option("--dry-run", "Preview exact pair preconditions and reset writes without mutation; omit to apply.")
        .action((_, commandInstance) => {
        const format = (0, output_1.resolveOutputFormat)((0, global_format_1.getGlobalFormat)(commandInstance));
        if (format === null)
            throw (0, errors_1.createUsageError)("Output format must be one of: text, json.");
        const repository = (0, runtime_contract_1.createRepositoryContext)((0, runtime_contract_1.detectRepositoryRoot)(), false);
        const options = commandInstance.opts();
        let result;
        try {
            const preview = (0, task_attempts_1.previewTaskAttemptAbortSync)({
                repositoryRoot: repository.root,
                taskDefinitionPath: options.taskDefinition,
                attemptId: options.attemptId,
                taskRevision: options.taskRevision,
                recordedBy: options.recordedBy,
                recordedAt: options.recordedAt,
                reason: options.reason
            });
            result = options.dryRun === true || preview.writeOutcome === "no-write"
                ? preview
                : (0, task_attempts_1.applyTaskAttemptAbortSync)(preview);
        }
        catch (error) {
            throw normalizeAttemptAbortError(error, options.taskDefinition);
        }
        if (!["previewed", "committed", "no-write"].includes(result.writeOutcome)) {
            throw createAttemptAbortOutcomeError(result);
        }
        (0, output_1.emitSuccess)({
            command: "task attempt-abort",
            format,
            text: renderText(result),
            data: {
                ...result,
                repositoryRoot: repository.root,
                detectionSource: repository.detectionSource,
                nextAction: result.writeOutcome === "previewed"
                    ? "Inspect the exact task-summary pair revisions, then rerun without --dry-run."
                    : "Revise the task contract if needed, obtain fresh readiness authorization, and open a clean successor with a new attempt identity."
            }
        });
    });
    return command;
}
function normalizeAttemptAbortError(error, taskDefinitionPath) {
    if (error instanceof errors_1.RuntimeError)
        return error;
    if (error instanceof task_attempts_1.TaskAttemptAbortError || error instanceof task_attempts_1.TaskAttemptOpenError) {
        const normalizedCode = error.code.replace(/-/g, "_").toUpperCase();
        const code = `TASK_ATTEMPT_ABORT_${normalizedCode}`;
        const exitCode = error.code === "stale-preview" || error.code === "stale-revision"
            ? errors_1.RuntimeExitCode.STALE_EVIDENCE
            : error.code === "attempt-conflict"
                || error.code === "evidence-bearing-attempt"
                || error.code === "pair-invalid"
                ? errors_1.RuntimeExitCode.INVALID_CONFIG
                : errors_1.RuntimeExitCode.USAGE;
        return new errors_1.RuntimeError({
            message: "Task attempt-abort was rejected.",
            code,
            exitCode,
            writeOutcome: "no-writes",
            details: [
                error.message,
                "No task-definition, implementation-summary, attempt history, or runtime evidence was written.",
                "Refresh the selected task pair and retry only when the exact current attempt has no material evidence."
            ],
            findings: [{
                    code,
                    severity: "error",
                    message: error.message,
                    path: taskDefinitionPath,
                    noWriteBoundary: "Rejected attempt-abort transitions do not mutate the selected task pair."
                }]
        });
    }
    throw error;
}
function createAttemptAbortOutcomeError(result) {
    const details = [
        `writeOutcome: ${result.writeOutcome}`,
        `intendedPaths: ${JSON.stringify(result.intendedPaths)}`,
        `changedPaths: ${JSON.stringify(result.changedPaths)}`,
        `conflicts: ${JSON.stringify(result.conflicts)}`,
        `recoveryPath: ${result.recoveryPath ?? "null"}`,
        `failure: ${result.failure ?? "null"}`
    ];
    if (result.writeOutcome === "conflict") {
        return new errors_1.RuntimeError({
            message: "Task attempt-abort preview is stale or conflicted.",
            code: "TASK_ATTEMPT_ABORT_CONFLICT",
            exitCode: errors_1.RuntimeExitCode.CONCURRENCY_CONFLICT,
            writeOutcome: "no-writes",
            details,
            recoveryActions: [(0, errors_1.createNonCallableRecoveryAction)({
                    id: "recovery.refresh-task-attempt-abort-preview",
                    command: "task attempt-abort",
                    explanation: "Refresh both task-pair revisions and preview the exact abort transition again.",
                    reason: "The original attempt identity, task revision, actor, time, and reason must be supplied again."
                })]
        });
    }
    if (result.writeOutcome === "incomplete") {
        return new errors_1.RuntimeError({
            message: "Task attempt-abort stopped with incomplete repository state.",
            code: "TASK_ATTEMPT_ABORT_INCOMPLETE",
            exitCode: errors_1.RuntimeExitCode.PARTIAL_MUTATION,
            writeOutcome: "partial",
            details,
            recoveryActions: [(0, errors_1.createNonCallableRecoveryAction)({
                    id: "recovery.inspect-task-attempt-abort-transaction",
                    explanation: "Inspect retained transaction evidence before retrying or repairing the task pair.",
                    reason: result.recoveryPath ?? "The retained transaction path was unavailable."
                })]
        });
    }
    return new errors_1.RuntimeError({
        message: "Task attempt-abort produced no canonical result.",
        code: "TASK_ATTEMPT_ABORT_NO_WRITE",
        exitCode: errors_1.RuntimeExitCode.ERROR,
        details
    });
}
function renderText(result) {
    return [
        "Task implementation attempt abort",
        "",
        `Task definition: ${result.taskDefinitionPath}`,
        `Implementation summary: ${result.implementationSummaryPath}`,
        `Prior attempt ID: ${result.priorAttemptId}`,
        `Abort state: ${result.abortState}`,
        `Bound task revision: ${result.boundTaskRevision}`,
        `Recorded by: ${result.recordedBy}`,
        `Recorded at: ${result.recordedAt}`,
        `Reason: ${result.reason}`,
        `Idempotent replay: ${result.idempotent ? "yes" : "no"}`,
        `Write outcome: ${result.writeOutcome}`,
        `Changed paths: ${result.changedPaths.length}`
    ].join("\n");
}
