const { Op, Sequelize } = require("sequelize");
const dbSAPPS = require("../../helpers/db");
require("dotenv").config();

module.exports = {
	getAll,
	filter,
	option,
	count,
	create,
	update,
	enabled,
	delete: _delete,
};

async function getAll() {
	try {
		const customerLists = await dbSAPPS.CustomerList.findAll({
			order: [["modified", "DESC"]],
			include: [
				{
					model: dbSAPPS.AddressChild,
					as: "addresschilds",
					attributes: ["id", "customer_id", "type", "address"],
				},
				{
					model: dbSAPPS.CustomerPICChild,
					as: "customerpicchilds",
					attributes: ["id", "name", "department", "contact", "email"],
				},
				{
					model: dbSAPPS.Company,
					as: "company",
					attributes: ["name"],
				},
			],
		});

		return {
			customerLists,
			success: true,
			message: "Customer lists loaded successfully!",
		};
	} catch (error) {
		const errorMessage = error.message || "Failed to load Customer lists!";
		return {
			success: false,
			message: errorMessage,
		};
	}
}

async function filter(params) {
	const filterConditions = {};

	const parseIdList = (value) => {
		if (value === undefined || value === null || value === "") return [];
		const parts = Array.isArray(value) ? value : String(value).split(",");
		const ids = parts
			.flatMap((v) => String(v).split(","))
			.map((v) => Number.parseInt(String(v).trim(), 10))
			.filter((n) => Number.isFinite(n));
		return Array.from(new Set(ids));
	};

	const like = (value) => ({
		[Op.like]: `%${String(value).trim()}%`,
	});

	if (params.enabled !== undefined && params.enabled !== null && params.enabled !== "") {
		filterConditions.enabled = {
			[Op.eq]: params.enabled === "1" || params.enabled === 1 || params.enabled === true,
		};
	}

	// Pattern precedence: company_id takes priority over companiesId
	const companyId = Number.parseInt(params.company_id, 10);
	const companiesId = parseIdList(params.companiesId);
	if (Number.isFinite(companyId)) {
		filterConditions.company_id = { [Op.eq]: companyId };
	} else if (companiesId.length > 0) {
		filterConditions.company_id = { [Op.in]: companiesId };
	}

	const andConditions = [];
	if (params.q) {
		const q = String(params.q).trim();
		if (q.length) {
			andConditions.push({
				[Op.or]: [{ name: like(q) }, { type: like(q) }, Sequelize.where(Sequelize.col("company.name"), like(q))],
			});
		}
	}

	if (params.f_name) andConditions.push({ name: like(params.f_name) });
	if (params.f_type) andConditions.push({ type: like(params.f_type) });

	if (andConditions.length) {
		filterConditions[Op.and] = andConditions;
	}

	try {
		const companyInclude = {
			model: dbSAPPS.Company,
			as: "company",
			attributes: ["name"],
		};

		if (params.f_company_name) {
			companyInclude.where = { name: like(params.f_company_name) };
			companyInclude.required = true;
		}

		const customerLists = await dbSAPPS.CustomerList.findAll({
			where: filterConditions,
			order: [["modified", "DESC"]], // Opsional: Mengurutkan hasil berdasarkan kolom 'modified'
			include: [
				{
					model: dbSAPPS.AddressChild,
					as: "addresschilds",
					attributes: ["id", "customer_id", "type", "address"],
				},
				{
					model: dbSAPPS.CustomerPICChild,
					as: "customerpicchilds",
					attributes: ["id", "name", "department", "contact", "email"],
				},
				companyInclude,
			],
		});

		return {
			success: true,
			customerLists,
			message: "Customer Lists loaded successfully!",
		};
	} catch (error) {
		console.error("Error retrieving Customer Lists: ", error);
		const errorMessage = error.message || "Failed to retrieve Customer Lists. Please try again later.";
		return {
			success: false,
			message: errorMessage,
		};
	}
}

async function option() {
	try {
		const customerLists = await dbSAPPS.CustomerList.findAll({
			attributes: ["id", "name", "territory_id", "subterritory_id"],
			where: { enabled: true },
			order: [["name", "ASC"]],
			include: [
				{
					model: dbSAPPS.AddressChild,
					as: "addresschilds",
					attributes: ["id", "customer_id", "type", "address"],
				},
				{
					model: dbSAPPS.CustomerPICChild,
					as: "customerpicchilds",
					attributes: ["id", "name", "department", "contact", "email"],
				},
				{
					model: dbSAPPS.Company,
					as: "company",
					attributes: ["name"],
				},
			],
		});

		return {
			success: true,
			customerLists,
			message: "Customer Lists loaded successfully!",
		};
	} catch (error) {
		console.error("Error retrieving Customer Lists: ", error);
		const errorMessage = error.message || "Failed to retrieve Customer Lists. Please try again later.";
		return {
			success: false,
			message: errorMessage,
		};
	}
}

async function count() {
	try {
		const count = await dbSAPPS.CustomerList.count({
			where: { enabled: true },
		});

		return {
			success: true,
			count,
			message: "Customer Lists loaded successfully!",
		};
	} catch (error) {
		console.error("Error counting Customer Lists: ", error);
		return {
			success: false,
			message: "Failed to retrieve Customer Lists count. Please try again later.",
		};
	}
}

async function create(params) {
	const transaction = await dbSAPPS.sequelize.transaction();
	try {
		// Validasi parameter yang diperlukan
		if (!params.company_id) {
			return {
				success: false,
				message: "Company is required!",
			};
		}

		if (!params.name) {
			return {
				success: false,
				message: "Customer Name is required!",
			};
		}

		// Cek apakah customer list sudah ada
		const existingCustomer = await dbSAPPS.CustomerList.findOne({
			where: {
				name: params.name,
			},
		});

		if (existingCustomer) {
			return {
				success: false,
				message: `Customer with "${params.name}" is already taken.`,
			};
		}

		// Set default value untuk enabled
		if (!params.enabled) params.enabled = true;

		// Buat Customer List baru
		const newCustomerList = await dbSAPPS.CustomerList.create(params, {
			transaction,
		});

		// Proses addresschilds jika ada
		if (params.addresschilds) {
			// Pastikan data adalah array
			if (typeof params.addresschilds === "string") {
				params.addresschilds = JSON.parse(params.addresschilds);
			}

			// Validasi dan persiapkan data untuk bulkCreate
			const addressChildData = params.addresschilds.map((addressChild) => {
				// Validasi field yang diperlukan
				if (!addressChild.address) {
					throw new Error("Missing required fields in address child.");
				}

				return {
					...addressChild,
					creation: Date.now(),
					modified: Date.now(),
					modified_by: params.modified_by,
					owner: params.owner,
					customer_id: newCustomerList.id,
				};
			});

			// Lakukan bulkCreate
			try {
				await dbSAPPS.AddressChild.bulkCreate(addressChildData, {
					transaction,
				});
			} catch (bulkCreateError) {
				await transaction.rollback();
				return {
					success: false,
					message: "Failed to create address child: " + bulkCreateError.message,
				};
			}
		}

		// Proses pic child jika ada
		if (params.customerpicchilds) {
			// Pastikan data adalah array
			if (typeof params.customerpicchilds === "string") {
				params.customerpicchilds = JSON.parse(params.customerpicchilds);
			}

			// Validasi dan persiapkan data untuk bulkCreate
			const picChildData = params.customerpicchilds.map((picChild) => {
				// Validasi field yang diperlukan
				if (!picChild.name) {
					throw new Error("Missing required fields in address child.");
				}

				return {
					...picChild,
					creation: Date.now(),
					modified: Date.now(),
					modified_by: params.modified_by,
					owner: params.owner,
					customer_id: newCustomerList.id,
				};
			});

			// Lakukan bulkCreate
			try {
				await dbSAPPS.CustomerPICChild.bulkCreate(picChildData, {
					transaction,
				});
			} catch (bulkCreateError) {
				await transaction.rollback();
				return {
					success: false,
					message: "Failed to create PIC Child: " + bulkCreateError.message,
				};
			}
		}

		// Commit transaksi jika semua berhasil
		await transaction.commit();
		return {
			success: true,
			message: "Data Customer List has been successfully added!",
			customerLists: newCustomerList,
		};
	} catch (error) {
		// Rollback transaksi jika terjadi kesalahan
		await transaction.rollback();
		const errorMessage = error.message || "An error occurred during Customer List creation.";
		console.error("Error creating customer list:", error); // Log kesalahan untuk debugging
		return {
			success: false,
			message: errorMessage,
		};
	}
}

async function update(id, params) {
	const transaction = await dbSAPPS.sequelize.transaction();
	try {
		// Mencari Customer List berdasarkan ID
		const customerList = await dbSAPPS.CustomerList.findByPk(id);
		if (!customerList) {
			return {
				success: false,
				message: "Customer not found!",
			};
		}

		// Validasi jika name diubah
		if (params.name && params.name !== customerList.name) {
			const existingCustomerName = await dbSAPPS.CustomerList.findOne({
				where: {
					name: params.name,
				},
			});
			if (existingCustomerName) {
				return {
					success: false,
					message: `Customer with "${params.name}" is already taken. Try again!`,
				};
			}
		}

		// Update Customer
		await customerList.update(params, { transaction });

		// Proses addresschilds jika ada
		if (params.addresschilds) {
			// Pastikan data adalah array
			if (typeof params.addresschilds === "string") {
				params.addresschilds = JSON.parse(params.addresschilds);
			}

			// Hapus child yang ada sebelum menambahkan yang baru
			await dbSAPPS.AddressChild.destroy({
				where: { customer_id: id },
				transaction,
			});

			// Persiapkan data untuk bulkCreate
			const addressChildData = params.addresschilds.map((addressChild) => {
				// Validasi field yang diperlukan
				if (!addressChild.address) {
					throw new Error("Missing required fields in address child.");
				}

				return {
					...addressChild,
					creation: Date.now(),
					modified: Date.now(),
					modified_by: params.modified_by,
					owner: params.owner,
					customer_id: id, // Mengaitkan dengan ID Customer List yang diupdate
				};
			});

			// Lakukan bulkCreate untuk child yang baru
			await dbSAPPS.AddressChild.bulkCreate(addressChildData, {
				transaction,
			});
		}

		if (params.customerpicchilds) {
			// Pastikan data adalah array
			if (typeof params.customerpicchilds === "string") {
				params.customerpicchilds = JSON.parse(params.customerpicchilds);
			}

			// Hapus child yang ada sebelum menambahkan yang baru
			await dbSAPPS.CustomerPICChild.destroy({
				where: { customer_id: id },
				transaction,
			});

			// Persiapkan data untuk bulkCreate
			const picChildData = params.customerpicchilds.map((picChild) => {
				// Validasi field yang diperlukan
				if (!picChild.name) {
					throw new Error("Missing required fields in address child.");
				}

				return {
					...picChild,
					creation: Date.now(),
					modified: Date.now(),
					modified_by: params.modified_by,
					owner: params.owner,
					customer_id: id, // Mengaitkan dengan ID Customer List yang diupdate
				};
			});

			// Lakukan bulkCreate untuk child yang baru
			await dbSAPPS.CustomerPICChild.bulkCreate(picChildData, {
				transaction,
			});
		}

		// Commit transaksi jika semua berhasil
		await transaction.commit();

		return {
			success: true,
			message: "Your data customer list has been saved!",
		};
	} catch (error) {
		// Rollback transaksi jika terjadi kesalahan
		await transaction.rollback();
		const errorMessage = error.message || "Failed to update customer list data.";
		console.error("Error updating Customer:", error); // Log kesalahan untuk debugging
		return {
			success: false,
			message: errorMessage,
		};
	}
}

async function enabled(id, params) {
	try {
		const customer = await dbSAPPS.CustomerList.findByPk(id);
		if (!customer)
			return {
				success: false,
				message: "Customer not found!",
			};

		const updateData = {};
		updateData.enabled = params.enabled;
		if (params.modified_by) updateData.modified_by = params.modified_by;
		if (params.modified) updateData.modified = params.modified;

		await customer.update(updateData);

		return {
			success: true,
			message: "Customer List has been updated!",
		};
	} catch (error) {
		const errorMessage = error.message || "Failed to Update Customer List";
		return {
			success: false,
			message: errorMessage,
		};
	}
}

async function _delete(id) {
	try {
		const customerList = await dbSAPPS.CustomerList.findByPk(id);
		if (!customerList) return { success: false, message: "Customer not found!" };

		await customerList.destroy();

		return {
			success: true,
			message: "Customer successfully deleted!",
		};
	} catch (error) {
		const errorMessage = error.message || "Failed to delete Customer.";
		return {
			success: false,
			message: errorMessage,
		};
	}
}
