"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createPromptReconcileCommand = createPromptReconcileCommand;
const config_store_1 = require("../../../lib/config/config-store");
const errors_1 = require("../../../lib/errors");
const recoverable_mutation_1 = require("../../../lib/filesystem/recoverable-mutation");
const output_1 = require("../../../lib/output");
const prompt_reconciliation_1 = require("../../../lib/prompts/prompt-reconciliation");
const runtime_contract_1 = require("../../../lib/runtime/runtime-contract");
const registration_1 = require("../registration");
async function createPromptReconcileCommand() {
    const { Command } = await import("commander");
    const command = new Command("reconcile");
    command.description("Preview or apply an explicit three-way user prompt reconciliation decision.");
    (0, registration_1.registerCommand)(command, await createPromptReconcilePreviewCommand());
    (0, registration_1.registerCommand)(command, await createPromptReconcileApplyCommand());
    return command;
}
async function createPromptReconcilePreviewCommand() {
    const { Command } = await import("commander");
    return new Command("preview")
        .description("Classify prompt drift and return a no-write preview hash.")
        .requiredOption("--prompt <path>", "Repository-relative prompt path to reconcile.")
        .action((_, commandInstance) => {
        const context = readCommandContext(commandInstance);
        const requestedPromptPath = readRequiredString(commandInstance.opts().prompt, "--prompt");
        const plan = createPlanOrUsageError({
            repositoryRoot: context.repositoryRoot,
            config: context.config,
            requestedPromptPath
        });
        (0, output_1.emitSuccess)({
            command: "prompt reconcile preview",
            format: context.format,
            text: renderReconcileText(plan, null, false, []),
            data: {
                repositoryRoot: context.repositoryRoot,
                detectionSource: context.detectionSource,
                reconciliation: plan,
                readOnly: true,
                writeApplied: false
            }
        });
    });
}
async function createPromptReconcileApplyCommand() {
    const { Command } = await import("commander");
    return new Command("apply")
        .description("Apply an explicit preserve or replace decision bound to a current preview hash.")
        .requiredOption("--prompt <path>", "Repository-relative prompt path to reconcile.")
        .requiredOption("--decision <decision>", "Explicit decision: preserve or replace.")
        .requiredOption("--preview-hash <sha256>", "Exact hash returned by prompt reconcile preview.")
        .action((_, commandInstance) => {
        const context = readCommandContext(commandInstance);
        const options = commandInstance.opts();
        const decision = parseDecision(options.decision);
        let result;
        try {
            result = (0, prompt_reconciliation_1.applyPromptReconciliationPlanSync)({
                repositoryRoot: context.repositoryRoot,
                config: context.config,
                requestedPromptPath: readRequiredString(options.prompt, "--prompt"),
                decision,
                previewHash: readRequiredString(options.previewHash, "--preview-hash")
            });
        }
        catch (error) {
            throw reconciliationUsageError(error);
        }
        (0, output_1.emitSuccess)({
            command: "prompt reconcile apply",
            format: context.format,
            text: renderReconcileText(result.plan, result.decision, result.writeApplied, result.updatedPaths),
            data: {
                repositoryRoot: context.repositoryRoot,
                detectionSource: context.detectionSource,
                reconciliation: result.plan,
                decision: result.decision,
                mutationOutcome: result.mutation?.outcome ?? "no-op",
                writeApplied: result.writeApplied,
                updatedPaths: result.updatedPaths
            }
        });
    });
}
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_reconciliation_1.createPromptReconciliationPlan)(options);
    }
    catch (error) {
        throw reconciliationUsageError(error);
    }
}
function reconciliationUsageError(error) {
    if (error instanceof recoverable_mutation_1.RecoverableMutationError) {
        return error;
    }
    return (0, errors_1.createUsageError)(error instanceof Error ? error.message : "Prompt reconciliation was rejected.", [
        "Rerun prompt reconcile preview after correcting the reported evidence.",
        "No implicit preserve or replace decision was made."
    ]);
}
function parseDecision(value) {
    const decision = typeof value === "string" ? value : "";
    if (!prompt_reconciliation_1.PROMPT_RECONCILIATION_DECISIONS.includes(decision)) {
        throw (0, errors_1.createUsageError)(`Unsupported prompt reconciliation decision '${String(value)}'.`, [`Supported decisions: ${prompt_reconciliation_1.PROMPT_RECONCILIATION_DECISIONS.join(", ")}.`]);
    }
    return decision;
}
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 renderReconcileText(plan, decision, writeApplied, updatedPaths) {
    return [
        (0, output_1.renderTerminalHeading)("Prompt Reconciliation", "title"),
        (0, output_1.renderTerminalSection)({
            heading: "Summary",
            fields: [
                { label: "Prompt", value: plan.promptPath },
                { label: "Drift state", value: plan.classification.state },
                { label: "Needs replacement", value: plan.classification.needsReplacement },
                { label: "Preview hash", value: plan.previewHash },
                { label: "Allowed decisions", value: plan.allowedDecisions.join(", ") },
                { label: "Applied decision", value: decision ?? "preview only" }
            ]
        }),
        "",
        (0, output_1.renderTerminalSection)({
            heading: "Hash Evidence",
            fields: [
                { label: "Base", value: plan.classification.baseSha256 ?? "(missing)" },
                { label: "User", value: plan.classification.userSha256 ?? "(missing)" },
                { label: "Upstream", value: plan.classification.upstreamSha256 ?? "(missing)" },
                { label: "Upstream layer", value: plan.upstream.layer ?? "(unavailable)" }
            ],
            lines: [...plan.evidenceIssues]
        }),
        "",
        (0, output_1.renderTerminalSection)({
            heading: "Write Boundary",
            lines: [
                writeApplied
                    ? (0, output_1.renderTerminalBoundary)({ kind: "write-applied", target: updatedPaths.join(", ") })
                    : decision === "preserve"
                        ? (0, output_1.renderTerminalBoundary)({ kind: "mutating-no-op", reason: "The explicit preserve decision leaves user content unchanged." })
                        : (0, output_1.renderTerminalBoundary)({ kind: "dry-run" })
            ]
        })
    ].join("\n");
}
