"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.startModelsDevRegistryRefresh = exports.refreshModelsDevRegistry = exports.clearModelsDevRegistryCache = exports.setCachedModelsDevRegistry = exports.getCachedModelsDevRegistry = exports.MODELS_DEV_API_URL = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const config_loader_facade_1 = require("../../config/config-loader-facade");
exports.MODELS_DEV_API_URL = 'https://models.dev/api.json';
const CACHE_FILE_NAME = 'models-dev-registry-cache.json';
const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
const LIVE_FETCH_TIMEOUT_MS = 3000;
let pendingBackgroundRefresh = null;
function getCacheFilePath() {
    return path.join((0, config_loader_facade_1.getCcsDir)(), CACHE_FILE_NAME);
}
function isPlainObject(value) {
    return typeof value === 'object' && value !== null && !Array.isArray(value);
}
function normalizeRegistryPayload(payload) {
    if (!isPlainObject(payload))
        return null;
    const providers = {};
    for (const [key, value] of Object.entries(payload)) {
        if (!isPlainObject(value))
            continue;
        const id = typeof value.id === 'string' && value.id.trim() ? value.id.trim() : key;
        const modelsPayload = isPlainObject(value.models) ? value.models : undefined;
        if (!modelsPayload)
            continue;
        const models = {};
        for (const [modelKey, modelValue] of Object.entries(modelsPayload)) {
            if (!isPlainObject(modelValue))
                continue;
            const modelId = typeof modelValue.id === 'string' && modelValue.id.trim() ? modelValue.id.trim() : modelKey;
            models[modelKey] = {
                ...modelValue,
                id: modelId,
            };
        }
        if (Object.keys(models).length === 0)
            continue;
        providers[id] = {
            ...value,
            id,
            models,
        };
    }
    return Object.keys(providers).length > 0 ? providers : null;
}
function normalizeCachePayload(payload) {
    if (!isPlainObject(payload))
        return null;
    if (payload.version !== 1 || typeof payload.fetchedAt !== 'number')
        return null;
    const providers = normalizeRegistryPayload(payload.providers);
    return providers ? { version: 1, fetchedAt: payload.fetchedAt, providers } : null;
}
function getCachedModelsDevRegistry(options = {}) {
    try {
        const filePath = getCacheFilePath();
        if (!fs.existsSync(filePath))
            return null;
        const cache = normalizeCachePayload(JSON.parse(fs.readFileSync(filePath, 'utf8')));
        if (!cache)
            return null;
        const now = options.now ?? Date.now();
        if (!options.allowStale && now - cache.fetchedAt > CACHE_TTL_MS)
            return null;
        return cache.providers;
    }
    catch {
        return null;
    }
}
exports.getCachedModelsDevRegistry = getCachedModelsDevRegistry;
function setCachedModelsDevRegistry(providers, fetchedAt = Date.now()) {
    try {
        const filePath = getCacheFilePath();
        fs.mkdirSync(path.dirname(filePath), { recursive: true });
        const cache = { version: 1, fetchedAt, providers };
        fs.writeFileSync(filePath, JSON.stringify(cache));
    }
    catch {
        // Best-effort cache writes must not break analytics.
    }
}
exports.setCachedModelsDevRegistry = setCachedModelsDevRegistry;
function clearModelsDevRegistryCache() {
    try {
        const filePath = getCacheFilePath();
        if (!fs.existsSync(filePath))
            return false;
        fs.unlinkSync(filePath);
        return true;
    }
    catch {
        return false;
    }
}
exports.clearModelsDevRegistryCache = clearModelsDevRegistryCache;
async function refreshModelsDevRegistry(options = {}) {
    const now = options.now ?? (() => Date.now());
    if (!options.force) {
        const fresh = getCachedModelsDevRegistry({ allowStale: false, now: now() });
        if (fresh)
            return fresh;
    }
    const fetchImpl = options.fetchImpl ?? fetch;
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), LIVE_FETCH_TIMEOUT_MS);
    try {
        const response = await fetchImpl(exports.MODELS_DEV_API_URL, {
            signal: controller.signal,
            headers: { Accept: 'application/json' },
        });
        if (!response.ok)
            return getCachedModelsDevRegistry({ allowStale: true });
        const providers = normalizeRegistryPayload(await response.json());
        if (!providers)
            return getCachedModelsDevRegistry({ allowStale: true });
        setCachedModelsDevRegistry(providers, now());
        return providers;
    }
    catch {
        return getCachedModelsDevRegistry({ allowStale: true });
    }
    finally {
        clearTimeout(timeoutId);
    }
}
exports.refreshModelsDevRegistry = refreshModelsDevRegistry;
function startModelsDevRegistryRefresh(options = {}) {
    if (!pendingBackgroundRefresh) {
        pendingBackgroundRefresh = refreshModelsDevRegistry(options)
            .catch(() => null)
            .finally(() => {
            pendingBackgroundRefresh = null;
        });
    }
    return pendingBackgroundRefresh;
}
exports.startModelsDevRegistryRefresh = startModelsDevRegistryRefresh;
//# sourceMappingURL=registry-cache.js.map