"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createLinkDispositionPreviewCommand = createLinkDispositionPreviewCommand;
const node_fs_1 = __importDefault(require("node:fs"));
const config_contract_1 = require("../../../lib/config/config-contract");
const errors_1 = require("../../../lib/errors");
const output_1 = require("../../../lib/output");
const paths_1 = require("../../../lib/paths");
const trace_link_dispositions_1 = require("../../../lib/trace-link-dispositions");
const global_format_1 = require("../global-format");
async function createLinkDispositionPreviewCommand() {
    const { Command } = await import("commander");
    const command = new Command("preview");
    command
        .description("Preview affected planning trace links for recorded dispositions without writing files.")
        .option("--id <id>", "Preview one disposition id.")
        .option("--target <path>", "Preview one disposition target path.")
        .option("--artifact <path>", "Focus discovery on one repository-relative planning artifact.")
        .option("--format <format>", "Output format. Accepted values: text, json.")
        .addHelpText("after", [
        "",
        "Boundaries:",
        "  Read-only: reads disposition storage and planning trace fields, but does not create storage, rewrite artifacts, update timestamps, repair validation findings, infer replacement targets, or apply migrations."
    ].join("\n"))
        .action((_, commandInstance) => {
        const options = commandInstance.opts();
        const requestedFormat = options.format ?? commandInstance.optsWithGlobals().format ?? (0, global_format_1.getGlobalFormat)(commandInstance);
        const format = (0, output_1.resolveOutputFormat)(requestedFormat);
        if (format === null) {
            throw (0, errors_1.createUnsupportedOutputFormatError)({
                received: requestedFormat,
                commandBoundary: "link disposition preview command output format"
            });
        }
        const repositoryRoot = getRootCommand(commandInstance).configRepositoryContext?.root ?? process.cwd();
        const resolvedConfig = (0, config_contract_1.resolveDayShiftConfig)({
            repositoryContext: {
                root: repositoryRoot,
                detectionSource: "explicit",
                warnedAboutFallback: false
            }
        });
        const storageAbsolutePath = (0, trace_link_dispositions_1.resolveTraceLinkDispositionStoragePath)(repositoryRoot);
        const storageExists = node_fs_1.default.existsSync(storageAbsolutePath);
        const document = storageExists
            ? (0, trace_link_dispositions_1.parseTraceLinkDispositionStorageDocument)(node_fs_1.default.readFileSync(storageAbsolutePath, "utf8"))
            : { schemaVersion: 1, dispositions: [] };
        const artifactPath = normalizeOptionalRepositoryPath(options.artifact, "artifact");
        const selectedDispositions = selectDispositions({
            dispositions: document.dispositions,
            id: normalizeOptionalString(options.id, "id"),
            target: normalizeOptionalRepositoryPath(options.target, "target")
        });
        const preview = (0, trace_link_dispositions_1.previewTraceLinkDispositionUpdates)({
            repositoryRoot,
            dispositionStoragePath: trace_link_dispositions_1.TRACE_LINK_DISPOSITION_STORAGE_PATH,
            dispositions: selectedDispositions,
            artifactPath,
            planningRootPath: (0, paths_1.toRepositoryRelativePath)(repositoryRoot, resolvedConfig.derived.planningRootPath),
            specIndexPath: (0, paths_1.toRepositoryRelativePath)(repositoryRoot, resolvedConfig.derived.specIndexPath)
        });
        (0, output_1.emitSuccess)({
            command: "link disposition preview",
            format,
            text: (0, trace_link_dispositions_1.renderTraceLinkDispositionPreviewText)(preview),
            data: {
                repositoryRoot,
                readOnly: true,
                writeCapable: false,
                localOnly: true,
                storagePath: trace_link_dispositions_1.TRACE_LINK_DISPOSITION_STORAGE_PATH,
                storageExists,
                selectedDispositionCount: selectedDispositions.length,
                artifact: artifactPath,
                preview
            }
        });
    });
    return command;
}
function selectDispositions(options) {
    if (options.id !== undefined && options.target !== null && options.target !== undefined) {
        throw (0, errors_1.createUsageError)("Use either --id or --target for link disposition preview, not both.", []);
    }
    if (options.id !== undefined) {
        return options.dispositions.filter((disposition) => disposition.id === options.id);
    }
    if (options.target !== null && options.target !== undefined) {
        return options.dispositions.filter((disposition) => disposition.target.normalizedPath === options.target);
    }
    return options.dispositions;
}
function normalizeOptionalRepositoryPath(input, fieldName) {
    if (input === undefined || input === null || input === "") {
        return null;
    }
    if (typeof input !== "string") {
        throw (0, errors_1.createUsageError)(`Link disposition preview ${fieldName} must be a repository-relative path.`, []);
    }
    try {
        return (0, paths_1.parseRepositoryRelativePath)(input).normalizedPath;
    }
    catch (error) {
        throw (0, errors_1.createUsageError)(`Link disposition preview ${fieldName} must be a repository-relative path.`, [error instanceof Error ? error.message : String(error)]);
    }
}
function normalizeOptionalString(input, fieldName) {
    if (input === undefined || input === null || input === "") {
        return undefined;
    }
    if (typeof input !== "string") {
        throw (0, errors_1.createUsageError)(`Link disposition preview ${fieldName} must be a string.`, []);
    }
    return input;
}
function getRootCommand(commandInstance) {
    let current = commandInstance;
    while (current.parent !== null && current.parent !== undefined) {
        current = current.parent;
    }
    return current;
}
