import * as fs from 'node:fs';
import * as path from 'node:path';

import axios from 'axios';
import dotenv from 'dotenv';

dotenv.config({ path: '.env' }).parsed;

const normalizeTranslation = (translation: string | null | undefined) => {
	if (translation == null) {
		return '';
	}
	return translation.replace(/\n/g, '\\n').replace(/"/g, "'");
};

function getSplitByIndexes(input: string, indexes: number[]): string[] {
	const parts = input.split('_');
	return indexes.map((index) => parts[index]).filter((item) => item !== undefined);
}

const prepareLuaWithFemaleVersion = (quest: Quest, type: keyof Quest, key: string) => {
	let text = '';
	const value = quest[type] as string;
	const normalizedMaleValue = normalizeTranslation(value?.[0]);
	const normalizedFemaleValue = normalizeTranslation(value?.[1]);
	if (normalizedMaleValue != '') {
		text += '\t' + key + 'Male = "' + normalizedMaleValue + '", \n';
	}
	if (normalizedFemaleValue != '') {
		text += '\t' + key + 'Female = "' + normalizedFemaleValue + '", \n';
	}
	return text;
};

const callTolgee = async <R>(
	method: 'GET' | 'POST' | 'PUT' | 'DELETE' = 'GET',
	path: string,
	params?: any,
	data?: any,
) => {
	const args = process.argv.slice(2);
	const projectId = args[1];
	try {
		return await axios<R>(`https://translate.romanjaros.local/v2/projects/${projectId}${path}`, {
			method,
			data,
			params,
			headers: {
				'X-API-KEY': process.env.TOLGEE_PAT as string,
			},
		});
	} catch (e) {
		throw e;
	}
};

function makeChunks(input: AddonData, chunkSize: number = 1000) {
	const keys = Object.keys(input);
	const result = [];

	for (let i = 0; i < keys.length; i += chunkSize) {
		const chunk = keys.slice(i, i + chunkSize).reduce((acc: AddonData, key) => {
			acc[key] = input[key];
			return acc;
		}, {});
		result.push(chunk);
	}

	return result;
}

const splitFirst = (text: string, delimiter: string) => {
	const index = text.indexOf(delimiter);
	if (index === -1) return text;
	return text.slice(index + delimiter.length);
};

const generateRoleTactic = (role: (string | null)[]) => {
	let luaQuestRecord = '';
	for (const ability of role) {
		if (ability == null) continue;
		const information = ability.split('\n');
		luaQuestRecord += `\t\t{"${information[0].trim()}","${information[1].trim()}","${information[2].trim()}","${information[3].trim()}"},\n`;
	}
	return luaQuestRecord;
};

(async () => {
	const args = process.argv.slice(2);
	const addonDir = path.join(process.cwd(), `../Addon/Data/${args[0]}`);

	const addonData: Record<string, Quest> = {};
	let pageNumber = 0;

	try {
		// load all data from tolgee
		while (true) {
			const response = await callTolgee<TolgeeTranslationsResponse>('GET', `/translations`, {
				filterTranslatedInLang: 'cs',
				languages: 'cs,csf,en',
				size: 2000,
				page: pageNumber,
			});
			const translations = response.data?._embedded?.keys ?? [];
			if (response.data?.page.totalPages > response.data?.page.number) {
				pageNumber++;

				// for each page from tolgee
				for (const tolgeeKey of translations) {
					let key = tolgeeKey.keyName;

					if (tolgeeKey.keyNamespace === 'tactic') {
						key = key.split('_')[0];
					}

					const instanceName = getSplitByIndexes(tolgeeKey.keyName, [1, 2]).join('_');

					addonData[key] = {
						...addonData[tolgeeKey.keyName],
						...(tolgeeKey.keyNamespace === 'name' && {
							names: [
								tolgeeKey.translations.cs.text,
								tolgeeKey.translations.cs.text === tolgeeKey.translations.csf.text
									? null
									: tolgeeKey.translations.csf.text,
							],
						}),
						...(tolgeeKey.keyNamespace === 'objective' && {
							objectives: [
								tolgeeKey.translations.cs.text,
								tolgeeKey.translations.cs.text === tolgeeKey.translations.csf.text
									? null
									: tolgeeKey.translations.csf.text,
							],
						}),
						...(tolgeeKey.keyNamespace === 'description' && {
							descriptions: [
								tolgeeKey.translations.cs.text,
								tolgeeKey.translations.cs.text === tolgeeKey.translations.csf.text
									? null
									: tolgeeKey.translations.csf.text,
								tolgeeKey.translations.en.text,
							],
						}),
						...(tolgeeKey.keyNamespace === 'progress' && {
							progresses: [
								tolgeeKey.translations.cs.text,
								tolgeeKey.translations.cs.text === tolgeeKey.translations.csf.text
									? null
									: tolgeeKey.translations.csf.text,
							],
						}),
						...(tolgeeKey.keyNamespace === 'completion' && {
							completions: [
								tolgeeKey.translations.cs.text,
								tolgeeKey.translations.cs.text === tolgeeKey.translations.csf.text
									? null
									: tolgeeKey.translations.csf.text,
							],
						}),
						...(tolgeeKey.keyNamespace === 'speech' && {
							speeches: [
								tolgeeKey.translations.cs.text,
								tolgeeKey.translations.cs.text === tolgeeKey.translations.csf.text
									? null
									: tolgeeKey.translations.csf.text,
								tolgeeKey.translations.en.text,
							],
						}),
						...(tolgeeKey.keyNamespace === 'tactic' && {
							tactics: {
								[instanceName]: {
									...(addonData[key]?.tactics?.[instanceName] ?? {}),
									...(tolgeeKey.keyName.endsWith('_summary') && {
										summary: tolgeeKey.translations.cs.text,
									}),
									...(tolgeeKey.keyName.includes('_tank_') && {
										tank: [...(addonData[key].tactics?.[instanceName]?.tank ?? []), tolgeeKey.translations.cs.text],
									}),
									...(tolgeeKey.keyName.includes('_healer_') && {
										healer: [...(addonData[key].tactics?.[instanceName]?.healer ?? []), tolgeeKey.translations.cs.text],
									}),
									...(tolgeeKey.keyName.includes('_dps_') && {
										dps: [...(addonData[key].tactics?.[instanceName]?.dps ?? []), tolgeeKey.translations.cs.text],
									}),
								},
							},
						}),
						name: tolgeeKey.keyDescription,
						id: tolgeeKey.keyName.replace('q', '').replace('i', ''),
						isQuest: tolgeeKey.keyName.startsWith('q'),
						isQuestItem: tolgeeKey.keyName.startsWith('i'),
					};
				}
			} else {
				break;
			}
		}

		// split into chunks
		const chunks = makeChunks(addonData);

		// build addon file
		chunks.forEach((chunk, index) => {
			const fileName = path.join(addonDir, `${index++}.lua`);
			try {
				fs.unlinkSync(fileName);
			} catch (e) {}
			fs.appendFileSync(fileName, 'local _, addon = ...\n', 'utf8');
			for (const [, czechQuest] of Object.entries(chunk)) {
				// prepare variables
				if (czechQuest.isQuest) {
					let luaQuestRecord = '';
					luaQuestRecord += `addon.data.quest[${czechQuest.id}] = {\n`;
					luaQuestRecord += prepareLuaWithFemaleVersion(czechQuest, 'names', 'title');
					luaQuestRecord += prepareLuaWithFemaleVersion(czechQuest, 'objectives', 'objective');
					luaQuestRecord += prepareLuaWithFemaleVersion(czechQuest, 'descriptions', 'description');
					luaQuestRecord += prepareLuaWithFemaleVersion(czechQuest, 'progresses', 'progress');
					luaQuestRecord += prepareLuaWithFemaleVersion(czechQuest, 'completions', 'completion');
					luaQuestRecord += `}\n`;
					fs.appendFileSync(fileName, luaQuestRecord, 'utf8');
				}

				if (czechQuest.isQuestItem) {
					const page = czechQuest.id.split('_page')?.[1] ?? null;
					const variableId = `"${czechQuest.name}${page ? `__${page}` : ''}"`;
					let luaQuestRecord = '';
					luaQuestRecord += `addon.data.item[${variableId}] = {\n`;
					luaQuestRecord += '\ttitle = "' + normalizeTranslation(czechQuest.name) + '", \n';
					luaQuestRecord += '\ttext = "' + normalizeTranslation(czechQuest.descriptions?.[0]) + '", \n';
					luaQuestRecord += `}\n`;
					fs.appendFileSync(fileName, luaQuestRecord, 'utf8');
				}

				if (czechQuest.speeches) {
					let luaQuestRecord = '';
					const key = splitFirst(normalizeTranslation(czechQuest.speeches?.[2]) ?? '', ': ').trim();
					const npcNameKey = normalizeTranslation(czechQuest.name).trim();
					luaQuestRecord += `addon.data.speech["${npcNameKey}_${key}"] = {\n`;
					luaQuestRecord += '\ttext = "' + normalizeTranslation(czechQuest.speeches?.[0]).trim() + '", \n';
					luaQuestRecord += `}\n`;
					fs.appendFileSync(fileName, luaQuestRecord, 'utf8');
				}

				if (czechQuest.tactics) {
					let luaQuestRecord = '';
					const npcNameKey = normalizeTranslation(czechQuest.name).trim();
					luaQuestRecord += `addon.data.tactic["${npcNameKey}"] = {\n`;
					for (const [instance, roles] of Object.entries(czechQuest.tactics)) {
						luaQuestRecord += `\t${instance} = {\n`;
						luaQuestRecord += `\t\tsummary = "${roles.summary}",\n`;
						luaQuestRecord += `\t\ttank = {\n`;
						if (roles.tank) luaQuestRecord += generateRoleTactic(roles.tank);
						luaQuestRecord += `\t\t},\n`;
						luaQuestRecord += `\t\theal = {\n`;
						if (roles.healer) luaQuestRecord += generateRoleTactic(roles.healer);
						luaQuestRecord += `\t\t},\n`;
						luaQuestRecord += `\t\tdps = {\n`;
						if (roles.dps) luaQuestRecord += generateRoleTactic(roles.dps);
						luaQuestRecord += `\t\t},\n`;
						luaQuestRecord += `\t},\n`;
					}
					luaQuestRecord += `}\n`;
					fs.appendFileSync(fileName, luaQuestRecord, 'utf8');
				}
			}
		});
	} catch (e) {
		throw e;
	}
})();

type AddonData = Record<string, Quest>;

type Tactic = {
	summary?: string | null;
	tank?: (string | null)[];
	healer?: (string | null)[];
	dps?: (string | null)[];
};

type InstanceTactic = {
	[key: string]: Tactic;
};

type Quest = {
	id: string;
	name: string;
	names?: (string | null)[];
	descriptions?: (string | null)[];
	progresses?: (string | null)[];
	completions?: (string | null)[];
	objectives?: (string | null)[];
	speeches?: (string | null)[];
	tactics?: InstanceTactic;
	isQuest: boolean;
	isQuestItem: boolean;
};

type TolgeeKeysData = {
	keyId: number;
	keyName: string;
	keyNamespace: string;
	keyDescription: string;
	keyTags: TolgeeTag[];
	translations: {
		en: {
			id: number;
			text: string;
			state: 'REVIEWED' | 'TRANSLATED';
		};
		cs: {
			id: number;
			text: string | null;
			state: 'REVIEWED' | 'TRANSLATED';
		};
		csf: {
			id: number;
			text: string | null;
			state: 'REVIEWED' | 'TRANSLATED';
		};
	};
};

type TolgeeTag = {
	name: string;
};

type TolgeeTranslationsResponse = {
	_embedded: {
		keys: TolgeeKeysData[];
	};
	page: {
		size: number;
		totalElements: number;
		totalPages: number;
		number: number;
	};
};