/**
 * Manifest Loader Utility
 *
 * Loads and validates SpecVerse manifest files.
 * Provides default manifests for testing and development.
 */
import { readFileSync, existsSync } from 'fs';
import { parse as parseYaml } from 'yaml';
import { resolve } from 'path';
/**
 * Load manifest from file
 */
export function loadManifest(manifestPath) {
    if (!manifestPath) {
        throw new Error('Manifest path is required');
    }
    const fullPath = resolve(manifestPath);
    if (!existsSync(fullPath)) {
        throw new Error(`Manifest file not found: ${fullPath}`);
    }
    try {
        const yamlContent = readFileSync(fullPath, 'utf8');
        const parsed = parseYaml(yamlContent);
        // Handle unified container format (manifests: { ManifestName: { ... } })
        if (parsed.manifests && typeof parsed.manifests === 'object') {
            const manifestKeys = Object.keys(parsed.manifests);
            if (manifestKeys.length === 0) {
                throw new Error('Manifests container is empty');
            }
            // Use first manifest
            const manifestName = manifestKeys[0];
            const manifest = parsed.manifests[manifestName];
            // Add metadata
            manifest._manifestName = manifestName;
            manifest._manifestPath = fullPath;
            return manifest;
        }
        // Handle direct manifest format (legacy or simplified)
        if (parsed.specVersion) {
            return parsed;
        }
        throw new Error('Invalid manifest format: missing "manifests" container or "specVersion"');
    }
    catch (error) {
        if (error.code === 'ENOENT') {
            throw new Error(`Manifest file not found: ${fullPath}`);
        }
        throw new Error(`Failed to load manifest: ${error.message}`);
    }
}
/**
 * Get manifest configuration value by path
 */
export function getManifestValue(manifest, path, defaultValue) {
    if (!manifest || !path) {
        return defaultValue;
    }
    const parts = path.split('.');
    let current = manifest;
    for (const part of parts) {
        if (current && typeof current === 'object' && part in current) {
            current = current[part];
        }
        else {
            return defaultValue;
        }
    }
    return current;
}
/**
 * Validate manifest structure (v3.3 only - no backward compatibility)
 */
export function validateManifest(manifest) {
    const errors = [];
    if (!manifest) {
        errors.push('Manifest is null or undefined');
        return { valid: false, errors };
    }
    // Required fields
    if (!manifest.specVersion) {
        errors.push('Missing required field: specVersion');
    }
    else if (!manifest.specVersion.match(/^\d+\.\d+/)) {
        errors.push(`Invalid specVersion format: ${manifest.specVersion}. Expected semver (e.g., 3.5.0).`);
    }
    if (!manifest.name) {
        errors.push('Missing required field: name');
    }
    if (!manifest.version) {
        errors.push('Missing required field: version');
    }
    // v3.3 required: deployment reference
    if (!manifest.deployment) {
        errors.push('Missing required field: deployment (must reference a deployment specification)');
    }
    else {
        if (!manifest.deployment.deploymentSource) {
            errors.push('deployment.deploymentSource is required');
        }
        if (!manifest.deployment.deploymentName) {
            errors.push('deployment.deploymentName is required');
        }
    }
    // v3.3 required: at least one mapping strategy
    const hasMappings = manifest.defaultMappings ||
        (manifest.capabilityMappings && manifest.capabilityMappings.length > 0) ||
        (manifest.instanceMappings && manifest.instanceMappings.length > 0);
    if (!hasMappings) {
        errors.push('At least one mapping strategy is required: defaultMappings, capabilityMappings, or instanceMappings');
    }
    return {
        valid: errors.length === 0,
        errors
    };
}
/**
 * Merge manifests (v3.3 composition)
 */
export function mergeManifests(baseManifest, overrideManifest) {
    if (!baseManifest)
        return overrideManifest || null;
    if (!overrideManifest)
        return baseManifest;
    // v3.3 merge: arrays override completely, objects merge
    return {
        ...baseManifest,
        ...overrideManifest,
        // Deployment reference: override completely
        deployment: overrideManifest.deployment || baseManifest.deployment,
        // Default mappings: merge objects
        defaultMappings: {
            ...(baseManifest.defaultMappings || {}),
            ...(overrideManifest.defaultMappings || {})
        },
        // Capability mappings: override array completely
        capabilityMappings: overrideManifest.capabilityMappings || baseManifest.capabilityMappings,
        // Instance mappings: override array completely
        instanceMappings: overrideManifest.instanceMappings || baseManifest.instanceMappings,
        // Configuration: merge objects
        configuration: {
            ...(baseManifest.configuration || {}),
            ...(overrideManifest.configuration || {})
        }
    };
}
/**
 * Get manifest summary for debugging
 */
export function getManifestSummary(manifest) {
    const strategies = [];
    if (manifest.defaultMappings) {
        const count = Object.keys(manifest.defaultMappings).length;
        strategies.push(`defaultMappings (${count} categories)`);
    }
    if (manifest.capabilityMappings && manifest.capabilityMappings.length > 0) {
        strategies.push(`capabilityMappings (${manifest.capabilityMappings.length} patterns)`);
    }
    if (manifest.instanceMappings && manifest.instanceMappings.length > 0) {
        strategies.push(`instanceMappings (${manifest.instanceMappings.length} instances)`);
    }
    return {
        name: manifest.name,
        version: manifest.version,
        deployment: `${manifest.deployment?.deploymentName || 'unknown'} from ${manifest.deployment?.deploymentSource || 'unknown'}`,
        mappingStrategies: strategies
    };
}
//# sourceMappingURL=manifest-loader.js.map