import { db } from "../../../../../../../database/dbclient.js";
import { settings } from "../../../../../../../database/schema/settings.js";
import { tryCatch } from "../../../../../../globalUtils/tryCatch.js";
import XLSX from "xlsx";
import { excelDateStuff } from "../../../../utils/excelDateStuff.js";
import { postForecast } from "../postForecast.js";
import { query } from "../../../../../sqlServer/prodSqlServer.js";
import { activeArticle } from "../../../../../sqlServer/querys/dataMart/article.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 { data: a, error: ae } = await tryCatch(
        query(activeArticle, "p&g active av")
    );

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

    const article: any = a?.data;

    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 sheetName = workbook.SheetNames[0];
    //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: plantToken[0].value,
            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."]),
                requirementDate: excelDateStuff(parseInt(o["Request Date"])),
                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)
            );

            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
        let updatedPredefinedObject = {
            ...predefinedObject,
            positions: [...predefinedObject.positions, ...filteredForecast],
        };

        //console.log(updatedPredefinedObject);

        // post the orders to the server
        const posting: any = await postForecast(updatedPredefinedObject, user);

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

    return {
        success: true,
        message: "Forecast Posted",
        data: foreCastData,
    };
};
