import { logger } from "../../../logger/index.js";
import { compressToBase64, decompressFromBase64 } from "../../compress.js";
import upath from "upath";
import { DateTime } from "luxon";
import cacache from "cacache";

//#region lib/util/cache/package/file.ts
function getKey(namespace, key) {
	return `${namespace}-${key}`;
}
let cacheFileName;
async function rm(namespace, key) {
	logger.trace({
		namespace,
		key
	}, "Removing cache entry");
	await cacache.rm.entry(cacheFileName, getKey(namespace, key));
}
async function get(namespace, key) {
	if (!cacheFileName) return;
	try {
		const res = await cacache.get(cacheFileName, getKey(namespace, key));
		const cachedValue = JSON.parse(res.data.toString());
		// v8 ignore else -- TODO: add test #40625
		if (cachedValue) {
			if (DateTime.local() < DateTime.fromISO(cachedValue.expiry)) {
				logger.trace({
					namespace,
					key
				}, "Returning cached value");
				// istanbul ignore if
				if (!cachedValue.compress) return cachedValue.value;
				const res = await decompressFromBase64(cachedValue.value);
				return JSON.parse(res);
			}
			await rm(namespace, key);
		}
	} catch {
		logger.trace({
			namespace,
			key
		}, "Cache miss");
	}
}
async function set(namespace, key, value, hardTtlMinutes = 5) {
	if (!cacheFileName) return;
	logger.trace({
		namespace,
		key,
		hardTtlMinutes
	}, "Saving cached value");
	await cacache.put(cacheFileName, getKey(namespace, key), JSON.stringify({
		compress: true,
		value: await compressToBase64(JSON.stringify(value)),
		expiry: DateTime.local().plus({ minutes: hardTtlMinutes })
	}));
}
function init(cacheDir) {
	cacheFileName = upath.join(cacheDir, "/renovate/renovate-cache-v1");
	logger.debug("Initializing Renovate internal cache into " + cacheFileName);
	return cacheFileName;
}
async function cleanup() {
	logger.debug("Checking file package cache for expired items");
	let totalCount = 0;
	let deletedCount = 0;
	const startTime = Date.now();
	let errorCount = 0;
	for await (const item of cacache.ls.stream(cacheFileName)) try {
		totalCount += 1;
		const cachedItem = item;
		const res = await cacache.get(cacheFileName, cachedItem.key);
		let cachedValue;
		try {
			cachedValue = JSON.parse(res.data.toString());
		} catch {
			logger.debug("Error parsing cached value - deleting");
		}
		if (!cachedValue || cachedValue?.expiry && DateTime.local() > DateTime.fromISO(cachedValue.expiry)) {
			await cacache.rm.entry(cacheFileName, cachedItem.key);
			await cacache.rm.content(cacheFileName, cachedItem.integrity);
			deletedCount += 1;
		}
	} catch (err) 	/* istanbul ignore next */ {
		logger.trace({ err }, "Error cleaning up cache entry");
		errorCount += 1;
	}
	// istanbul ignore if: cannot reproduce error
	if (errorCount > 0) logger.debug(`Error count cleaning up cache: ${errorCount}`);
	const durationMs = Math.round(Date.now() - startTime);
	logger.debug(`Deleted ${deletedCount} of ${totalCount} file cached entries in ${durationMs}ms`);
}

//#endregion
export { cleanup, get, init, set };
//# sourceMappingURL=file.js.map