"use strict";
/**
 * Shared validation helpers for composite CLIProxy variants.
 * Used by API routes, service layer, and config loader to avoid contract drift.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateCompositeTiers = exports.validateCompositeDefaultTier = exports.VALID_COMPOSITE_TIERS = void 0;
const unified_config_types_1 = require("../../config/unified-config-types");
const model_id_normalizer_1 = require("../ai-providers/model-id-normalizer");
exports.VALID_COMPOSITE_TIERS = ['opus', 'sonnet', 'haiku'];
function isRecord(value) {
    return typeof value === 'object' && value !== null && !Array.isArray(value);
}
function isValidProvider(provider) {
    return (typeof provider === 'string' &&
        unified_config_types_1.CLIPROXY_SUPPORTED_PROVIDERS.includes(provider));
}
function validateCompositeDefaultTier(defaultTier) {
    if (defaultTier !== undefined &&
        !exports.VALID_COMPOSITE_TIERS.includes(defaultTier)) {
        return `Invalid default_tier '${String(defaultTier)}': must be one of ${exports.VALID_COMPOSITE_TIERS.join(', ')}`;
    }
    return null;
}
exports.validateCompositeDefaultTier = validateCompositeDefaultTier;
/**
 * Validate composite tier payload.
 *
 * Create mode (`requireAllTiers=true`): all tiers required.
 * Update mode (`requireAllTiers=false`): partial tiers allowed.
 */
function validateCompositeTiers(tiers, options = {}) {
    const { defaultTier, requireAllTiers = false } = options;
    const defaultTierError = validateCompositeDefaultTier(defaultTier);
    if (defaultTierError) {
        return defaultTierError;
    }
    if (!isRecord(tiers)) {
        return "Invalid tiers payload: expected object with tier keys ('opus', 'sonnet', 'haiku')";
    }
    const tierMap = tiers;
    for (const tier of exports.VALID_COMPOSITE_TIERS) {
        const tierValue = tierMap[tier];
        if (requireAllTiers && tierValue === undefined) {
            return `Missing required tier '${tier}': all tiers (opus, sonnet, haiku) required for create`;
        }
        if (tierValue === undefined) {
            continue;
        }
        if (!isRecord(tierValue)) {
            return `Invalid tier config for '${tier}': expected object with provider and model`;
        }
        const provider = tierValue.provider;
        const model = tierValue.model;
        if (typeof provider !== 'string' || typeof model !== 'string') {
            return `Invalid tier config for '${tier}': requires 'provider' and 'model' strings`;
        }
        if (!model.trim()) {
            return `Invalid model for tier '${tier}': model cannot be empty or whitespace`;
        }
        if (!isValidProvider(provider)) {
            return `Invalid provider '${provider}' for tier '${tier}': must be one of ${unified_config_types_1.CLIPROXY_SUPPORTED_PROVIDERS.join(', ')}`;
        }
        const deniedTierModelReason = (0, model_id_normalizer_1.getDeniedModelIdReasonForProvider)(model, provider);
        if (deniedTierModelReason) {
            return `Invalid model for tier '${tier}': ${deniedTierModelReason}`;
        }
        if (tierValue.fallback !== undefined) {
            const fallback = tierValue.fallback;
            if (!isRecord(fallback)) {
                return `Invalid fallback config for tier '${tier}': expected object with provider and model`;
            }
            if (typeof fallback.provider !== 'string' || typeof fallback.model !== 'string') {
                return `Invalid fallback config for tier '${tier}': requires 'provider' and 'model' strings`;
            }
            if (!fallback.model.trim()) {
                return `Invalid fallback model for tier '${tier}': model cannot be empty or whitespace`;
            }
            if (!isValidProvider(fallback.provider)) {
                return `Invalid fallback provider '${fallback.provider}' for tier '${tier}': must be one of ${unified_config_types_1.CLIPROXY_SUPPORTED_PROVIDERS.join(', ')}`;
            }
            const deniedFallbackReason = (0, model_id_normalizer_1.getDeniedModelIdReasonForProvider)(fallback.model, fallback.provider);
            if (deniedFallbackReason) {
                return `Invalid fallback model for tier '${tier}': ${deniedFallbackReason}`;
            }
            if (fallback.provider === provider && fallback.model === model) {
                return `Circular fallback in tier '${tier}': fallback cannot point to same provider and model`;
            }
        }
    }
    return null;
}
exports.validateCompositeTiers = validateCompositeTiers;
//# sourceMappingURL=composite-validator.js.map