import { logger } from '../utils/logger.js';
export function getCostFromPricingCatalog(modelId, catalog, modelLimitsService, opts = {}) {
    if (modelId.endsWith(':free')) {
        return { input: 0, output: 0 };
    }
    const exact = catalog.models.find((model) => model.id === modelId);
    if (exact) {
        if (exact.tier === 'free')
            return { input: 0, output: 0 };
        return { input: exact.pricing.input, output: exact.pricing.output };
    }
    for (const model of catalog.models) {
        if (modelId.startsWith(model.id) || modelId.includes(model.id)) {
            if (model.tier === 'free')
                return { input: 0, output: 0 };
            return { input: model.pricing.input, output: model.pricing.output };
        }
    }
    if (catalog.models.length === 0) {
        const slashIdx = modelId.indexOf('/');
        const provider = slashIdx !== -1 ? modelId.slice(0, slashIdx) : '';
        const orPricing = modelLimitsService?.getPricingForModel(modelId, provider) ?? null;
        if (orPricing) {
            return { input: orPricing.prompt * 1_000_000, output: orPricing.completion * 1_000_000 };
        }
    }
    if (opts.debug) {
        logger.debug('[cost-tracker] model not in catalog', { modelId });
    }
    return { input: 0, output: 0 };
}
export function normalizeModelId(modelId) {
    let id = modelId;
    if (id.startsWith('coding-'))
        id = id.slice('coding-'.length);
    const slashIdx = id.lastIndexOf('/');
    if (slashIdx !== -1)
        id = id.slice(slashIdx + 1);
    if (id.endsWith(':free'))
        id = id.slice(0, -':free'.length);
    if (id.endsWith('-free'))
        id = id.slice(0, -'-free'.length);
    return id;
}
export function hasKeyForProvider(provider) {
    if (provider.requiresKey === false || provider.envVars.length === 0)
        return true;
    return provider.envVars.some((envVar) => {
        const value = process.env[envVar];
        return typeof value === 'string' && value.length > 0;
    });
}
export class RegistryBackedCatalog {
    registry;
    entriesCache = null;
    entriesCacheVersion = -1;
    constructor(registry) {
        this.registry = registry;
    }
    getEntries() {
        const models = this.registry.listModels();
        if (this.entriesCache !== null && models.length === this.entriesCacheVersion) {
            return this.entriesCache;
        }
        this.entriesCacheVersion = models.length;
        this.entriesCache = models.map((model) => ({
            id: model.id,
            displayName: model.displayName,
            provider: model.provider,
            context: this.registry.getContextWindowForModel(model),
            tier: (model.tier ?? 'paid'),
        }));
        return this.entriesCache;
    }
    getModel(modelId) {
        return this.getEntries().find((entry) => entry.id === modelId) ?? null;
    }
    findLargerContextModels(minContext, tier, limit = 3) {
        return this.getEntries()
            .filter((entry) => entry.context > minContext && (tier === undefined || entry.tier === tier))
            .sort((a, b) => b.context - a.context)
            .slice(0, limit);
    }
}
export function createModelCatalog(registry) {
    return new RegistryBackedCatalog(registry);
}
export function getCatalogModelDefinitionsFrom(models) {
    return models.map((model) => {
        const providerLower = model.provider.toLowerCase();
        const isFree = model.tier === 'free';
        const isGoogle = providerLower.includes('google') || providerLower.includes('gemini');
        const isAnthropic = providerLower.includes('anthropic');
        const isOpenAI = providerLower.includes('openai');
        const hasReasoning = model.reasoning === true || isAnthropic || isOpenAI || isGoogle;
        const hasCatalogContextWindow = model.contextWindow != null;
        return {
            id: model.id,
            provider: model.providerId,
            registryKey: `${model.providerId}:${model.id}`,
            displayName: model.name,
            description: `${model.name} — sourced from model catalog.`,
            capabilities: {
                toolCalling: true,
                codeEditing: true,
                reasoning: hasReasoning,
                multimodal: isGoogle || isOpenAI,
            },
            contextWindow: hasCatalogContextWindow
                ? model.contextWindow
                : (isGoogle ? 1_000_000 : isAnthropic ? 200_000 : 128_000),
            ...(!hasCatalogContextWindow ? { contextWindowProvenance: 'fallback' } : {}),
            selectable: true,
            tier: model.tier === 'subscription' ? 'subscription' : isFree ? 'free' : model.pricing.input >= 3 ? 'premium' : 'standard',
            ...(hasReasoning ? { reasoningEffort: ['instant', 'low', 'medium', 'high'] } : {}),
        };
    });
}
export { fetchCatalog, getCatalogCachePath, getCatalogTmpPath, isCatalogCacheStale, loadCatalogCache, saveCatalogCache, } from './model-catalog-cache.js';
export { buildSyntheticCanonicalModels, getSyntheticBackendModelIds, getSyntheticModelDefinitions, getSyntheticModelInfo, nameToSlug, normalizeModelName, } from './model-catalog-synthetic.js';
export { diffCatalogs, filterRelevantChanges, formatChangeNotifications, notifyCatalogChanges, } from './model-catalog-notifications.js';
