import { eq, sql } from "drizzle-orm";
import { db } from "../../../../../../database/dbclient.js";
import { serverData } from "../../../../../../database/schema/serverData.js";
import { settings } from "../../../../../../database/schema/settings.js";
import { tryCatch } from "../../../../../globalUtils/tryCatch.js";
import { notifications } from "../../../../../../database/schema/notifications.js";
import { getHeaders } from "../../../../sqlServer/querys/notifications/ti/getHeaders.js";
import { query } from "../../../../sqlServer/prodSqlServer.js";
import { createLog } from "../../../../logger/logger.js";
import { getOrderToSend } from "../../../../sqlServer/querys/notifications/ti/getOrderToSend.js";
import { xmlPayloadTI } from "./tiXmlPayload.js";
import { headerUpdate } from "./headerUpdate.js";
import { loadItems } from "./loadItems.js";
import { dateCorrection } from "./dateCorrection.js";
import { scacCheck } from "./scacCodeCheck.js";
import { postToTi } from "./postToTI.js";
import { escapeXml } from "../../../utils/xmlCharFixes.js";

export const tiImport = async () => {
    // get the plant token
    let payload = xmlPayloadTI;
    const { data: plantData, error: plantError } = await tryCatch(
        db.select().from(settings)
    );

    if (plantError)
        return {
            success: false,
            message: "Error Getting Plant Data.",
            data: plantError,
        };
    const plantToken = plantData?.filter((n) => n.name === "plantToken");

    const { data: plantInfo, error: plantEr } = await tryCatch(
        db
            .select()
            .from(serverData)
            .where(eq(serverData.plantToken, plantToken[0].value))
    );

    if (plantEr)
        return {
            success: false,
            message: "Error Getting Plant Data.",
            data: plantEr,
        };

    // parsing posting window
    const plantI = plantInfo!;

    // order notifications
    const { data: notificationSet, error: notificationSettingsErr } =
        await tryCatch(
            db
                .select()
                .from(notifications)
                .where(eq(notifications.name, "tiIntergration"))
        );
    if (notificationSettingsErr)
        return {
            success: false,
            message: "Notification missing.",
            data: notificationSettingsErr,
        };

    const notiSet: any = notificationSet;
    const customerAccountNum = plantI[0].customerTiAcc as string; // tiIntergration
    // get current releaes not in the already sent oders

    const releaseString = notiSet[0].notifiySettings.releases

        .map((num: any) => `'${num.releaseNumber}'`)
        .join(", ");

    let orders = getHeaders
        .replaceAll("[from]", notiSet[0]?.notifiySettings.start)
        .replaceAll("[to]", notiSet[0]?.notifiySettings.end)
        .replaceAll("[exclude]", releaseString);

    // get the headers pending
    const { data: h, error: headerError } = await tryCatch(
        query(orders, "Ti get open headers")
    );
    const header: any = h?.data as any;

    if (headerError) {
        createLog(
            "error",
            "ti",
            "notify",
            `Error getting headers: ${headerError}`
        );
        return {
            success: false,
            message: "Error getting headers",
            data: headerError,
        };
    }

    if (header.length === 0) {
        createLog(
            "info",
            "ti",
            "notify",
            "There are no pending orders to be sent over to ti."
        );
        return {
            success: true,
            message: "There are no pending orders to be sent over to ti.",
        };
    }

    createLog(
        "info",
        "tiIntergration",
        "notify",
        `There are a total of ${header.length} to send over`
    );

    /**
     * Update the query to get only the first header
     */

    // update query to have the correct plant token
    let orderToSend = getOrderToSend

        .replaceAll("test1", plantToken[0].value)
        .replaceAll("[releaseToProcess]", `'${header[0].releaseNumber}'`)
        .replaceAll("[from]", notiSet[0].notifiySettings.start)
        .replaceAll("[to]", notiSet[0].notifiySettings.end);

    // get the headers pending
    const { data: o, error: ordersError } = await tryCatch(
        query(orderToSend, "Ti get open headers")
    );

    const orderData: any = o?.data as any;
    if (ordersError)
        return {
            success: false,
            message: "Error getting getting orders",
            data: ordersError,
        };

    // update the special instructions section
    const otherSettings = plantI[0]?.otherSettings as {
        specialInstructions: string;
        active: boolean;
    }[];

    const specialInfo = otherSettings[0].specialInstructions.replaceAll(
        "[header]",
        orderData[0].Header
    );

    // add the full amount of pallets sending over
    let fullPalToSend = orderData.reduce(
        (acc: any, o: any) => acc + o.Pallets,
        0
    );

    //console.log("payload", payload);
    payload = payload
        .replaceAll(
            `[WebImportHeader]`,
            await headerUpdate(orderData, plantToken)
        )
        .replaceAll(`[items]`, await loadItems(orderData))
        .replaceAll(`[customerAccountNum]`, customerAccountNum)
        .replaceAll("[fullTotalPal]", fullPalToSend)
        // add in release info
        .replaceAll(`[shipNumber]`, orderData[0].releaseNumber)
        .replaceAll(`[loadNumber]`, orderData[0].releaseNumber);

    // add in the multi release numbers
    let multiRelease = ``;
    if (orderData.length > 0) {
        for (let i = 0; i < orderData.length; i++) {
            const newRelease = `
            <ReferenceNumber type="Release Number" isPrimary="false">${orderData[i].releaseNumber}</ReferenceNumber>`;
            multiRelease += newRelease;
        }

        payload = payload.replaceAll("[multieReleaseNumber]", multiRelease);
    } else {
        payload = payload.replaceAll("[multieReleaseNumber]", "");
    }

    // add the correct date stuff
    payload = payload
        .replaceAll(
            "[loadingDate]",
            await dateCorrection(orderData[0].LoadingDate)
        )

        .replaceAll(
            "[deliveryDate]",
            await dateCorrection(orderData[0].DeliveryDate)
        );

    // shipping ours corrections
    const formattedDate = orderData[0].LoadingDate.toLocaleDateString("en-US", {
        month: "2-digit",
        day: "2-digit",
        year: "numeric",
    });
    const shippingHours = JSON.parse(plantI[0]?.shippingHours!);

    payload = payload
        .replaceAll(
            "[shippingHoursEarly]",
            `${formattedDate} ${shippingHours[0].early}`
        )
        .replaceAll(
            "[shippingHoursLate]",
            `${formattedDate} ${shippingHours[0].late}`
        );

    // special instructions
    if (otherSettings[0].specialInstructions.length != 0) {
        payload = payload.replaceAll("[specialInstructions]", specialInfo);
    } else {
        payload = payload.replaceAll("[specialInstructions]", "");
    }

    // shipper info
    payload = payload
        .replaceAll("[plantName]", escapeXml(`Alpla ${plantI[0]?.sName!}`))
        .replaceAll(
            "[plantStreetAddress]",
            escapeXml(plantI[0]?.streetAddress!)
        )
        .replaceAll(
            "[plantCity]",
            escapeXml(plantI[0]?.cityState!.split(",")[0])
        )
        .replaceAll(
            "[plantState]",
            escapeXml(plantI[0]?.cityState!.split(",")[1])
        )
        .replaceAll("[plantZipCode]", escapeXml(plantI[0]?.zipcode!))
        .replaceAll("[contactNum]", escapeXml(plantI[0]?.contactPhone!))
        .replaceAll("[contactEmail]", escapeXml(plantI[0]?.contactEmail!))

        // customer info
        .replaceAll("[customerName]", escapeXml(orderData[0].addressAlias))
        .replaceAll(
            "[customerStreetAddress]",
            escapeXml(orderData[0].streetAddress)
        )
        .replaceAll(
            "[customerCity]",
            escapeXml(orderData[0].city.split(",")[0])
        )
        .replaceAll(
            "[customerState]",
            escapeXml(orderData[0].city.split(",")[1])
        )
        .replaceAll("[customerZip]", escapeXml(orderData[0].zipCode))
        .replaceAll("[customerPO]", escapeXml(orderData[0].Header))
        // .replaceAll(
        //     "[glCoding]",
        //     `52410-${
        //         orderData[0].artileType.toLowerCase() === "preform" ||
        //         orderData[0].artileType.toLowerCase() === "metalCage"
        //             ? 31
        //             : plantI[0].greatPlainsPlantCode
        //     }`
        // ) // {"52410 - " + (artileType.toLowerCase() === "preform" || artileType.toLowerCase() === "metalCage" ? 31: plantInfo[0].greatPlainsPlantCode)}
        .replaceAll("[glCoding]", `52410`)
        .replaceAll(
            "[pfc]",
            `${
                orderData[0].artileType.toLowerCase() === "preform" ||
                orderData[0].artileType.toLowerCase() === "metalCage"
                    ? 40
                    : orderData[0].costCenter
            }`
        )
        .replaceAll(
            "[locCode]",
            `${
                orderData[0].artileType.toLowerCase() === "preform" ||
                orderData[0].artileType.toLowerCase() === "metalCage"
                    ? 31
                    : plantI[0].greatPlainsPlantCode
            }`
        )
        .replaceAll("[priceSheet]", await scacCheck(orderData));
    //send over to be processed

    //console.log("payload", payload);

    const { data: tiPost, error: tiError } = await tryCatch(
        postToTi(
            payload,
            `${orderData[0].addressAlias.replaceAll(" ", "")}-${
                header[0].releaseNumber
            }`
        )
    );

    if (tiError) {
        return {
            success: false,
            message: "Error posting to TI",
            error: tiError,
        };
    }

    /**
     * Update the db so we dont try to pull the next one
     */

    const currentDate = new Date(Date.now());
    const uniqueOrders = Array.from(
        new Set([
            ...notiSet[0].notifiySettings.releases,
            {
                releaseNumber: header[0].releaseNumber,
                timeStamp: currentDate,
            },
        ])
    );

    // 45 days ago
    const dateLimit = new Date(
        currentDate.getTime() - 45 * 24 * 60 * 60 * 1000
    );

    // filter dates
    let filteredOrders = uniqueOrders.filter((item) => {
        const time = new Date(item.timeStamp).getTime();
        return time >= dateLimit.getTime();
    });

    const { data, error } = await tryCatch(
        db
            .update(notifications)
            .set({
                lastRan: sql`NOW()`,
                notifiySettings: {
                    ...notiSet[0].notifiySettings,
                    releases: filteredOrders,
                },
            })
            .where(eq(notifications.name, "tiIntergration"))
    );

    createLog("info", "ti", "notify", "done with this order");

    return { message: "done with this order" };
};
