// engine/llm-providers/cost-optimizer.ts — Cost optimization engine.
// SPEC-083 AC-05, AC-14
import { checkProviderHealth } from './health-checker.js';
import equivalencesData from '../../config/model-equivalences.json' with { type: 'json' };
import affinityData from '../../config/model-language-affinity.json' with { type: 'json' };
/** Map task complexity to quality tier. */
export function complexityToTier(complexity) {
    switch (complexity) {
        case 'complex':
            return 'high';
        case 'standard':
            return 'medium';
        case 'simple':
            return 'low';
    }
}
/**
 * Find the cheapest provider+model that meets the quality tier requirement.
 * Returns ranked recommendations sorted by cost (cheapest first).
 */
export function optimizeCost(definitions, tier, language) {
    const candidates = [];
    for (const def of definitions) {
        const health = checkProviderHealth(def);
        if (health.status === 'unavailable') {
            continue;
        }
        const matchingModels = def.models.filter((m) => m.tier === tier);
        for (const model of matchingModels) {
            const totalCostPer1M = model.pricingPerMToken.input + model.pricingPerMToken.output;
            const affinityBonus = getLanguageAffinityBonus(def.id, language);
            candidates.push({
                providerId: def.id,
                modelId: model.id,
                tier: model.tier,
                costEstimate: {
                    tokensEstimated: 1_000_000,
                    usdEstimated: totalCostPer1M,
                },
                reasoning: buildReasoning(def, model.id, totalCostPer1M, language),
                score: 1.0 / (totalCostPer1M + 0.001) + affinityBonus,
            });
        }
    }
    return candidates.sort((a, b) => a.costEstimate.usdEstimated - b.costEstimate.usdEstimated);
}
/**
 * Calculate potential savings compared to the most expensive provider for a tier.
 */
export function calculateSavings(definitions, tier, tokensEstimated) {
    const ranked = optimizeCost(definitions, tier);
    if (ranked.length < 2) {
        return null;
    }
    const cheapest = ranked[0];
    const expensive = ranked[ranked.length - 1];
    if (!cheapest || !expensive) {
        return null;
    }
    const cheapCost = (cheapest.costEstimate.usdEstimated / 1_000_000) * tokensEstimated;
    const expCost = (expensive.costEstimate.usdEstimated / 1_000_000) * tokensEstimated;
    const savings = expCost - cheapCost;
    return {
        cheapestProvider: `${cheapest.providerId}/${cheapest.modelId}`,
        expensiveProvider: `${expensive.providerId}/${expensive.modelId}`,
        savingsUsd: Math.round(savings * 10000) / 10000,
        savingsPercent: expCost > 0 ? Math.round((savings / expCost) * 100) : 0,
    };
}
function getLanguageAffinityBonus(providerId, language) {
    if (!language) {
        return 0;
    }
    const entry = affinityData.affinities.find((a) => a.language === language.toLowerCase());
    if (!entry) {
        return 0;
    }
    const rank = entry.preferredProviders.indexOf(providerId);
    if (rank === -1) {
        return 0;
    }
    return entry.weight * (1 - rank * 0.3);
}
function buildReasoning(def, modelId, costPer1M, language) {
    const reasons = [`${def.name} ${modelId}: $${costPer1M.toFixed(2)}/1M tokens (in+out)`];
    if (language) {
        const bonus = getLanguageAffinityBonus(def.id, language);
        if (bonus > 0) {
            reasons.push(`Language affinity bonus for ${language}: +${bonus.toFixed(2)}`);
        }
    }
    return reasons;
}
/**
 * Get model equivalences for a given tier from config.
 */
export function getEquivalences(tier) {
    const equiv = equivalencesData.equivalences.find((e) => e.tier === tier);
    return equiv?.models ?? [];
}
//# sourceMappingURL=cost-optimizer.js.map