require("dotenv").config();
const axios = require("axios");

module.exports = {
	getDepartments,
	getOptionDepartments,
    importAll,
};

async function getDepartments(params) {
	try {
		// get
		const departments = await axios.get(`${params.api_url}api/resource/Department`, {
			headers: {
				Authorization: `token ${params.api_key}:${params.api_secret}`,
				"Content-Type": "application/x-www-form-urlencoded, multipart/form-data",
				Accept: "application/json",
			},
			params: {
				fields: '["*"]',
				limit_start: "0",
				limit_page_length: "0",
				order_by: "modified DESC",
				debug: "true",
				// filters: '[["disabled","=",0]]',
			},
		});

		return {
			departments: departments.data.data || [],
			success: true,
			message: "Loaded successfully!",
		};
	} catch (error) {
		const errorMessage = error?.message || "Failed to load, please try again!";
		return {
			success: false,
			message: errorMessage,
		};
	}
}

async function getOptionDepartments(params) {
	try {
		// get
		const options = await axios.get(`${params.api_url}api/resource/Department`, {
			headers: {
				Authorization: `token ${params.api_key}:${params.api_secret}`,
				"Content-Type": "application/x-www-form-urlencoded, multipart/form-data",
				Accept: "application/json",
			},
			params: {
				fields: '["*"]',
				limit_start: "0",
				limit_page_length: "0",
				order_by: "modified DESC",
				debug: "true",
				filters: '[["disabled","=",0]]',
			},
		});

		return {
			options: options.data.data || [],
			success: true,
			message: "Loaded successfully!",
		};
	} catch (error) {
		const errorMessage = error?.message || "Failed to load, please try again!";
		return {
			success: false,
			message: errorMessage,
		};
	}
}

// Fungsi importAll disesuaikan untuk Department.
// Ditambahkan: Cek company berdasarkan name untuk mengisi company_id.
// Ditambahkan: Replace owner dan modified_by dengan angka 4.
// Menggunakan Sequelize untuk transaksi, validasi existing, dan insert.
// Bangun hirarki berdasarkan parent_department, identifikasi parents (is_group: true), sort berdasarkan name,
// dan insert semua parents dulu dalam urutan hirarki sebelum children.
// Ditambahkan: Jika parent tidak ditemukan untuk child, treat sebagai root dengan warning (bukan error).
// Ditambahkan: Jika department sudah ada berdasarkan name, cek perubahan field lain dan update jika perlu.

async function importAll(params) {
	const transaction = await dbSAPPS.sequelize.transaction();
	try {
		// Validasi input: pastikan params adalah array dan tidak kosong
		if (!Array.isArray(params) || params.length === 0) {
			throw new Error("Invalid input: params must be a non-empty array of department objects.");
		}

		// Validasi struktur setiap department, isi company_id, dan replace owner/modified_by
		for (let i = 0; i < params.length; i++) {
			const dep = params[i];
			if (!dep.name || !dep.department_name) {
				throw new Error(`Invalid department data at index ${i}: missing required fields (name, department_name).`);
			}

			// Cek company berdasarkan name jika ada
			if (dep.company) {
				const company = await dbSAPPS.Company.findOne({
					where: { name: dep.company },
				});
				if (!company) {
					throw new Error(`Company '${dep.company}' not found for department '${dep.name}'.`);
				}
				dep.company_id = company.id; // Isi company_id dengan ID dari company
			} else {
				dep.company_id = null; // Jika tidak ada company, set null
			}

			// Replace owner dan modified_by dengan angka 4
			dep.owner = 4;
			dep.modified_by = 4;
		}

		// Bangun hirarki: Map name -> department object
		const departmentMap = new Map();
		const parents = [];
		const children = [];

		for (const dep of params) {
			departmentMap.set(dep.name, dep);
			if (dep.is_group === true || dep.is_group === 1) {
				parents.push(dep);
			} else {
				children.push(dep);
			}
		}

		// Sort parents berdasarkan name ascending untuk hirarki (root dulu)
		parents.sort((a, b) => a.name.localeCompare(b.name));

		// Map untuk menyimpan name -> ID
		const departmentIdMap = new Map();
		const insertedIds = [];
		const updatedIds = [];

		// Fungsi helper untuk cek dan update jika ada perubahan
		const checkAndUpdate = async (dep, existing) => {
			// Bandingkan field-field utama (exclude id, created_at, dll.)
			const fieldsToCheck = [
				"department_name",
				"parent_department",
				"company",
				"is_group",
				"disabled",
				"payroll_cost_center",
				"leave_block_list",
				"lft",
				"rgt",
				"old_parent",
				"_user_tags",
				"_comments",
				"_assign",
				"_liked_by",
				"company_id",
				"owner",
				"modified_by",
			];
			let hasChanges = false;
			const updateData = {};

			for (const field of fieldsToCheck) {
				if (dep[field] !== existing[field]) {
					hasChanges = true;
					updateData[field] = dep[field];
				}
			}

			if (hasChanges) {
				await dbSAPPS.BudgetDepartment.update(updateData, {
					where: { id: existing.id },
					transaction,
				});
				console.log(`Updated department '${dep.name}' with changes.`);
				updatedIds.push(existing.id);
			}
			return existing.id;
		};

		// 1. Insert atau update semua parents dalam urutan hirarki
		for (const parent of parents) {
			// Tentukan parent_department berdasarkan parent_department jika belum ada
			let parentDepartmentName = parent.parent_department;
			if (!parentDepartmentName || parentDepartmentName === "") {
				parent.parent_department = null; // Root parent
			} else if (departmentMap.has(parentDepartmentName)) {
				// Jika ada parent_department, pastikan parent-nya sudah ada di map
				const parentId = departmentIdMap.get(parentDepartmentName);
				if (!parentId) {
					throw new Error(`Parent department '${parentDepartmentName}' not found for parent '${parent.name}'. Ensure hierarchy is correct.`);
				}
				parent.parent_department = parentId; // Update dengan ID
			} else if (!departmentMap.has(parentDepartmentName)) {
				// Jika parent_department adalah string tapi tidak ada di data, anggap sebagai root atau skip
				console.warn(`Parent department '${parentDepartmentName}' for '${parent.name}' not in data, treating as root.`);
				parent.parent_department = null;
			} else {
				parent.parent_department = null; // Root parent
			}

			// Cek existing berdasarkan name
			const existing = await dbSAPPS.BudgetDepartment.findOne({
				where: { name: parent.name },
				transaction,
			});
			if (existing) {
				// Cek dan update jika ada perubahan
				const id = await checkAndUpdate(parent, existing);
				departmentIdMap.set(parent.name, id);
			} else {
				// Save parent baru
				const department = await dbSAPPS.BudgetDepartment.create(parent, { transaction });
				departmentIdMap.set(parent.name, department.id);
				insertedIds.push(department.id);
			}
		}

		// 2. Insert atau update children dengan parent_department diisi ID berdasarkan parent_department
		for (const child of children) {
			// Cari parent_department berdasarkan parent_department jika belum ada
			let parentDepartmentName = child.parent_department;
			if (!parentDepartmentName || parentDepartmentName === "") {
				child.parent_department = null; // Root child
			} else {
				// Cari ID parent dari map berdasarkan name
				const parentId = departmentIdMap.get(parentDepartmentName);
				if (!parentId) {
					// Jika parent tidak ditemukan, treat sebagai root dengan warning
					console.warn(`Parent department '${parentDepartmentName}' not found for child '${child.name}', treating as root.`);
					child.parent_department = null;
				} else {
					child.parent_department = parentId;
				}
			}

			// Cek existing berdasarkan name
			const existing = await dbSAPPS.BudgetDepartment.findOne({
				where: { name: child.name },
				transaction,
			});
			if (existing) {
				// Cek dan update jika ada perubahan
				await checkAndUpdate(child, existing);
			} else {
				// Save child baru
				const department = await dbSAPPS.BudgetDepartment.create(child, { transaction });
				insertedIds.push(department.id);
			}
		}

		await transaction.commit();
		return {
			insertedIds,
			updatedIds,
			success: true,
			message: `Successfully processed ${params.length} departments! Inserted: ${insertedIds.length}, Updated: ${updatedIds.length}`,
		};
	} catch (error) {
		await transaction.rollback();
		const errorMessage = error?.message || "Failed to import departments, please try again!";
		console.error("Import error:", error); // Log untuk debugging
		return {
			success: false,
			message: errorMessage,
		};
	}
}

// Contoh penggunaan:
// const departmentsData = [/* array of department objects dari sample data Anda */];
// importAll(departmentsData).then(result => console.log(result));
