"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateSpecRegistryStructure = validateSpecRegistryStructure;
exports.validateSpecIndexDocumentStructure = validateSpecIndexDocumentStructure;
const cli_constants_1 = require("../config/cli-constants");
const read_helpers_1 = require("./read-helpers");
const types_1 = require("./types");
/**
 * Validate raw registry entries for required metadata and structure.
 * Checks the raw JSON entries before parsing to detect missing required fields.
 * Returns findings for entries with missing required fields.
 * Continues scanning all entries instead of aborting at the first malformed entry.
 */
function validateSpecRegistryStructure(entries) {
    const findings = [];
    const malformedEntries = [];
    // Validate each raw entry's required fields
    for (let i = 0; i < entries.length; i++) {
        const entry = entries[i];
        const missingFields = [];
        // Check if entry is an object
        if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) {
            malformedEntries.push({
                index: i,
                missingFields: [...types_1.SPEC_INDEX_ENTRY_REQUIRED_FIELDS],
                parseError: 'Entry must be a JSON object',
            });
            findings.push({
                code: 'SPEC_REGISTRY_MISSING_REQUIRED_FIELDS',
                message: `Spec index entry at specs[${i}] must be a JSON object.`,
                severity: 'error',
                path: cli_constants_1.CLI_SPEC_INDEX_PATH,
            });
            continue;
        }
        const entryObj = entry;
        // Check for required fields
        for (const field of types_1.SPEC_INDEX_ENTRY_REQUIRED_FIELDS) {
            if (!(0, read_helpers_1.hasRequiredValue)(entryObj[field])) {
                missingFields.push(field);
            }
        }
        if (String(entryObj.status ?? '')
            .trim()
            .toLowerCase() !== 'draft') {
            for (const field of types_1.SPEC_INDEX_ENTRY_ROUTED_REQUIRED_FIELDS) {
                if (!(0, read_helpers_1.hasRequiredValue)(entryObj[field])) {
                    missingFields.push(field);
                }
            }
        }
        if (missingFields.length > 0) {
            malformedEntries.push({
                index: i,
                missingFields,
                parseError: null,
            });
            findings.push({
                code: 'SPEC_REGISTRY_MISSING_REQUIRED_FIELDS',
                message: `Spec index entry at specs[${i}] is missing required fields: ${(0, read_helpers_1.formatFieldList)(missingFields)}.`,
                severity: 'error',
                path: cli_constants_1.CLI_SPEC_INDEX_PATH,
            });
        }
    }
    return {
        hasErrors: findings.length > 0,
        findings: Object.freeze(findings),
        malformedEntries: Object.freeze(malformedEntries),
    };
}
/**
 * Validate the spec index document structure itself.
 * Returns findings for missing top-level required fields.
 */
function validateSpecIndexDocumentStructure(document) {
    if (typeof document !== 'object' || document === null || Array.isArray(document)) {
        return {
            code: 'SPEC_REGISTRY_DOCUMENT_MALFORMED',
            message: 'Spec index document must be a JSON object.',
            severity: 'error',
            path: cli_constants_1.CLI_SPEC_INDEX_PATH,
        };
    }
    const doc = document;
    if (typeof doc.spec_index_schema_version !== 'number') {
        return {
            code: 'SPEC_REGISTRY_DOCUMENT_MALFORMED',
            message: 'Spec index document must have a numeric spec_index_schema_version field.',
            severity: 'error',
            path: cli_constants_1.CLI_SPEC_INDEX_PATH,
        };
    }
    if (!Array.isArray(doc.specs)) {
        return {
            code: 'SPEC_REGISTRY_DOCUMENT_MALFORMED',
            message: "Spec index document must have a 'specs' array field.",
            severity: 'error',
            path: cli_constants_1.CLI_SPEC_INDEX_PATH,
        };
    }
    return null;
}
