import XLSX from "xlsx";
import { runDatamartQuery } from "../datamart/datamart.controller.js";
import { db } from "../db/db.controller.js";
import { settings } from "../db/schema/settings.schema.js";
import {
	type SqlQuery,
	sqlQuerySelector,
} from "../prodSql/prodSqlQuerySelector.utils.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 pNgForecast = async (data: any, user: any) => {
	/**
	 * Post a standard forecast based on the standard template.
	 */

	const { data: s, error: e } = await tryCatch(db.select().from(settings));

	if (e) {
		return {
			sucess: false,
			message: `Error getting settings`,
			data: e,
		};
	}

	const pNg = s.filter((n: any) => n.name === "pNgAddress");

	const avSQLQuery = sqlQuerySelector(`datamart.activeArticles`) as SqlQuery;

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

	const { data: a, error: ae } = await tryCatch(
		runDatamartQuery({ name: "activeArticles", options: {} }),
	);

	if (ae) {
		return {
			success: false,
			message: "Error getting active av",
			data: [],
		};
	}

	const article: any = a?.data;

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

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

	//const sheet: any = workbook.Sheets[sheetName];
	const sheet: any = workbook.Sheets["SchedAgreementUIConfigSpreadshe"];
	const range = XLSX.utils.decode_range(sheet["!ref"]);

	const headers = [];
	for (let C = range.s.c; C <= range.e.c; ++C) {
		const cellAddress = XLSX.utils.encode_cell({ r: 0, c: C }); // row 0 = Excel row 1
		const cell = sheet[cellAddress];
		headers.push(cell ? cell.v : undefined);
	}

	//console.log(headers);
	const forecastData: any = XLSX.utils.sheet_to_json(sheet, {
		defval: "",
		header: headers,
		range: 1,
	});

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

	const foreCastData: any = [];

	for (const [customerID, forecast] of Object.entries(groupedByCustomer)) {
		//console.log(`Running for Customer ID: ${customerID}`);
		const newForecast: any = forecast;

		const predefinedObject = {
			receivingPlantId: process.env.PROD_PLANT_TOKEN ?? "test1",
			documentName: `ForecastFromLST-${new Date(Date.now()).toLocaleString(
				"en-US",
			)}`,
			sender: user.username || "lst-system",
			customerId: pNg[0]?.value,
			positions: [],
		};

		// map everything out for each order
		const nForecast = newForecast.map((o: any) => {
			// const invoice = i.filter(
			//     (i: any) => i.deliveryAddress === parseInt(customerID)
			// );
			// if (!invoice) {
			//     return;
			// }

			return {
				customerArticleNo: parseInt(o["Customer Item No."] ?? "0", 10),
				requirementDate: excelDateStuff(parseInt(o["Request Date"] ?? "0", 10)),
				quantity: o["Remaining Qty to be Shipped"],
			};
		});

		// check to make sure the av belongs in this plant.
		const onlyNumbers = nForecast.filter((n: any) => n.quantity > 0);
		const filteredForecast: any = [];

		for (let i = 0; i < nForecast.length; i++) {
			//console.log(nForecast[i].customerArticleNo);
			const activeAV = article.filter(
				(c: any) =>
					c?.CustomerArticleNumber ===
						nForecast[i]?.customerArticleNo.toString() &&
					// validate it works via the default address
					c?.IdAdresse === parseInt(pNg[0]?.value ?? "139", 10),
			);

			if (activeAV.length > 0) {
				filteredForecast.push(onlyNumbers[i]);
			}
		}

		if (filteredForecast.length === 0) {
			console.log("Nothing to post");
			return {
				success: true,
				message: "No forecast to be posted",
				data: foreCastData,
			};
		}

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

		//console.log(updatedPredefinedObject);

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

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

	return {
		success: foreCastData[0].success,
		message: foreCastData[0].message,
		data: foreCastData,
	};
};
