import axios from "axios";
import { addDays } from "date-fns";
import XLSX from "xlsx";
import { db } from "../../../../../../../database/dbclient.js";
import { settings } from "../../../../../../../database/schema/settings.js";
import { tryCatch } from "../../../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../../../logger/logger.js";
import { sendEmail } from "../../../../../notifications/controller/sendMail.js";
import { query } from "../../../../../sqlServer/prodSqlServer.js";
import { activeArticle } from "../../../../../sqlServer/querys/dataMart/article.js";
import { excelDateStuff } from "../../../../utils/excelDateStuff.js";
import { postForecast } from "../postForecast.js";

let customerID = 4;
export const lorealForecast = 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 plantToken = s.filter((s) => s.name === "plantToken");

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

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

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

	const psheet: any = workbook.Sheets["Alpla PET"];
	const prange = XLSX.utils.decode_range(psheet["!ref"]);

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

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

	const ebmForeCastData: any = XLSX.utils.sheet_to_json(sheet, {
		defval: "",
		header: headers,
		range: 3,
	});

	const petForeCastData: any = XLSX.utils.sheet_to_json(psheet, {
		defval: "",
		header: pheaders,
		range: 3,
	});

	const ebmForecastData: any = [];
	const missingSku: any = [];

	const { data: a, error: ae } = await tryCatch(
		query(activeArticle, "Loreal calling active av"),
	);

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

	const article: any = a?.data;

	// process the ebm forcast
	for (let i = 0; i < ebmForeCastData.length; i++) {
		// bottle code
		const sku = ebmForeCastData[i]["HDPE Bottle Code"];

		// ignore the blanks
		if (sku === "") continue;

		// ignore zero qty
		// if (ebmForeCastData[i][`Day ${i}`]) continue;

		for (let f = 0; f <= 90; f++) {
			const day = `Day ${f + 1}`;
			// if (ebmForeCastData[i][day] === 0) continue;

			const forcast = {
				customerArticleNo: sku,
				requirementDate: addDays(new Date(Date.now()), f), //excelDateStuff(parseInt(date)),
				quantity: ebmForeCastData[i][day] ?? 0,
			};

			if (forcast.quantity === 0) continue;

			// checking to make sure there is a real av to add to.
			const activeAV = article.filter(
				(c: any) =>
					c?.CustomerArticleNumber === forcast.customerArticleNo.toString(),
			);

			if (activeAV.length === 0) {
				if (typeof forcast.customerArticleNo === "number") {
					missingSku.push(forcast);
				}
				continue;
			}

			ebmForecastData.push(forcast);
		}

		//console.log(ebmForeCastData.length);
	}

	// petForeCastData.forEach((item: any, index: any) => {
	//     //console.log(`Processing item ${index + 1} of ${forecastData.length}`);

	//     // Extract the customer code
	//     const customerCode = item["SOUTH PET BOTTLES"];

	//     // Process each date in the current object
	//     for (const [date, qty] of Object.entries(item)) {
	//         // Skip metadata fields
	//         if (petMetadataFields.includes(date)) continue;

	//         if (qty === 0) continue;

	//         // Create your transformed record
	//         const record = {
	//             customerArticleNo: customerCode,
	//             requirementDate: excelDateStuff(parseInt(date)),
	//             quantity: qty,
	//         };

	//         // Do something with this record
	//         petForecastData.push(record);
	//     }
	// });

	// pet forecast
	for (let i = 0; i < petForeCastData.length; i++) {
		// bottle code
		const sku = petForeCastData[i]["South PET Bottle Code"];

		// ignore the blanks
		if (sku === "") continue;

		// ignore zero qty
		// if (ebmForeCastData[i][`Day ${i}`]) continue;

		for (let f = 0; f <= 90; f++) {
			const day = `Day ${f + 1}`;
			// if (ebmForeCastData[i][day] === 0) continue;

			const forcast = {
				customerArticleNo: sku,
				requirementDate: addDays(new Date(Date.now()), f), //excelDateStuff(parseInt(date)),
				quantity: petForeCastData[i][day] ?? 0,
			};

			if (forcast.quantity === 0 || forcast.quantity === "") continue;

			if (forcast.customerArticleNo < 99999) {
				//console.log(`Sku a normal av ${forcast.customerArticleNo}`);
				continue;
			}

			// checking to make sure there is a real av to add to.
			const activeAV = article.filter(
				(c: any) =>
					c?.CustomerArticleNumber === forcast.customerArticleNo.toString(),
			);

			if (activeAV.length === 0) {
				if (typeof forcast.customerArticleNo === "number") {
					missingSku.push(forcast);
				}
				continue;
			}

			ebmForecastData.push(forcast);
		}
	}

	//console.log(comForecast);

	// email the  for the missing ones
	const missedGrouped = Object.values(
		missingSku.reduce((acc: any, item: any) => {
			const key = item.customerArticleNo;

			if (!acc[key]) {
				// first time we see this customer
				acc[key] = item;
			} else {
				// compare dates and keep the earliest
				if (
					new Date(item.requirementDate) < new Date(acc[key].requirementDate)
				) {
					acc[key] = item;
				}
			}

			return acc;
		}, {}),
	);

	const emailSetup = {
		email:
			"Blake.matthes@alpla.com; Stuart.Gladney@alpla.com; Harold.Mccalister@alpla.com; Jenn.Osbourn@alpla.com",
		subject:
			missedGrouped.length > 0
				? `Alert! There are ${missedGrouped.length}, missing skus.`
				: `Alert! There is a missing SKU.`,
		template: "missingLorealSkus",
		context: {
			items: missedGrouped,
		},
	};

	const { data: sentEmail, error: sendEmailError } = await tryCatch(
		sendEmail(emailSetup),
	);
	if (sendEmailError) {
		createLog(
			"error",
			"blocking",
			"notify",
			"Failed to send email, will try again on next interval",
		);
		return {
			success: false,
			message: "Failed to send email, will try again on next interval",
		};
	}

	// if the customerarticle number is not matching just ignore it
	const predefinedObject = {
		receivingPlantId: plantToken[0].value,
		documentName: `ForecastFromLST-${new Date(Date.now()).toLocaleString(
			"en-US",
		)}`,
		sender: user.username || "lst-system",
		customerId: customerID,
		positions: [],
	};

	let updatedPredefinedObject = {
		...predefinedObject,
		positions: [
			...predefinedObject.positions,
			...ebmForecastData,

			// ...ebmForecastData.filter(
			//     (q: any) =>
			//         q.customerArticleNo != "" && q.customerArticleNo != "Total"
			// ),
			// ...petForecastData.filter(
			//     (q: any) =>
			//         q.customerArticleNo != "" && q.customerArticleNo != "Total"
			// ),
		],
	};
	// console.log(updatedPredefinedObject);

	// posting the data to the new backend so we can store the data.
	axios.post(
		`http://localhost:${process.env.NODE_ENV?.trim() != "production" ? "4200/lst" : "4000"}/api/logistics/dm/forecastData`,
		ebmForecastData,
	);
	const posting: any = await postForecast(updatedPredefinedObject, user);

	return {
		success: posting.success,
		message: posting.message,
		data: posting.data === "" ? ebmForecastData : posting.data,
	};
};
