import XLSX from "xlsx";
import { runDatamartQuery } from "../datamart/datamart.controller.js";
import { excelDateStuff } from "../utils/excelToDate.utils.js";
import { returnFunc } from "../utils/returnHelper.utils.js";
import { tryCatch } from "../utils/trycatch.utils.js";
import { postData } from "./logistics.dm.postData.js";

export const macroImportOrders = async (data: any, user: any) => {
	/**
	 * Standard orders meaning that we get the standard file exported and fill it out and uplaod to lst.
	 */

	const plantToken = process.env.PROD_PLANT_TOKEN;

	/*
    get the order state.
    */

	const { data: o, error: oe } = await tryCatch(
		runDatamartQuery({ name: "orderState", options: {} }),
	);

	if (oe) {
		return returnFunc({
			success: false,
			level: "error",
			module: "logistics",
			subModule: "orders",
			message: `Error getting Article info`,
			data: [oe.message],
			notify: true,
		});
	}

	const openOrders: any = o?.data;

	/*
    get default invoice address
    */
	const { data: invoice, error: ie } = await tryCatch(
		runDatamartQuery({ name: "invoiceAddress", options: {} }),
	);

	if (ie) {
		return returnFunc({
			success: false,
			level: "error",
			module: "logistics",
			subModule: "orders",
			message: `Error getting Article info`,
			data: [ie.message],
			notify: true,
		});
	}

	const i: any = invoice?.data;

	const buffer = Buffer.from(data.buffer);

	const workbook = XLSX.read(buffer, { type: "buffer" });

	const sheetName = workbook.SheetNames[0] as string;
	const sheet = workbook.Sheets[sheetName] as any;

	// define custom headers
	const headers = [
		"CustomerArticleNumber",
		"CustomerOrderNumber",
		"CustomerLineNumber",
		"CustomerRealeaseNumber",
		"Quantity",
		"DeliveryDate",
		"CustomerID",
		"Remark",
	];
	const orderData = XLSX.utils.sheet_to_json(sheet, {
		defval: "",
		header: headers,
		range: 5,
	});

	// the base of the import
	const predefinedObject = {
		receivingPlantId: plantToken ?? "test1",
		documentName: `OrdersFromLST-${new Date(Date.now()).toLocaleString(
			"en-US",
		)}`,
		sender: user.username || "lst-system",
		externalRefNo: `OrdersFromLST-${new Date(Date.now()).toLocaleString(
			"en-US",
		)}`,
		orders: [],
	};

	const removeBlanks = orderData.filter(
		(n: any) => n.CustomerArticleNumber !== "",
	);

	const groupedByCustomer: any = removeBlanks.reduce((acc: any, item: any) => {
		const id = item.CustomerID;
		if (!acc[id]) {
			acc[id] = [];
		}
		acc[id].push(item);
		return acc;
	}, {});

	const postedOrders: any = [];
	for (const [customerID, orders] of Object.entries(groupedByCustomer)) {
		// console.log(`Running for Customer ID: ${customerID}`);
		const filterOrders: any = orders;
		const newOrders: any = [];
		//newOrders.filter((oo) => openOrders.some((o) => String(o.CustomerOrderNumber) === String(oo.CustomerOrderNumber)));
		//console.log(newOrders)
		filterOrders.forEach((oo: any) => {
			const isMatch = openOrders.some(
				(o: any) =>
					// check the header
					String(o.CustomerOrderNumber).trim() ===
						String(oo.CustomerOrderNumber).trim() &&
					// and check the customer release is not in here.
					String(o.CustomerReleaseNumber).trim() ===
						String(oo.CustomerReleaseNumber).trim(),
			);
			if (!isMatch) {
				//console.log(`ok to update: ${oo.CustomerOrderNumber}`);

				newOrders.push(oo);
			} else {
				//console.log(`Not valid order to update: ${oo.CustomerOrderNumber}`);
				//console.log(oo)
			}
		});

		// filter out the orders that have already been started just to reduce the risk of errors.
		newOrders.filter((oo: any) =>
			openOrders.some(
				(o: any) => o.CustomerOrderNumber === oo.CustomerOrderNumber,
			),
		);

		// map everything out for each order
		const nOrder = newOrders.map((o: any) => {
			const invoice = i.find(
				(inv: any) => inv.deliveryAddress === parseInt(customerID),
			);
			if (!invoice) {
				return null;
			}
			return {
				customerId: parseInt(customerID),
				invoiceAddressId: invoice.invoiceAddress, // matched to the default invoice address
				customerOrderNo: o.CustomerOrderNumber,
				orderDate: new Date(Date.now()).toLocaleString("en-US"),
				positions: [
					{
						deliveryAddressId: parseInt(customerID),
						customerArticleNo: o.CustomerArticleNumber,
						quantity: parseInt(o.Quantity),
						deliveryDate: excelDateStuff(o.DeliveryDate),
						customerLineItemNo: o.CustomerLineNumber, // this is how it is currently sent over from abbott
						customerReleaseNo: o.CustomerRealeaseNumber, // same as above
						remark: o.remark === "" ? null : o.remark,
					},
				],
			};
		});

		// do that fun combining thing
		const updatedPredefinedObject = {
			...predefinedObject,
			orders: [...predefinedObject.orders, ...nOrder],
		};

		//console.log(updatedPredefinedObject);

		// post the orders to the server
		const posting: any = await postData(
			{
				type: "orders",
				endpoint: "/public/v1.0/DemandManagement/ORDERS",
				data: updatedPredefinedObject as any,
			},
			user,
		);

		postedOrders.push({
			customer: customerID,
			//totalOrders: orders?.length(),
			success: posting.success,
			message: posting.message,
			data: posting.data,
		});
	}

	return {
		success: true,
		message:
			"Standard Template was just processed successfully, please check AlplaProd 2.0 to confirm no errors. ",
		data: postedOrders,
	};
};
