/**
 * we want to be able to preprint labels from finished lots.
 * we will need a lot number
 * machine
 * printer
 * qty will come over as one by default
 * copies will come over as 0 by default
 * layout
 */

import { eq } from "drizzle-orm";
import type { Logger } from "pino";
import { db } from "../../../../pkg/db/db.js";
import { printers } from "../../../../pkg/db/schema/printers.js";
import { prodlabels } from "../../../../pkg/db/schema/prodLabels.js";
import { createLogger } from "../../../../pkg/logger/logger.js";
import { delay } from "../../../../pkg/utils/delay.js";
import { getMachineData } from "../../../../pkg/utils/getMachineInfo.js";
import { prodEndpoint } from "../../../../pkg/utils/prodEndpoint.js";
import { tryCatch } from "../../../../pkg/utils/tryCatch.js";

export type Preprint = {
	scannerId: number;
	lotNr: number;
	machineId: number;
	printerId: number;
	layoutId: number;
	numberOfCopies: number;
	qtyToPrint: number;
};

const addProdLabel = async (
	preprint: Preprint,
	runningNr: number,
	username: string,
	log: Logger,
) => {
	// get the printers
	const printerName = await db
		.select()
		.from(printers)
		.where(eq(printers.humanReadableId, preprint.printerId.toString()));

	// get the machine data
	const { data, error } = await tryCatch(getMachineData("all"));

	if (error) {
		log.error({ error: error }, "There was an error getting machine data");
	}

	const lineNumber = data.filter(
		(n: any) => n.HumanReadableId === preprint.machineId,
	);

	const { data: prodLabel, error: prodLabelError } = await tryCatch(
		db
			.insert(prodlabels)
			.values({
				printerID: preprint.printerId,
				printerName: printerName[0]?.name,
				runningNr: runningNr,
				status: "printed",
				line: lineNumber[0]?.Location || 0,
				add_user: username,
			})
			.onConflictDoNothing(),
	);

	if (prodLabelError) {
		log.error({ error: error }, "Error adding the label");
	}

	return;
};

export const preprintLabels = async (preprint: Preprint, username?: string) => {
	const log = createLogger({
		module: "logistics",
		subModule: "preprint",
	});
	let x = 0;

	const labelsPrinted: number[] = [];
	if (preprint.qtyToPrint > 1) {
		do {
			const labels = await prodEndpoint(
				"POST",
				"/public/v1.0/Warehousing/GenerateAndPrintLabel",
				{
					scannerId: preprint.scannerId.toString(),
					lotNr: preprint.lotNr.toString(),
					machineId: preprint.machineId.toString(),
					printerId: preprint.printerId.toString(),
					layoutId: preprint.layoutId.toString(),
					numberOfCopies: preprint.numberOfCopies.toString(),
				},
			);
			if (labels?.data.Result === 1) {
				log.error(
					{},
					`There was an error printing the label: ${labels.data.Message}`,
				);
				return {
					success: false,
					message: `${labels.data.Message}`,
				};
			} else {
				if (!labels?.success) {
					log.error(
						{ error: labels?.data },
						`There was an error printing the label`,
					);
					return {
						success: false,
						message: `${labels?.message}`,
						data: labels?.data,
					};
				}
				labelsPrinted.push(parseInt(labels?.data.SSCC.slice(10, -1)));
				// add the label to our label db for tracking purposes
				await addProdLabel(
					preprint,
					parseInt(labels?.data.SSCC.slice(10, -1)),
					username || "lst",
					log,
				);
				log.info(
					{},
					`Label just created ${parseInt(labels?.data.SSCC.slice(10, -1))} and printed, remaining to print ${preprint.qtyToPrint - x}`,
				);
			}
			await delay(250);
			x++;
		} while (x < preprint.qtyToPrint);

		return {
			success: true,
			message: `${preprint.qtyToPrint} were just printed`,
			data: labelsPrinted,
		};
	} else {
		const labels = await prodEndpoint(
			"POST",
			"/public/v1.0/Warehousing/GenerateAndPrintLabel",
			{
				scannerId: preprint.scannerId.toString(),
				lotNr: preprint.lotNr.toString(),
				machineId: preprint.machineId.toString(),
				printerId: preprint.printerId.toString(),
				layoutId: preprint.layoutId.toString(),
				numberOfCopies: preprint.numberOfCopies.toString(),
			},
		);

		if (labels?.data.Result === 1) {
			log.error(
				{},
				`There was an error printing the label: ${labels.data.Message}`,
			);
			return {
				success: false,
				message: `${labels.data.Message}`,
			};
		} else {
			if (!labels?.success) {
				log.error(
					{ error: labels?.data },
					`There was an error printing the label`,
				);
				return {
					success: false,
					message: `${labels?.message}`,
					data: labels?.data,
				};
			}

			labelsPrinted.push(parseInt(labels.data.SSCC.slice(10, -1)));
			await addProdLabel(
				preprint,
				parseInt(labels?.data.SSCC.slice(10, -1)),
				username || "lst",
				log,
			);
			log.info(
				{},
				`Label just created ${parseInt(labels.data.SSCC.slice(10, -1))} and printed`,
			);

			return {
				success: true,
				message: `${preprint.qtyToPrint} were just printed.`,
				data: labelsPrinted,
			};
		}
	}
};
