"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SPEC_UPDATE_RUNTIME_SEMANTICS = exports.SUPPORTED_SPEC_UPDATE_FIELDS = void 0;
exports.createSpecUpdateCommand = createSpecUpdateCommand;
const runtime_contract_1 = require("../../../lib/runtime/runtime-contract");
const errors_1 = require("../../../lib/errors");
const output_1 = require("../../../lib/output");
const metadata_update_operation_1 = require("../metadata-update-operation");
const SPEC_INDEX_PATH = ".day-shift/specs/index.json";
exports.SUPPORTED_SPEC_UPDATE_FIELDS = Object.freeze([
    "title", "depth", "status", "implementation_order", "registered_at", "updated_at",
    "archived_at", "linked_slice.slice", "linked_slice.path"
]);
const SUPPORTED_SPEC_UPDATE_FIELD_SET = new Set(exports.SUPPORTED_SPEC_UPDATE_FIELDS);
exports.SPEC_UPDATE_RUNTIME_SEMANTICS = Object.freeze({
    conditionalInputs: Object.freeze([]),
    dependentInputs: Object.freeze([]),
    conflictingInputs: Object.freeze([]),
    mutableFields: exports.SUPPORTED_SPEC_UPDATE_FIELDS,
    genericGuards: Object.freeze([Object.freeze({
            id: "append-only-source-reference",
            description: "source.ref is append-only and may be changed only through spec source add."
        })]),
    failureTaxonomy: Object.freeze({
        missingRequiredInput: "invalid-input",
        invalidField: "invalid-input",
        invalidRepositoryState: "invalid-config"
    }),
    recoveries: Object.freeze([Object.freeze({
            command: "spec source add",
            requiredInputs: Object.freeze(["id", "ref", "reason"]),
            callableWhen: "all-required-inputs-present",
            availability: "callable"
        })]),
    exactExamples: Object.freeze([Object.freeze([
            "day-shift", "spec", "update", "--spec-id", "spec-registry-commands",
            "--field", "title=Updated spec title"
        ])])
});
async function createSpecUpdateCommand() {
    const { Command } = await import("commander");
    const command = new Command("update");
    command
        .description("Apply helper-backed field updates to one spec-registry entry.")
        .requiredOption("--spec-id <id>", "Spec registry entry id to update.")
        .requiredOption("--field <key=value>", "Direct intended metadata update. Repeat for multiple fields.", collectFieldAssignment, [])
        .action((_, commandInstance) => {
        const repositoryContext = (0, runtime_contract_1.createRepositoryContext)((0, runtime_contract_1.detectRepositoryRoot)(), false);
        const commandOptions = commandInstance.opts();
        const specId = readRequiredSpecId(commandOptions.specId);
        const fieldAssignments = readAndValidateFieldAssignments(commandOptions.field, specId);
        const prefixedAssignments = fieldAssignments.map((assignment) => `entry:${specId}:${assignment}`);
        (0, metadata_update_operation_1.executeMetadataUpdateOperation)({
            commandName: "spec update",
            write: true,
            commandInstance,
            repositoryRoot: repositoryContext.root,
            detectionSource: repositoryContext.detectionSource,
            artifactPathOverride: SPEC_INDEX_PATH,
            fieldAssignmentsOverride: prefixedAssignments,
            expectedFamilies: ["spec-registry"]
        });
    });
    (0, output_1.attachCommandRuntimeSemantics)(command, exports.SPEC_UPDATE_RUNTIME_SEMANTICS);
    return command;
}
function readAndValidateFieldAssignments(value, specId) {
    if (!Array.isArray(value) || value.length === 0) {
        throw (0, errors_1.createUsageError)("--field is required and must be provided at least once.");
    }
    return value.map((assignment) => {
        if (typeof assignment !== "string") {
            throw (0, errors_1.createUsageError)("Each --field value must use <key>=<value>.");
        }
        const separatorIndex = assignment.indexOf("=");
        const field = separatorIndex < 0 ? assignment.trim() : assignment.slice(0, separatorIndex).trim();
        if (separatorIndex <= 0 || field === "") {
            throw (0, errors_1.createUsageError)(`Invalid --field assignment '${assignment}'.`, [
                "Each assignment must use <key>=<value>."
            ]);
        }
        if (!SUPPORTED_SPEC_UPDATE_FIELD_SET.has(field)) {
            if (field === "source.ref") {
                throw (0, errors_1.createUsageError)("Spec source references are append-only and cannot be changed through spec update.", [
                    `Supported alternative: day-shift spec source add --id ${specId} --ref <ref> --reason <reason>.`,
                    "Recovery is not executable until id, ref, and reason are all provided."
                ]);
            }
            throw (0, errors_1.createUsageError)(`Unsupported spec update field '${field}'.`, [`Supported fields: ${exports.SUPPORTED_SPEC_UPDATE_FIELDS.join(", ")}.`]);
        }
        return assignment;
    });
}
function collectFieldAssignment(value, previous) {
    previous.push(value);
    return previous;
}
function readRequiredSpecId(value) {
    if (typeof value !== "string" || value.trim() === "") {
        throw (0, errors_1.createUsageError)("--spec-id is required.");
    }
    return value.trim();
}
