"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 ?? commandInstance);
}
