import { formatPath } from "../chokidar/dist/esm/utils/formatter.mjs";
import { parallelize } from "../chokidar/dist/esm/utils/parallelize.mjs";
import { prepareIntlayer } from "../chokidar/dist/esm/prepareIntlayer.mjs";
import { writeContentDeclaration } from "../chokidar/dist/esm/writeContentDeclaration/writeContentDeclaration.mjs";
import { listGitFiles } from "../chokidar/dist/esm/listGitFiles.mjs";
import { getUnmergedDictionaries } from "../unmerged-dictionaries-entry/dist/esm/index.mjs";
import { getIntlayerAPIProxy } from "../api/dist/esm/proxy.mjs";
import { checkCMSAuth } from "../utils/checkAccess.mjs";
import { PushLogger } from "../pushLog.mjs";
import { join } from "node:path";
import * as fsPromises from "node:fs/promises";
import { ANSIColors, getAppLogger, getConfiguration } from "@intlayer/config";
import * as readline from "node:readline";

//#region ../@intlayer/cli/dist/esm/push/push.mjs
const statusIconsAndColors = {
	pushed: {
		icon: "✔",
		color: ANSIColors.GREEN
	},
	modified: {
		icon: "✔",
		color: ANSIColors.GREEN
	},
	error: {
		icon: "✖",
		color: ANSIColors.RED
	},
	default: {
		icon: "⏲",
		color: ANSIColors.BLUE
	}
};
const getIconAndColor = (status) => {
	return statusIconsAndColors[status] ?? statusIconsAndColors.default;
};
/**
* Get all local dictionaries and push them simultaneously.
*/
const push = async (options) => {
	const config = getConfiguration(options?.configOptions);
	const appLogger = getAppLogger(config, { config: { prefix: "" } });
	if (options?.build === true) await prepareIntlayer(config, { forceRun: true });
	else if (typeof options?.build === "undefined") await prepareIntlayer(config);
	try {
		if (!await checkCMSAuth(config)) return;
		const intlayerAPI = getIntlayerAPIProxy(void 0, config);
		const unmergedDictionariesRecord = getUnmergedDictionaries(config);
		let dictionaries = Object.values(unmergedDictionariesRecord).flat();
		const existingDictionariesKeys = Object.keys(unmergedDictionariesRecord);
		if (options?.dictionaries) {
			const noneExistingDictionariesOption = options.dictionaries.filter((dictionaryId) => !existingDictionariesKeys.includes(dictionaryId));
			if (noneExistingDictionariesOption.length > 0) appLogger(`The following dictionaries do not exist: ${noneExistingDictionariesOption.join(", ")} and have been ignored.`, { level: "error" });
			dictionaries = dictionaries.filter((dictionary) => options.dictionaries?.includes(dictionary.key));
		}
		if (options?.gitOptions) {
			const gitFiles = await listGitFiles(options.gitOptions);
			dictionaries = dictionaries.filter((dictionary) => gitFiles.includes(join(config.content.baseDir, dictionary.filePath ?? "")));
		}
		if (dictionaries.length === 0) {
			appLogger("No local dictionaries found", { level: "error" });
			return;
		}
		appLogger("Pushing dictionaries:");
		const dictionariesStatuses = dictionaries.map((dictionary) => ({
			dictionary,
			status: "pending"
		}));
		const logger$1 = new PushLogger();
		logger$1.update(dictionariesStatuses.map((s) => ({
			dictionaryKey: s.dictionary.key,
			status: "pending"
		})));
		const successfullyPushedDictionaries = [];
		const processDictionary = async (statusObj) => {
			statusObj.status = "pushing";
			logger$1.update([{
				dictionaryKey: statusObj.dictionary.key,
				status: "pushing"
			}]);
			try {
				const pushResult = await intlayerAPI.dictionary.pushDictionaries([statusObj.dictionary]);
				const updatedDictionaries = pushResult.data?.updatedDictionaries ?? [];
				const newDictionaries = pushResult.data?.newDictionaries ?? [];
				const allDictionaries = [...updatedDictionaries, ...newDictionaries];
				for (const remoteDictionaryData of allDictionaries) {
					const localDictionary = unmergedDictionariesRecord[remoteDictionaryData.key]?.find((dictionary) => dictionary.localId === remoteDictionaryData.localId);
					if (!localDictionary) continue;
					await writeContentDeclaration({
						...localDictionary,
						id: remoteDictionaryData.id
					}, config);
				}
				if (updatedDictionaries.some((dictionary) => dictionary.key === statusObj.dictionary.key)) {
					statusObj.status = "modified";
					successfullyPushedDictionaries.push(statusObj.dictionary);
					logger$1.update([{
						dictionaryKey: statusObj.dictionary.key,
						status: "modified"
					}]);
				} else if (newDictionaries.some((dictionary) => dictionary.key === statusObj.dictionary.key)) {
					statusObj.status = "pushed";
					successfullyPushedDictionaries.push(statusObj.dictionary);
					logger$1.update([{
						dictionaryKey: statusObj.dictionary.key,
						status: "pushed"
					}]);
				} else statusObj.status = "unknown";
			} catch (error) {
				statusObj.status = "error";
				statusObj.error = error;
				statusObj.errorMessage = `Error pushing dictionary ${statusObj.dictionary.key}: ${error}`;
				logger$1.update([{
					dictionaryKey: statusObj.dictionary.key,
					status: "error"
				}]);
			}
		};
		await parallelize(dictionariesStatuses, processDictionary, 5);
		logger$1.finish();
		for (const dictionaryStatus of dictionariesStatuses) {
			const { icon, color } = getIconAndColor(dictionaryStatus.status);
			appLogger(` - ${dictionaryStatus.dictionary.key} ${ANSIColors.GREY}[${color}${icon} ${dictionaryStatus.status}${ANSIColors.GREY}]${ANSIColors.RESET}`);
		}
		for (const statusObj of dictionariesStatuses) if (statusObj.errorMessage) appLogger(statusObj.errorMessage, { level: "error" });
		const deleteOption = options?.deleteLocaleDictionary;
		const keepOption = options?.keepLocaleDictionary;
		if (deleteOption && keepOption) throw new Error("Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.");
		if (deleteOption) await deleteLocalDictionaries(successfullyPushedDictionaries, options);
		else if (keepOption) {} else {
			const answer = await askUser("Do you want to delete the local dictionaries that were successfully pushed? (yes/no): ");
			if (answer.toLowerCase() === "yes" || answer.toLowerCase() === "y") await deleteLocalDictionaries(successfullyPushedDictionaries, options);
		}
	} catch (error) {
		appLogger(error, { level: "error" });
	}
};
const askUser = (question) => {
	const rl = readline.createInterface({
		input: process.stdin,
		output: process.stdout
	});
	return new Promise((resolve$1) => {
		rl.question(question, (answer) => {
			rl.close();
			resolve$1(answer);
		});
	});
};
const deleteLocalDictionaries = async (dictionariesToDelete, options) => {
	const appLogger = getAppLogger(getConfiguration(options?.configOptions), { config: { prefix: "" } });
	const filePathsSet = /* @__PURE__ */ new Set();
	for (const dictionary of dictionariesToDelete) {
		const { filePath } = dictionary;
		if (!filePath) {
			appLogger(`Dictionary ${dictionary.key} does not have a file path`, { level: "error" });
			continue;
		}
		filePathsSet.add(filePath);
	}
	for (const filePath of filePathsSet) try {
		const stats = await fsPromises.lstat(filePath);
		if (stats.isFile()) {
			await fsPromises.unlink(filePath);
			appLogger(`Deleted file ${formatPath(filePath)}`, {});
		} else if (stats.isDirectory()) appLogger(`Path is a directory ${formatPath(filePath)}, skipping.`, {});
		else appLogger(`Unknown file type for ${formatPath(filePath)}, skipping.`, {});
	} catch (err) {
		appLogger(`Error deleting ${formatPath(filePath)}: ${err}`, { level: "error" });
	}
};

//#endregion
export { push };
//# sourceMappingURL=push.mjs.map