////////////////////////////////////////////////////////////////////////////////////////
//Page 전역 변수
////////////////////////////////////////////////////////////////////////////////////////
var referenceLanguagePack = { language: null, languagePack: {} };
var selectedLanguageCode;
var isChanged = false;
var changedLang = new Set();
var langPacksColumnList = {};
var pairCounter = 0;
var isValidCheck = { modal: false, gc: false };
var dynamicPairContainer;

////////////////////////////////////////////////////////////////////////////////////////
//Document Ready
////////////////////////////////////////////////////////////////////////////////////////
function execDocReady() {
	var pluginGroups = [
		[
			"../reference/light-blue/lib/vendor/jquery.ui.widget.js",
			"../reference/lightblue4/docs/lib/widgster/widgster.js",
			"../reference/lightblue4/docs/lib/slimScroll/jquery.slimscroll.min.js",
			// JS tree
			"../reference/jquery-plugins/jstree-v.pre1.0/_lib/jquery.cookie.js",
			"../reference/jquery-plugins/jstree-v.pre1.0/_lib/jquery.hotkeys.js",
			"../reference/jquery-plugins/jstree-v.pre1.0/jquery.jstree.js",

			"../reference/light-blue/lib/jquery.iframe-transport.js",
			"../reference/light-blue/lib/jquery.fileupload.js",
			"../reference/light-blue/lib/jquery.fileupload-fp.js",
			"../reference/light-blue/lib/jquery.fileupload-ui.js"
		],

		[
			// excel component
			"../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/jsuites.js",
			"../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/index.js",
			"../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/jsuites.css",
			"../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/jspreadsheet.css",
			"../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/jspreadsheet.datatables.css",
			"../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/jspreadsheet.theme.css",
			"./js/common/jspreadsheet/spreadsheet.js"
		]
		// 추가적인 플러그인 그룹들을 이곳에 추가하면 됩니다.
	];

	loadPluginGroupsParallelAndSequential(pluginGroups)
		.then(function () {
			console.log("모든 플러그인 로드 완료");

			dynamicPairContainer = $("#languagePackForm_add_key fieldset");
			// 사이드 메뉴 색상 설정
			$(".widget").widgster();
			setSideMenu("sidebar_menu_config", "sidebar_menu_config_language");

			$("#language_pack_list").trigger("create.language_pack_list");

			btnClickEvent();
			// 전체 언어팩 로드
			getAllContents();
		})
		.catch(function (error) {
			console.error("플러그인 로드 중 오류 발생");
			console.log(error);
		});
}

/////////////////////////////////////////////////
// 엑셀 그리기
/////////////////////////////////////////////////
var SpreadsheetFunctions = (function () {
	let targetId = { v: "", jq: "" };
	let targetRect = { width: 0, height: 0 };
	let excelData; // 엑셀 데이터
	let excelColumns; // 엑셀 컬럼
	let customOptions; // 엑셀 커스텀 옵션들 :: 정의 안할 경우 default
	let isEditingCell = false;

	var setDefaultTargetRect = function () {
		let defaultWidth = $(getTargetId("jq")).width();
		let defaultHeight = $(getTargetId("jq")).height();
		setTargetRect(defaultWidth, defaultHeight);
	};
	var setTargetRect = function (width, height) {
		targetRect.width = width;
		targetRect.height = height;
	};

	var getTargetRect = function (type) {
		if (type === "width") {
			return targetRect.width;
		} else if (type === "height") {
			return targetRect.height;
		} else {
			return targetRect;
		}
	};

	var setTargetId = function (target) {
		targetId.v = target;
		targetId.jq = "#" + target;
	};

	var getTargetId = function (type) {
		if (type === "jq") {
			return targetId.jq;
		} else {
			return targetId.v;
		}
	};

	var setExcelData = function (data) {
		excelData = data;
	};
	var getExcelData = function () {
		return excelData;
	};

	var updateDataAtIndex = function (index, changedData) {
		if (excelData) {
			excelData[index] = changedData;
		} else {
			console.log("updateDataAtIndex :: excelData 가 없습니다.");
			return false;
		}
	};

	var getDataAtIndex = function (index) {
		if (excelData) {
			return excelData[index];
		} else {
			console.log("getDataAtIndex :: excelData 가 없습니다.");
			return false;
		}
	};

	var setColumns = function (columns) {
		excelColumns = columns;
	};
	var getColumns = function () {
		return excelColumns;
	};

	var setColumnWidth = function (width) {
		if (excelColumns) {
			excelColumns = excelColumns.map((column) => ({
				...column,
				width: width * column.wRatio - 1
			}));
		}
	};

	function setColumnWidthAsync(width) {
		return new Promise((resolve) => {
			if (excelColumns) {
				excelColumns = excelColumns.map((column) => ({
					...column,
					width: width * column.wRatio - 1
				}));
			}
			resolve(); // 컬럼 너비 설정이 완료된 후 resolve 호출
		});
	}

	var setOptions = function (options) {
		customOptions = options;
	};
	var getOptions = function () {
		return customOptions ? customOptions : null;
	};

	var resizeObserver = new ResizeObserver(function (entries) {
		if (isEditingCell) {
			// 수정중에는 resize 비활성화
			return;
		}
		for (let entry of entries) {
			setTargetRect(entry.contentRect.width, entry.contentRect.height);
			handleResize(entry.target.id, getTargetRect("width"), getTargetRect("height"));
		}
	});

	// 모달요소 크기 변화 관찰(Observer)
	function startObserver() {
		resizeObserver.observe($(getTargetId("jq"))[0]);
	}

	// Observer 멈추기
	function stopObserver() {
		console.log("Stopping ResizeObserver");
		resizeObserver.disconnect(); // 크기 변화를 더 이상 감지하지 않음
	}

	function handleResize(id, width, height) {
		if (id === getTargetId() && height !== 0) {
			if (excelData) {
				drawResizedExcel(getTargetId());
			} else {
				console.log("Spreadsheet.handleResize :: 엑셀 데이터 없음");
			}
		} else {
			console.log("Spreadsheet.handleResize :: id 불일치 또는 height 가 0 입니다.");
		}
	}

	function drawResizedExcel(target) {
		let $targetId = "#" + target;

		if ($($targetId).length > 0 && $($targetId)[0].jexcel) {
			$($targetId)[0].jexcel.destroy();
		}

		setColumnWidthAsync(getTargetRect("width") - 50).then(() => {
			$($targetId).spreadsheet(
				$.extend(
					{},
					{
						columns: getColumns(),
						data: getExcelData()
					},
					getOptions()
				)
			);

			let jexcel_content_height = getTargetRect("height") - 40 - 30 - 35 - 34;
			$($targetId + " .jexcel_content").css("max-height", jexcel_content_height);
			$($targetId + " .jexcel_content").css("width", "100%");
		});
	}

	function drawExcel(target) {
		let $targetId = "#" + target;

		if ($($targetId).length > 0 && $($targetId)[0].jexcel) {
			$($targetId)[0].jexcel.destroy();
		}

		$($targetId).spreadsheet(
			$.extend(
				{},
				{
					columns: getColumns(),
					data: getExcelData()
				},
				getOptions()
			)
		);

		let jexcel_content_height = getTargetRect("height") - 40 - 30 - 35 - 34;
		$($targetId + " .jexcel_content").css("max-height", jexcel_content_height);
		$($targetId + " .jexcel_content").css("width", "100%");
	}

	return {
		setTargetId,
		getTargetId,
		setTargetRect,
		getTargetRect,
		setDefaultTargetRect,
		setExcelData,
		getExcelData,
		updateDataAtIndex,
		getDataAtIndex,
		setColumns,
		getColumns,
		setColumnWidth,
		setOptions,
		getOptions,

		startObserver,
		stopObserver,
		drawExcel,
		drawResizedExcel
	};
})();

function csvExport() {
	$(".jexcel_toolbar_item.material-icons.fa.fa-save").click();
}

+(function ($) {
	"use strict";
	$(document).on("create.language_pack_list", function (event) {
		var $target = $(event.target);

		if ($target.jstree(true)) {
			$target.jstree("destroy").html("<p class='text-center'>조회된 데이터가 없습니다.</p>");
		}
		// 언어팩 파일 목록 조회
		$.get("/auth-sche/language-config/packs/files").done(function (response) {
			// jsTree 데이터 구조 생성
			var treeData = {
				data: {
					data: "A-RMS - Language Packs (전체)",
					state: "open",
					attr: { rel: "drive" },
					children: response.map((file) => ({
						data: file.fileName,
						attr: { rel: "default" }
					}))
				}
			};
			console.log("treeData => ", treeData);
			$target
				.on("select_node.jstree", function (e, data) {
					// 선택된 노드의 정보
					var selectedNode = data.inst.get_json()[0];
					var selectedNodeData = data.rslt.obj;
					var selectedNodeType = selectedNodeData.attr("rel");

					// 선택된 노드가 파일인 경우 (rel이 'default'인 경우)
					if (selectedNodeType === "default") {
						var fileName = data.inst.get_text(data.rslt.obj);
						const fileNameExceptExt = fileName.replace(".json", "");
						selectedLanguageCode = fileNameExceptExt;
						senderSetting(fileName);
						$("#addLanguageKey").removeClass("hidden");
						$("#languagePack_delete_modal #languagePackForm_delete input[name='languageCode']").val(fileNameExceptExt);
						getLanguagePack(fileNameExceptExt);
					} else if (selectedNodeType === "drive") {
						// 루트 선택
						senderSetting("언어팩 전체");
						$("#addLanguageKey").addClass("hidden");
						selectedLanguageCode = "all";
						getAllContents();
					}
				})
				.on("loaded.jstree", function (e, data) {
					$("#alog").append(data.func + "<br />");
					$("li:not([rel='drive']).jstree-open > a > .jstree-icon").css(
						"background-image",
						"url(../reference/jquery-plugins/jstree-v.pre1.0/themes/toolbar_open.png)"
					);
					$("li:not([rel='drive']).jstree-closed > a > .jstree-icon").css(
						"background-image",
						"url(../reference/jquery-plugins/jstree-v.pre1.0/themes/ic_explorer.png)"
					);
				})
				.jstree({
					plugins: ["themes", "json_data", "ui", "crrm", "dnd", "types"],
					themes: { theme: ["lightblue4"] },
					json_data: treeData,
					types: {
						types: {
							default: {
								valid_children: "none",
								icon: {
									image: "../reference/jquery-plugins/jstree-v.pre1.0/themes/attibutes.png"
								}
							},
							drive: {
								valid_children: ["default"],
								icon: {
									image: "../reference/jquery-plugins/jstree-v.pre1.0/themes/home.png"
								},
								start_drag: false,
								move_node: false,
								delete_node: false,
								remove: false
							}
						}
					}
				});
		});
	});
})(jQuery);

function getAllContents() {
	$.get("/auth-sche/language-config/packs/all-contents").done(function (response) {
		console.log(`getAllLanguagePacks :: response =>`, response);
		// 동적으로 columnList 생성
		var columnList = generateColumnListByAllContents(response);
		// 데이터 파싱
		var excelData = parseLanguageDataByAllContents(response);

		drawExcelByType("drive", "modal_excel", columnList, excelData);
	});
}

async function getLanguagePack(languageCode) {
	try {
		const response = await $.get("/auth-sche/language-config/packs/language/" + languageCode);
		console.log(`getLanguagePack :: ${languageCode} =>`, response);

		let columnList = null;
		let parsedExcelData = null;

		if (languageCode === "ko") {
			columnList = generateSingleLangColumnList();
			parsedExcelData = parseSingleLangData(response);
		} else {
			columnList = await generateSingleLangColumnListWithReferenceLangPack(languageCode);
			parsedExcelData = await parseSingleLangDataWithReferenceLang(response);
		}

		drawExcelByType("default", "modal_excel", columnList, parsedExcelData);
	} catch (error) {
		console.error("Error in getLanguagePack:", error);
	}
}

/////////////////////////////////
// 함수. 서버에서 기본 언어팩 가져오기
/////////////////////////////////
function getReferenceLanguagePack(languageCode) {
	return $.get("/auth-sche/language-config/packs/language/" + languageCode)
		.then(function (response) {
			if (response && response.language && response.languagePack) {
				setReferenceLanguage(response.language, response.languagePack);
			} else {
				console.error("Invalid response from getReferenceLanguagePack:", response);
			}
			return response;
		})
		.catch(function (error) {
			console.error("Error fetching language pack:", error);
		});
}

function generateSingleLangColumnList() {
	return [
		{ type: "text", title: "키 (key)", name: "key", wRatio: 0.5, readOnly: true },
		{ type: "text", title: "값(value)", name: "value", wRatio: 0.5 }
	];
}

async function generateSingleLangColumnListWithReferenceLangPack(languageCode) {
	console.log("generateSingleLangColumnListWithReferenceLangPack :: languageCode =>", languageCode);
	const languageDisplayName = await getLanguageDisplayName(languageCode);
	const formattedName = languageCode.toUpperCase();
	console.log("generateSingleLangColumnListWithReferenceLangPack :: languageDisplayName =>", languageDisplayName);
	return [
		{ type: "text", title: "KO (한국어)", name: "ko", wRatio: 0.3, readOnly: true },
		{ type: "text", title: `${formattedName} (${languageDisplayName})`, name: "value", wRatio: 0.3 },
		{ type: "text", title: "키 (key)", name: "key", wRatio: 0.4, readOnly: true }
	];
}

function getLanguageDisplayName(languageCode) {
	const displayNameMap = {
		en: "영어",
		ja: "일본어",
		ko: "한국어",
		zh: "중국어" // Add more as needed
	};
	return displayNameMap[languageCode] || languageCode;
}

function extractLanguageCode(input) {
	const match = input.match(/^[^(]+/); // 괄호 '(' 앞의 모든 내용 추출
	return match ? match[0].trim().toLowerCase() : null; // 양쪽 공백 제거 후 소문자로 변환
}

function generateColumnListByAllContents(response) {
	const columnList = [];
	let colIdx = 0;
	columnList.push({ readOnly: true, type: "text", title: "KO (한국어)", name: "ko" });
	langPacksColumnList["ko"] = colIdx;

	const languageNames = response.map((item) => item.language);
	languageNames.forEach((language) => {
		if (language !== "ko") {
			langPacksColumnList[`${language}`] = ++colIdx;
			const formattedName = language.toUpperCase();
			columnList.push({
				type: "text",
				title: `${formattedName} (${getLanguageDisplayName(language)})`,
				name: language
				// readOnly: true
			});
		}
	});

	// Calculate wRatio for 'text' type columns
	const textColumnCount = columnList.filter((col) => col.type === "text").length;
	if (textColumnCount > 0) {
		const wRatioValue = Math.round((1 / textColumnCount) * 100) / 100; // Round to two decimal places
		columnList.forEach((col) => {
			if (col.type === "text") {
				col.wRatio = wRatioValue;
			}
		});
	}

	// Add the hidden key column
	columnList.push({ type: "hidden", title: "키 (key)", name: "key" });
	langPacksColumnList["key"] = ++colIdx;
	return columnList;
}

function parseLanguageDataByAllContents(response) {
	const languagePacks = {};
	const result = []; // 최종 결과 배열

	// 언어별 데이터 추출
	response.forEach((item) => {
		const { language, languagePack } = item;
		languagePacks[language] = languagePack;
	});

	const referenceLanguage = "ko"; // 기준 언어 (필요시 다른 언어로 변경 가능)
	const referenceData = languagePacks[referenceLanguage];

	setReferenceLanguage(referenceLanguage, referenceData);

	if (!referenceData) {
		throw new Error(`기준 언어(${referenceLanguage}) 데이터가 존재하지 않습니다.`);
	}

	Object.keys(referenceLanguagePack.languagePack).forEach((key) => {
		const row = { key }; // 현재 키를 기반으로 결과 생성
		// 각 언어에 해당 키 값을 추가
		Object.keys(languagePacks).forEach((language) => {
			row[language] = languagePacks[language][key] || ""; // 언어 데이터가 없으면 빈 문자열
		});

		result.push(row);
	});

	return result;
}

function parseSingleLangData(responseByOneLang) {
	const parsedData = [];
	const languagePack = responseByOneLang.languagePack;

	const sortedKeys = Object.keys(languagePack).sort();
	for (const key of sortedKeys) {
		parsedData.push({
			key: key,
			value: languagePack[key]
		});
	}

	return parsedData;
}

async function parseSingleLangDataWithReferenceLang(responseByOneLang) {
	const parsedData = [];
	const languagePack = responseByOneLang.languagePack;

	if (!referenceLanguagePack || referenceLanguagePack.language === null) {
		await getReferenceLanguagePack("ko");
	}

	const $referenceLanguagePack = referenceLanguagePack.languagePack;

	if (!$referenceLanguagePack) {
		console.error("Reference language pack is still not initialized.");
		return [];
	}

	for (const key in $referenceLanguagePack) {
		if (Object.hasOwnProperty.call($referenceLanguagePack, key)) {
			parsedData.push({
				key: key,
				ko: $referenceLanguagePack[key] || "",
				value: languagePack[key] || ""
			});
		}
	}

	return parsedData;
}

function drawExcelByType(type, target, columnList, excelData) {
	if (!columnList) {
		return;
	}

	var customOption = {
		toolbar: [], // 툴바 사용하지 않음.
		search: true,
		contextMenu: [],
		pagination: 50,
		allowInsertRow: false,
		allowInsertColumn: false,
		// passive 이벤트 리스너 설정으로 성능 최적화
		onload: function (element) {},
		updateTable: function (instance, cell, col, row, val, id) {
			cell.style.textAlign = "left";
			cell.style.whiteSpace = "normal";
		},
		onchange: function (instance, cell, col, row, val, id) {
			var changedRowData = SpreadsheetFunctions.getDataAtIndex(row);
			isChanged = true;
			if (type === "default") {
				changedRowData.value = val;
				SpreadsheetFunctions.updateDataAtIndex(row, changedRowData);
			} else {
				let colName = $("#modal_excel")[0].jexcel.getHeader(col);
				let langCode = extractLanguageCode(colName);
				changedLang.add(langCode);
				changedRowData[langCode] = val;
				SpreadsheetFunctions.updateDataAtIndex(row, changedRowData);
			}
		},
		oneditionstart: function () {
			SpreadsheetFunctions.isEditingCell = true;
			SpreadsheetFunctions.stopObserver();
		},
		oneditionend: function () {
			SpreadsheetFunctions.isEditingCell = false;
			SpreadsheetFunctions.startObserver();
		}
	};

	SpreadsheetFunctions.setTargetId(target);
	SpreadsheetFunctions.setDefaultTargetRect();

	SpreadsheetFunctions.setColumns(columnList);
	SpreadsheetFunctions.setColumnWidth(SpreadsheetFunctions.getTargetRect("width"));
	SpreadsheetFunctions.setOptions(customOption);
	SpreadsheetFunctions.startObserver();

	SpreadsheetFunctions.setExcelData(excelData);
	SpreadsheetFunctions.drawExcel(SpreadsheetFunctions.getTargetId());
}

////////////////////////////////////////
// referenceLanguagePack 업데이트 함수
////////////////////////////////////////
function setReferenceLanguage(language, languagePack) {
	if (!language || !languagePack) {
		console.error("Invalid language or languagePack:", language, languagePack);
		return;
	}
	// languagePack의 키를 알파벳 순으로 정렬
	const sortedLanguagePack = Object.keys(languagePack)
		.sort() // 키를 알파벳 순으로 정렬
		.reduce((acc, key) => {
			acc[key] = languagePack[key]; // 정렬된 순서로 새로운 객체 생성
			return acc;
		}, {});

	// referenceLanguagePack 업데이트
	referenceLanguagePack.language = language;
	referenceLanguagePack.languagePack = sortedLanguagePack;

	console.log("referenceLanguagePack is updated");
}

function btnClickEvent() {
	$("#updateLanguagePack").on("click", function () {
		if (!isChanged) {
			jError("수정된 값이 없습니다.");
			return;
		}

		let arrayData = $("#modal_excel")[0].jexcel.getData();
		if (!selectedLanguageCode || selectedLanguageCode === "all") {
			console.log("selectedLanguageCode => ", selectedLanguageCode);
			let changedLangArr = [...changedLang];
			updateLanguagePacks(changedLangArr);
		} else {
			updateSingleLanguagePack(selectedLanguageCode, convertSheetDataToAnArrayOfKeyValue(arrayData));
		}
	});

	$("#checkKeyExist").on("click", async function () {
		// 모달 UI 초기화
		$("#languagePackForm_add_key fieldset .input-group input").removeClass("is-invalid");
		isValidCheck.modal = false;
		isValidCheck.gc = false;

		let formDataArray = $("#languagePackForm_add_key").serializeArray();

		let elementIdListOfDuplicatedKey = findDuplicateKeysOnModal(formDataArray, "additionalKey");
		let keys, swappedFormArray;
		if (elementIdListOfDuplicatedKey.length === 0) {
			isValidCheck.modal = true;
			keys = getAdditionalKeyValues(formDataArray, "additionalKey");
			swappedFormArray = valueElementId(formDataArray);
		} else {
			elementIdListOfDuplicatedKey.forEach((element) => {
				$(`#${element}`).addClass("is-invalid");
			});
		}

		try {
			const isDuplicatedOnGC = await checkLanguageKeyExistsOnRepo(selectedLanguageCode, keys);
			if (isDuplicatedOnGC && isDuplicatedOnGC.length === 0) {
				isValidCheck.gc = true;
				$("#uniqueCheckComplete").removeClass("hidden");
			} else {
				console.log("Duplicated keys =>", isDuplicatedOnGC);
				isDuplicatedOnGC.forEach((key) => {
					let duplicatedFormId = swappedFormArray[key];
					if (duplicatedFormId) {
						$(`#${duplicatedFormId}`).addClass("is-invalid");
					}
				});
			}
		} catch (error) {
			console.error("Error during global config check:", error);
		}
	});

	$("#add_languagePack_btn").on("click", function () {
		console.log("languageConfig :: add_languagePack_btn is clicked");

		let formDataArray = $("#languagePack_add_modal #languagePackForm_add").serializeArray();

		if (formDataArray.length === 0) {
			console.log("추가할 Language Code 가 없습니다.");
		}
		let langCodeForAddition = formDataArray[0].value;
		console.log("langCodeForAddition => ", langCodeForAddition);
		addSingleLanguagePack(langCodeForAddition, [{}]);
	});

	$("#delete_languagePack_btn").on("click", function () {
		if (selectedLanguageCode === "all") {
			jError("전체 언어팩 일괄 삭제는 지원하지 않습니다. 관리자에 문의하세요.");
		}
		console.log("languageConfig :: delete_languagePack_btn is clicked");

		let formDataArray = $("#languagePack_delete_modal #languagePackForm_delete").serializeArray();

		let langCodeForDelete = formDataArray[0].value;

		deleteSingleLanguagePack(langCodeForDelete);
	});

	$("#languagePack_add_modal").on("show.bs.modal", function () {
		$("#languagePack_add_modal #languagePackForm_add input[name='languageCode']").val("");
	});

	$("#refreshLanguagePacks").on("click", function () {
		refreshLanguagePacks();
	});

	$("#languagePack_add_key_modal")
		.on("hidden.bs.modal", function () {
			dynamicPairContainer.empty(); // 동적 필드셋 초기화
			pairCounter = 0; // 카운터 초기화
		})
		.on("show.bs.modal", function () {
			console.log("add New Empty Pair when modal is shown");
			$("#addNewEmptyPair").trigger("click"); // 1개 추가
		});

	dynamicPairContainer.on("click", ".removePair", function () {
		const pairId = $(this).data("pair-id");
		$(`#pair-${pairId}`).remove();
		console.log(`Removed pair-${pairId}`);
	});

	$("#addNewEmptyPair").on("click", function () {
		addNewEmptyPairHtmlElement();
		$("#uniqueCheckComplete").addClass("hidden");
		isValidCheck.modal = false;
		isValidCheck.gc = false;
	});

	$("#add_key_pair_btn").on("click", function (event) {
		if (!isValidCheck.gc || !isValidCheck.modal) {
			jError("키(Key) 중복체크를 해주세요.");
			event.preventDefault();
			event.stopPropagation();
			return;
		}

		const addedPairs = transformKeyValuePairs($("#languagePackForm_add_key").serializeArray());
		if (addedPairs.length === 0) {
			// 추가할 Key-Value가 없는 경우
			jError("저장할 Key 값이 없습니다.");
			// 이벤트 전파 및 기본 동작 멈춤
			event.preventDefault();
			event.stopPropagation();
			return;
		}
		let excelData = convertSheetDataToAnArrayOfKeyValue($("#modal_excel")[0].jexcel.getData());
		let mergedData = excelData.concat(addedPairs);
		if (selectedLanguageCode === "ko") {
			// 기준언어는 언어팩 업데이트.
			updateSingleLanguagePack(selectedLanguageCode, mergedData);
			refreshPacksAndGetSingleLanguagePack(selectedLanguageCode);
		} else {
			//1st update
			updateSingleLanguagePack(selectedLanguageCode, mergedData);
			//2nd update
			const referencePackArray = objectToKeyValueArray(referenceLanguagePack.languagePack);
			const emptyValues = addedPairs.map((pair) => {
				const key = Object.keys(pair)[0];
				return { [key]: "" };
			});
			updateSingleLanguagePack("ko", referencePackArray.concat(emptyValues));
			refreshPacksAndGetSingleLanguagePack(selectedLanguageCode);
		}
	});
}

//////////////////////////////////////////////
// converting format sheetData(Array) to another array of { key : value }
//////////////////////////////////////////////
function convertSheetDataToAnArrayOfKeyValue(arrayData) {
	// 변환 로직
	const transformedData = arrayData.map((item) => {
		if (Array.isArray(item) && item.length >= 2) {
			if (item.length === 3) {
				const key = item[2];
				const value = item[1];
				return { [key]: value };
			} else {
				return { [item[0]]: item[1] };
			}
		} else {
			throw new Error("Invalid item format: Expected array with at least 2 elements");
		}
	});

	return transformedData;
}

function updateLanguagePacks(changedLangArr) {
	if (!changedLangArr || changedLangArr.length === 0) {
		jError("업데이트할 내용이 없습니다.");
	}
	console.log("updateLanguagePacks :: changedLangArr => ", changedLangArr);

	let idxOfKey = langPacksColumnList["key"];
	let keyArr = $("#modal_excel")[0].jexcel.getColumnData(idxOfKey);
	changedLangArr.forEach((langCode) => {
		let idxOfLang = langPacksColumnList[langCode];
		let langDataArr = $("#modal_excel")[0].jexcel.getColumnData(idxOfLang);
		let mergedLangPack = keyArr.map((key, index) => ({ [key]: langDataArr[index] }));
		$.ajax({
			url: "/auth-sche/language-config/packs/language/" + langCode,
			type: "PUT",
			data: JSON.stringify(mergedLangPack),
			contentType: "application/json; charset=utf-8",
			async: false, // 동기 처리
			success: function (response) {
				console.log(`${langCode}.json is updated`);
			},
			error: function (error) {
				console.error("Error updating language pack:", error);
			},
			complete: function () {
				jSuccess(`${langCode}.json 업데이트 완료`);
			}
		});
	});
	isChanged = false;
	changedLang.clear();
}

// update LanguagePack
function updateSingleLanguagePack(languageCode, languagePack) {
	console.log(`updateSingleLanguagePack :: languageCode => ${languageCode}, languagePack => `, languagePack);
	$.ajax({
		url: "/auth-sche/language-config/packs/language/" + languageCode,
		type: "PUT",
		data: JSON.stringify(languagePack),
		contentType: "application/json; charset=utf-8",
		async: false,
		success: function (response) {
			console.log("updateSingleLanguagePack :: response =>", response);
			isChanged = false;
			isValidCheck.modal = false;
			isValidCheck.gc = false;
			jSuccess(`${languageCode}.json is updated`);
		},
		error: function (error) {
			console.error("Error updating language pack:", error);
		}
	});
}
// create LanguagePack (empty contents)
function addSingleLanguagePack(languageCode, languagePack) {
	console.log(`addSingleLanguagePack :: languageCode => ${languageCode}, languagePack => `, languagePack);
	$.ajax({
		url: "/auth-sche/language-config/packs/language/" + languageCode,
		type: "PUT",
		data: JSON.stringify(languagePack),
		contentType: "application/json; charset=utf-8",
		success: function (response) {
			console.log("updateSingleLanguagePack :: response =>", response);
			$("#language_pack_list").trigger("create.language_pack_list");
		},
		error: function (error) {
			console.error("Error updating language pack:", error);
		}
	});
}

function deleteSingleLanguagePack(languageCode) {
	console.log(`deleteSingleLanguagePack :: languageCode => ${languageCode}`);
	$.ajax({
		url: "/auth-sche/language-config/packs/language/" + languageCode,
		type: "DELETE",
		contentType: "application/json; charset=utf-8",
		success: function (response) {
			console.log("deleteSingleLanguagePack :: response =>", response);
			// refresh jsTree
			$("#language_pack_list").trigger("create.language_pack_list");
		},
		error: function (error) {
			console.error("Error deleting language pack:", error);
		}
	});
}

function refreshLanguagePacks() {
	$.get("/auth-sche/language-config/packs/all-contents/refresh").done(function (response) {
		console.log(`refreshLanguagePacks :: response =>`, response);
		// refresh jsTree
		$("#language_pack_list").trigger("create.language_pack_list");
		var columnList = generateColumnListByAllContents(response);
		var excelData = parseLanguageDataByAllContents(response);
		drawExcelByType("drive", "modal_excel", columnList, excelData);
	});
}

function refreshPacksAndGetSingleLanguagePack(languageCode) {
	$.get("/auth-sche/language-config/packs/all-contents/refresh").done(function (response) {
		getLanguagePack(languageCode);
	});
}

/////////////////////////////////////////////////
// 항목추가 모달 :: 키(key)-값(value) 빈 요소 추가
/////////////////////////////////////////////////
function addNewEmptyPairHtmlElement() {
	pairCounter++;
	const newPairHtml = `
		<div class="control-group clearfix" id="pair-${pairCounter}">
      <label for="additionalKey-${pairCounter}" class="control-label" style="width:120px;"><span class="required">*</span>키(Key)&nbsp;</label>
      <div class="controls form-group">          		
        <div class="input-group">
        	<span class="input-group-addon"><i class="fa fa-gift"></i></span>
					<input
							type="text"
							id = "additionalKey-${pairCounter}"
							name="additionalKey-${pairCounter}"
							class="form-control parsley-validated font13 darkBack ajax-data" style="width: 80%">         
					<button
						type="button"
						class="btn btn-danger btn-sm removePair"
						style="height: 30px; margin-left: 5px"
						data-pair-id="${pairCounter}">항목 삭제</button>                                                         
        </div>          
      </div>
      <label for="additionalValue-${pairCounter}" class="control-label" style="width:120px;">&nbsp;값(Value)&nbsp;</label>
      <div class="controls form-group">                  
        <div class="input-group">
        	<span class="input-group-addon"><i class="fa fa-gift"></i></span>
					<input
							type="text"
							id = "additionalValue-${pairCounter}"
							name="additionalValue-${pairCounter}"
							class="form-control parsley-validated font13 darkBack ajax-data" style="width: 80%">                                                                 
        </div>          
      </div>            
  </div>`;
	dynamicPairContainer.append(newPairHtml);
}

function senderSetting(textContents) {
	$("#sender-language").css("color", "#a4c6ff").text(textContents);
	$(".chat-message-body").css("border-left", "2px solid #e5603b");
	$(".chat-message-body .arrow").css("border-right", "5px solid #e5603b");
	$(".sender-contents").text(textContents).css("color", "#a4c6ff");
}
/////////////////////////
// 언어팩 키(key) 중복 체크
/////////////////////////
async function checkLanguageKeyExistsOnRepo(languageCode, keys) {
	return new Promise((resolve, reject) => {
		$.ajax({
			url: `/auth-sche/language-config/packs/language/${languageCode}/keys/exists`,
			type: "GET",
			traditional: true,
			data: { keys: keys },
			success: function (response) {
				console.log("checkLanguageKeyExists :: response =>", response);
				if (response && response.length === 0) {
					console.log("There is no duplicated key");
				} else {
					console.log("Duplicated keys => ", response);
				}
				resolve(response);
			},
			error: function (error) {
				console.error("Error checking language key exists:", error);
				reject(error);
			}
		});
	});
}

function valueElementId(serializedArray) {
	if (serializedArray.length === 0) return {};
	return serializedArray
		.filter((item) => item.name.startsWith("additionalKey")) // "additionalKey-*" 필터링
		.reduce((acc, item) => {
			acc[item.value] = item.name;
			return acc;
		}, {});
}

function getAdditionalKeyValues(data, prefix) {
	return data
		.filter((item) => item.name.startsWith(prefix)) // "additionalKey-"로 시작하는 항목 필터링
		.map((item) => item.value); // value 값만 추출
}
//////////////////////////////
// 모달에서 key 중복 여부 확인
//////////////////////////////
function findDuplicateKeysOnModal(data, prefix) {
	const valueToNamesMap = new Map();
	const duplicateNames = new Set();

	data
		.filter((item) => item.name.startsWith(prefix))
		.forEach((item) => {
			if (valueToNamesMap.has(item.value)) {
				valueToNamesMap.get(item.value).push(item.name);

				valueToNamesMap.get(item.value).forEach((name) => {
					duplicateNames.add(name);
				});
			} else {
				valueToNamesMap.set(item.value, [item.name]);
			}
		});
	return Array.from(duplicateNames);
}

function transformKeyValuePairs(data) {
	const keyPrefix = "additionalKey";
	const valuePrefix = "additionalValue";
	const result = [];

	// Key와 Value를 매핑
	const keyMap = new Map();

	data.forEach((item) => {
		if (item.name.startsWith(keyPrefix)) {
			const index = item.name.split("-")[1]; // Key의 번호를 가져옴
			if (!keyMap.has(index)) {
				keyMap.set(index, { key: item.value, value: "" }); // Key 저장, 기본 value를 ""로 설정
			} else {
				keyMap.get(index).key = item.value; // 기존 객체에 Key 설정
			}
		} else if (item.name.startsWith(valuePrefix)) {
			const index = item.name.split("-")[1]; // Value의 번호를 가져옴
			if (!keyMap.has(index)) {
				keyMap.set(index, { key: "", value: item.value }); // 기본 key를 ""로 설정
			} else {
				keyMap.get(index).value = item.value; // 기존 객체에 Value 설정
			}
		}
	});

	// Key-Value 쌍을 배열에 추가
	keyMap.forEach((pair) => {
		// value가 항상 빈값이라도 존재하도록 보장
		if (pair.key) {
			result.push({ [pair.key]: pair.value }); // 빈 문자열도 포함해 추가
		}
	});

	return result;
}

function objectToKeyValueArray(obj) {
	return Object.entries(obj).map(([key, value]) => ({ [key]: value }));
}
