import { delay } from "../../../../../../globalUtils/delay.js";
import XLSX from "xlsx";
import { tryCatch } from "../../../../../../globalUtils/tryCatch.js";
import { db } from "../../../../../../../database/dbclient.js";
import { settings } from "../../../../../../../database/schema/settings.js";
import { query } from "../../../../../sqlServer/prodSqlServer.js";
import { orderState } from "../../../../../sqlServer/querys/dm/orderState.js";
import { excelDateStuff } from "../../../../utils/excelDateStuff.js";
import { invoiceAddress } from "../../../../../sqlServer/querys/dm/invoiceAddress.js";
import { postOrders } from "../postOrders.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 { data: s, error: e } = await tryCatch(db.select().from(settings));

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

    // order state
    const { data: o, error: oe } = await tryCatch(
        query(orderState, "Gets the next 500 orders that have not been started")
    );

    const openOrders: any = o?.data;

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

    // order state
    const { data: invoice, error: ie } = await tryCatch(
        query(invoiceAddress, "Gets invoices addresses")
    );
    const i: any = invoice?.data;
    if (ie) {
        return {
            sucess: false,
            message: `Error getting invoice address data`,
            data: ie,
        };
    }
    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 = workbook.Sheets["Data"];

    // 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[0].value,
        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 != ""
    );

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

    let 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.CustomerRealeaseNumber).trim() ===
                        String(oo.CustomerRealeaseNumber).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.filter(
                (i: any) => i.deliveryAddress === parseInt(customerID)
            );
            if (!invoice) {
                return;
            }
            return {
                customerId: parseInt(customerID),
                invoiceAddressId: invoice[0]?.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 postOrders(updatedPredefinedObject, 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,
    };
};
