/**
 * Release configuration loader and validator.
 *
 * Loads release configuration from .cleo/config.json, providing defaults
 * for versioning scheme, changelog format, artifact types, and gates.
 *
 * @task T4454
 * @epic T4454
 */
import { existsSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
import { getCleoDir } from '../paths.js';
/** Synchronous config value reader (avoids async config pipeline). */
function readConfigValueSync(path, defaultValue, cwd) {
    try {
        const configPath = join(getCleoDir(cwd), 'config.json');
        if (!existsSync(configPath))
            return defaultValue;
        const config = JSON.parse(readFileSync(configPath, 'utf-8'));
        const keys = path.split('.');
        let value = config;
        for (const key of keys) {
            if (value == null || typeof value !== 'object')
                return defaultValue;
            value = value[key];
        }
        return value ?? defaultValue;
    }
    catch {
        return defaultValue;
    }
}
/** Default configuration values. */
const DEFAULTS = {
    versioningScheme: 'calver',
    tagPrefix: 'v',
    changelogFormat: 'keepachangelog',
    changelogFile: 'CHANGELOG.md',
    artifactType: 'generic-tarball',
};
/** Load release configuration with defaults. */
export function loadReleaseConfig(cwd) {
    return {
        versioningScheme: readConfigValueSync('release.versioning.scheme', DEFAULTS.versioningScheme, cwd),
        tagPrefix: readConfigValueSync('release.versioning.tagPrefix', DEFAULTS.tagPrefix, cwd),
        changelogFormat: readConfigValueSync('release.changelog.format', DEFAULTS.changelogFormat, cwd),
        changelogFile: readConfigValueSync('release.changelog.file', DEFAULTS.changelogFile, cwd),
        artifactType: readConfigValueSync('release.artifact.type', DEFAULTS.artifactType, cwd),
        gates: readConfigValueSync('release.gates', [], cwd),
        versionBump: {
            files: readConfigValueSync('release.versionBump.files', [], cwd),
        },
        security: {
            enableProvenance: readConfigValueSync('release.security.enableProvenance', false, cwd),
            slsaLevel: readConfigValueSync('release.security.slsaLevel', 3, cwd),
            requireSignedCommits: readConfigValueSync('release.security.requireSignedCommits', false, cwd),
        },
    };
}
/** Validate release configuration. */
export function validateReleaseConfig(config) {
    const errors = [];
    const warnings = [];
    // Validate versioning scheme
    const validSchemes = ['semver', 'calver', 'custom'];
    if (!validSchemes.includes(config.versioningScheme)) {
        errors.push(`Invalid versioning scheme: ${config.versioningScheme}`);
    }
    // Validate changelog format
    const validFormats = ['keepachangelog', 'conventional', 'custom'];
    if (!validFormats.includes(config.changelogFormat)) {
        warnings.push(`Unknown changelog format: ${config.changelogFormat}`);
    }
    // Validate gates
    for (const gate of config.gates) {
        if (!gate.name)
            errors.push('Gate missing name');
        if (!gate.command)
            errors.push(`Gate '${gate.name}' missing command`);
    }
    // Validate version bump targets
    for (const file of config.versionBump.files) {
        if (!file.file)
            errors.push('Version bump target missing file');
        const validStrategies = ['plain', 'json', 'toml', 'sed'];
        if (!validStrategies.includes(file.strategy)) {
            errors.push(`Invalid bump strategy for ${file.file}: ${file.strategy}`);
        }
    }
    return { valid: errors.length === 0, errors, warnings };
}
/** Get artifact type from config. */
export function getArtifactType(cwd) {
    return loadReleaseConfig(cwd).artifactType;
}
/** Get release gates from config. */
export function getReleaseGates(cwd) {
    return loadReleaseConfig(cwd).gates;
}
/** Get changelog configuration. */
export function getChangelogConfig(cwd) {
    const config = loadReleaseConfig(cwd);
    return { format: config.changelogFormat, file: config.changelogFile };
}
/** Return the default GitFlow branch configuration. */
export function getDefaultGitFlowConfig() {
    return {
        enabled: true,
        branches: {
            main: 'main',
            develop: 'develop',
            featurePrefix: 'feature/',
            hotfixPrefix: 'hotfix/',
            releasePrefix: 'release/',
        },
    };
}
/** Merge caller-supplied GitFlow config with defaults. */
export function getGitFlowConfig(config) {
    const defaults = getDefaultGitFlowConfig();
    if (!config.gitflow)
        return defaults;
    return {
        enabled: config.gitflow.enabled ?? defaults.enabled,
        branches: {
            main: config.gitflow.branches?.main ?? defaults.branches.main,
            develop: config.gitflow.branches?.develop ?? defaults.branches.develop,
            featurePrefix: config.gitflow.branches?.featurePrefix ?? defaults.branches.featurePrefix,
            hotfixPrefix: config.gitflow.branches?.hotfixPrefix ?? defaults.branches.hotfixPrefix,
            releasePrefix: config.gitflow.branches?.releasePrefix ?? defaults.branches.releasePrefix,
        },
    };
}
/** Return the default channel configuration. */
export function getDefaultChannelConfig() {
    return {
        main: 'latest',
        develop: 'beta',
        feature: 'alpha',
    };
}
/** Merge caller-supplied channel config with defaults. */
export function getChannelConfig(config) {
    const defaults = getDefaultChannelConfig();
    if (!config.channels)
        return defaults;
    return {
        main: config.channels.main ?? defaults.main,
        develop: config.channels.develop ?? defaults.develop,
        feature: config.channels.feature ?? defaults.feature,
        custom: config.channels.custom,
    };
}
/** Return the configured push mode, defaulting to 'auto'. */
export function getPushMode(config) {
    return config.push?.mode ?? 'auto';
}
//# sourceMappingURL=release-config.js.map