const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
const require_utils_checkAccess = require('./utils/checkAccess.cjs');
const require_push_pullLog = require('./push/pullLog.cjs');
let __intlayer_api = require("@intlayer/api");
let __intlayer_chokidar = require("@intlayer/chokidar");
let __intlayer_config = require("@intlayer/config");
let node_path = require("node:path");
let node_fs = require("node:fs");

//#region src/pull.ts
/**
* Fetch distant dictionaries and write them locally,
* with progress indicators and concurrency control.
*/
const pull = async (options) => {
	const appLogger = (0, __intlayer_config.getAppLogger)(options?.configOptions?.override);
	try {
		const config = (0, __intlayer_config.getConfiguration)(options?.configOptions);
		if (!await require_utils_checkAccess.checkCMSAuth(config)) return;
		const intlayerAPI = (0, __intlayer_api.getIntlayerAPIProxy)(void 0, config);
		const getDictionariesUpdateTimestampResult = await intlayerAPI.dictionary.getDictionariesUpdateTimestamp();
		if (!getDictionariesUpdateTimestampResult.data) throw new Error("No distant dictionaries found");
		let distantDictionariesUpdateTimeStamp = getDictionariesUpdateTimestampResult.data;
		if (options?.dictionaries) distantDictionariesUpdateTimeStamp = Object.fromEntries(Object.entries(distantDictionariesUpdateTimeStamp).filter(([key]) => options.dictionaries?.includes(key)));
		const remoteDictionariesPath = (0, node_path.join)(config.content.mainDir, "remote_dictionaries.cjs");
		const requireFunction = config.build?.require ?? (0, __intlayer_config.getProjectRequire)();
		const remoteDictionariesRecord = (0, node_fs.existsSync)(remoteDictionariesPath) ? requireFunction(remoteDictionariesPath) : {};
		const entries = Object.entries(distantDictionariesUpdateTimeStamp);
		const keysToFetch = entries.filter(([key, remoteUpdatedAt]) => {
			if (!remoteUpdatedAt) return true;
			const local = remoteDictionariesRecord[key];
			if (!local) return true;
			const localUpdatedAtRaw = local?.updatedAt;
			const localUpdatedAt = typeof localUpdatedAtRaw === "number" ? localUpdatedAtRaw : localUpdatedAtRaw ? new Date(localUpdatedAtRaw).getTime() : void 0;
			if (typeof localUpdatedAt !== "number") return true;
			return remoteUpdatedAt > localUpdatedAt;
		}).map(([key]) => key);
		const cachedKeys = entries.filter(([key, remoteUpdatedAt]) => {
			const localUpdatedAtRaw = remoteDictionariesRecord[key]?.updatedAt;
			const localUpdatedAt = typeof localUpdatedAtRaw === "number" ? localUpdatedAtRaw : localUpdatedAtRaw ? new Date(localUpdatedAtRaw).getTime() : void 0;
			return typeof localUpdatedAt === "number" && typeof remoteUpdatedAt === "number" && localUpdatedAt >= remoteUpdatedAt;
		}).map(([key]) => key);
		if (entries.length === 0) {
			appLogger("No dictionaries to fetch", { level: "error" });
			return;
		}
		appLogger("Fetching dictionaries:");
		const dictionariesStatuses = [...cachedKeys.map((dictionaryKey) => ({
			dictionaryKey,
			status: "imported"
		})), ...keysToFetch.map((dictionaryKey) => ({
			dictionaryKey,
			status: "pending"
		}))];
		const logger = new require_push_pullLog.PullLogger();
		logger.update(dictionariesStatuses.map((s) => ({
			dictionaryKey: s.dictionaryKey,
			status: s.status
		})));
		const successfullyFetchedDictionaries = [];
		const processDictionary = async (statusObj) => {
			const isCached = statusObj.status === "imported" || statusObj.status === "up-to-date";
			if (!isCached) {
				statusObj.status = "fetching";
				logger.update([{
					dictionaryKey: statusObj.dictionaryKey,
					status: "fetching"
				}]);
			}
			try {
				let sourceDictionary;
				if (isCached) sourceDictionary = remoteDictionariesRecord[statusObj.dictionaryKey];
				if (!sourceDictionary) sourceDictionary = (await intlayerAPI.dictionary.getDictionary(statusObj.dictionaryKey)).data;
				if (!sourceDictionary) throw new Error(`Dictionary ${statusObj.dictionaryKey} not found on remote`);
				const { status } = await (0, __intlayer_chokidar.writeContentDeclaration)(sourceDictionary, config, options);
				statusObj.status = status;
				logger.update([{
					dictionaryKey: statusObj.dictionaryKey,
					status
				}]);
				successfullyFetchedDictionaries.push(sourceDictionary);
			} catch (error) {
				statusObj.status = "error";
				statusObj.error = error;
				statusObj.errorMessage = `Error fetching dictionary ${statusObj.dictionaryKey}: ${error}`;
				logger.update([{
					dictionaryKey: statusObj.dictionaryKey,
					status: "error"
				}]);
			}
		};
		await (0, __intlayer_chokidar.parallelize)(dictionariesStatuses, processDictionary, 5);
		logger.finish();
		const iconFor = (status) => {
			switch (status) {
				case "fetched":
				case "imported":
				case "updated":
				case "up-to-date":
				case "reimported in JSON":
				case "new content file": return "✔";
				case "error": return "✖";
				default: return "⏲";
			}
		};
		const colorFor = (status) => {
			switch (status) {
				case "fetched":
				case "imported":
				case "updated":
				case "up-to-date": return __intlayer_config.ANSIColors.GREEN;
				case "reimported in JSON":
				case "new content file": return __intlayer_config.ANSIColors.YELLOW;
				case "error": return __intlayer_config.ANSIColors.RED;
				default: return __intlayer_config.ANSIColors.BLUE;
			}
		};
		for (const s of dictionariesStatuses) {
			const icon = iconFor(s.status);
			const color = colorFor(s.status);
			appLogger(` - ${s.dictionaryKey} ${__intlayer_config.ANSIColors.GREY}[${color}${icon} ${s.status}${__intlayer_config.ANSIColors.GREY}]${__intlayer_config.ANSIColors.RESET}`);
		}
		for (const statusObj of dictionariesStatuses) if (statusObj.errorMessage) appLogger(statusObj.errorMessage, { level: "error" });
	} catch (error) {
		appLogger(error, { level: "error" });
	}
};

//#endregion
exports.pull = pull;
//# sourceMappingURL=pull.cjs.map