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

module.exports = {
	getAccounts,
	getOptionAccounts,
	importAll,
};

async function getAccounts(params) {
	try {
		// get
		const accounts = await axios.get(`${params.api_url}api/resource/Account`, {
			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 {
			accounts: accounts.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 getOptionAccounts(params) {
	try {
		// get
		const options = await axios.get(`${params.api_url}api/resource/Account`, {
			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 dengan struktur kode contoh Anda.
// 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 account_number, identifikasi parents (is_group: true), sort berdasarkan account_number sampai buat seperti hirarki dari situ anda bisa mendahulukan semua parent terinsert dengan baik baru child nya di insert.
// Ditambahkan: Handle account yang tidak memiliki account_number (skip dari sorting/mapping, gunakan parent_account langsung jika ada).
// Ditambahkan: Handle root parent (jika parentAccountNumber sama dengan account_number sendiri, set parent_account = null).
// Ditambahkan: Jika parent tidak ditemukan untuk child, treat sebagai root dengan warning (bukan error).

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 account objects.");
		}

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

			// Cek company berdasarkan name
			const company = await dbSAPPS.Company.findOne({
				where: { name: acc.company },
			});
			if (!company) {
				throw new Error(`Company '${acc.company}' not found for account '${acc.name}'.`);
			}
			acc.company_id = company.id; // Isi company_id dengan ID dari company

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

		// Fungsi untuk menentukan parent berdasarkan account_number
		// Asumsi: Parent adalah account dengan account_number yang lebih pendek atau prefix dari child
		// Contoh: "1000.000" adalah parent dari "1100.000", "1110.000", dll.
		const getParentAccountNumber = (accountNumber) => {
			if (!accountNumber) return null;
			const parts = accountNumber.split(".");
			if (parts.length > 1) {
				parts.pop(); // Hapus bagian terakhir untuk dapat parent
				return parts.join(".") + ".000"; // Asumsi format .000 untuk parent
			}
			return null; // Root parent
		};

		// Bangun hirarki: Map account_number -> account object (hanya untuk yang punya account_number)
		const accountMap = new Map();
		const parents = [];
		const children = [];

		for (const acc of params) {
			if (acc.account_number) {
				accountMap.set(acc.account_number, acc);
			}
			if (acc.is_group === true || acc.is_group === 1) {
				parents.push(acc);
			} else {
				children.push(acc);
			}
		}

		// Sort parents berdasarkan account_number ascending untuk hirarki (root dulu)
		// Hanya sort yang punya account_number
		parents.sort((a, b) => {
			const aNum = a.account_number || "";
			const bNum = b.account_number || "";
			return aNum.localeCompare(bNum);
		});

		// Map untuk menyimpan account_number -> ID (hanya untuk yang punya account_number)
		const accountIdMap = new Map();
		const insertedIds = [];

		// 1. Insert semua parents dalam urutan hirarki
		for (const parent of parents) {
			// Tentukan parent_account berdasarkan account_number jika belum ada dan account_number ada
			let parentAccountNumber = parent.parent_account;
			if (!parentAccountNumber && parent.account_number) {
				parentAccountNumber = getParentAccountNumber(parent.account_number);
			}

			// Jika parentAccountNumber sama dengan account_number sendiri, ini adalah root parent
			if (parentAccountNumber === parent.account_number) {
				parent.parent_account = null; // Root parent
			} else if (parentAccountNumber && accountMap.has(parentAccountNumber)) {
				// Jika ada parent_account, pastikan parent-nya sudah ada di map
				const parentId = accountIdMap.get(parentAccountNumber);
				if (!parentId) {
					throw new Error(`Parent account '${parentAccountNumber}' not found for parent '${parent.name}'. Ensure hierarchy is correct.`);
				}
				parent.parent_account = parentId; // Update dengan ID
			} else if (parentAccountNumber && !accountMap.has(parentAccountNumber)) {
				// Jika parent_account adalah string tapi tidak ada di data, anggap sebagai root atau skip
				console.warn(`Parent account '${parentAccountNumber}' for '${parent.name}' not in data, treating as root.`);
				parent.parent_account = null;
			} else {
				parent.parent_account = null; // Root parent
			}

			// Validate existing
			const existing = await dbSAPPS.Account.findOne({
				where: {
					name: parent.name,
					account_name: parent.account_name,
					account_number: parent.account_number,
					parent_account: parent.parent_account,
					company_id: parent.company_id,
				},
				transaction,
			});
			if (existing) {
				console.warn(`Parent account '${parent.name}' already exists, skipping.`);
				if (parent.account_number) {
					accountIdMap.set(parent.account_number, existing.id); // Gunakan ID existing
				}
				continue;
			}

			// Save parent
			const account = await dbSAPPS.Account.create(parent, { transaction });
			if (parent.account_number) {
				accountIdMap.set(parent.account_number, account.id);
			}
			insertedIds.push(account.id);
		}

		// 2. Insert children dengan parent_account diisi ID berdasarkan account_number atau parent_account langsung
		const childrenToInsert = [];
		for (const child of children) {
			// Cari parent_account berdasarkan account_number jika belum ada dan account_number ada
			let parentAccountNumber = child.parent_account;
			if (!parentAccountNumber && child.account_number) {
				parentAccountNumber = getParentAccountNumber(child.account_number);
			}

			// Cari ID parent dari map berdasarkan account_number
			let parentId = null;
			if (parentAccountNumber) {
				parentId = accountIdMap.get(parentAccountNumber);
				if (!parentId) {
					// Jika parent tidak ditemukan, treat sebagai root dengan warning
					console.warn(`Parent account '${parentAccountNumber}' not found for child '${child.name}', treating as root.`);
					parentId = null;
				}
			}

			// Update child.parent_account dengan ID
			child.parent_account = parentId;

			// Validate existing
			const existing = await dbSAPPS.Account.findOne({
				where: {
					name: child.name,
					account_name: child.account_name,
					account_number: child.account_number,
					parent_account: child.parent_account,
					company_id: child.company_id,
				},
				transaction,
			});
			if (existing) {
				console.warn(`Child account '${child.name}' already exists, skipping.`);
				continue;
			}

			childrenToInsert.push(child);
		}

		// Bulk insert children jika ada
		if (childrenToInsert.length > 0) {
			const insertedChildren = await dbSAPPS.Account.bulkCreate(childrenToInsert, { transaction });
			insertedIds.push(...insertedChildren.map((acc) => acc.id));
		}

		await transaction.commit();
		return {
			ids: insertedIds,
			success: true,
			message: `Successfully imported ${insertedIds.length} accounts! Parents: ${parents.length}, Children: ${childrenToInsert.length}`,
		};
	} catch (error) {
		await transaction.rollback();
		const errorMessage = error?.message || "Failed to import accounts, please try again!";
		console.error("Import error:", error); // Log untuk debugging
		return {
			success: false,
			message: errorMessage,
		};
	}
}

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