import { eq } from "drizzle-orm";
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 { getPrinters } from "./getPrinters.js";
import { autoLabelingStats, printerStatus } from "./printerStatus.js";

let isPrinterCycling = false;
let actualPrinterCycle: any;

export const printerCycle = async () => {
    /**
     * We will cycle through the printers to check there states.
     */

    if (isPrinterCycling)
        return {
            success: false,
            message: "Printers are already being cycled.",
        };

    createLog("info", "ocp", "ocp", "Printer cycle has started.");
    // get the printers
    const { data: s, error: se } = await tryCatch(
        db.select().from(settings).where(eq(settings.name, "ocpCycleDelay"))
    );
    if (se) {
        createLog(
            "error",
            "ocp",
            "ocp",
            "There was an error getting the ocpCycleDelay."
        );
        return {
            success: false,
            message: "Error getting printers.",
        };
    }

    const ocpDelay: any = s;
    isPrinterCycling = true;
    // start the actual printer cycle
    actualPrinterCycle = setInterval(async () => {
        const { data, error } = await tryCatch(getPrinters());

        if (error) {
            createLog(
                "error",
                "ocp",
                "ocp",
                "There was an error getting the printers."
            );
            return {
                success: false,
                message: "Error getting printers.",
            };
        }
        let printers: any = data.data;

        // only keep the assigned ones
        printers = printers.filter((p: any) => p.assigned === true);

        // for printers we want to ignore there must be a remark stateing to ignore.
        printers = printers.filter((p: any) => !p.remark.includes("ignore"));

        printers.forEach(async (p: any) => {
            /**
             * if the last timeprinted would be greater than x well just change the status to idle and extended based on the 2 times.
             *
             * to get a printer going again label will need to come from the front end as that will just unpause the printer and start the labeling, or the api for manual print
             * well need to adjust this to actually print the label then unpause it.
             *
             * it will be
             *
             * less than x since time printed run the printer status
             * greater than x but less than y change the status to idle, but ping to make sure its online,
             * if greater than y change to extended idle but stil also ping to make sure its online.
             */

            // ignore pdf printer as we want it here for testing purposes
            if (p.name.toLowerCase() === "pdf24") {
                return;
            }

            if (p.name === "Autolabeler") {
                //await autoLabelingStats(p);
                return;
            }

            // for all other printers
            await printerStatus(p);
        });
    }, parseInt(ocpDelay[0]?.value) * 1000);

    return { success: true, message: "Printer cycle has been started." };
};

export const stopPrinterCycle = async () => {
    /**
     * We will stop the print cylce this is more an emergancy thing.
     */
    if (actualPrinterCycle && !actualPrinterCycle._destroyed) {
        createLog("info", "ocp", "ocp", "Printer cycle is being stopped.");
        clearInterval(actualPrinterCycle);
        isPrinterCycling = false;
        return { success: true, message: "Printer cycle has been stopped." };
    } else {
        createLog("info", "ocp", "ocp", "Printer cycle is already stopped.");
        isPrinterCycling = false;
        return { success: true, message: "Printer cycle is already Stopped." };
    }
};
