import { format } from "date-fns";
import { eq, sql } from "drizzle-orm";
import { runDatamartQuery } from "../datamart/datamart.controller.js";
import { db } from "../db/db.controller.js";
import { invHistoricalData } from "../db/schema/historicalInv.schema.js";
import { prodQuery } from "../prodSql/prodSqlQuery.controller.js";
import {
	type SqlQuery,
	sqlQuerySelector,
} from "../prodSql/prodSqlQuerySelector.utils.js";
import { createCronJob } from "../utils/croner.utils.js";
import { returnFunc } from "../utils/returnHelper.utils.js";
import { tryCatch } from "../utils/trycatch.utils.js";

type Inventory = {
	article: string;
	alias: string;
	materialType: string;
	total_palletQTY: string;
	available_QTY: string;
	coa_QTY: string;
	held_QTY: string;
	consignment_qty: string;
	lot: string;
	locationId: string;
	laneDescription: string;
	warehouseId: string;
	warehouseDescription: string;
};

const historicalInvImport = async () => {
	const today = new Date();
	const { data, error } = await tryCatch(
		db
			.select()
			.from(invHistoricalData)
			.where(eq(invHistoricalData.histDate, format(today, "yyyy-MM-dd"))),
	);

	if (error) {
		return returnFunc({
			success: false,
			level: "error",
			module: "system",
			subModule: "query",
			message: `Error getting historical inv info`,
			data: error as any,
			notify: false,
		});
	}

	if (data.length === 0) {
		const avSQLQuery = sqlQuerySelector(`datamart.activeArticles`) as SqlQuery;

		if (!avSQLQuery.success) {
			return returnFunc({
				success: false,
				level: "error",
				module: "logistics",
				subModule: "inv",
				message: `Error getting Article info`,
				data: [avSQLQuery.message],
				notify: true,
			});
		}

		const { data: inv, error: invError } = await tryCatch(
			//prodQuery(sqlQuery.query, "Inventory data"),
			runDatamartQuery({
				name: "inventory",
				options: { lots: "x", locations: "x" },
			}),
		);

		const { data: av, error: avError } = (await tryCatch(
			runDatamartQuery({ name: "activeArticles", options: {} }),
		)) as any;

		if (invError) {
			return returnFunc({
				success: false,
				level: "error",
				module: "logistics",
				subModule: "inv",
				message: `Error getting inventory info from prod query`,
				data: invError as any,
				notify: false,
			});
		}

		if (avError) {
			return returnFunc({
				success: false,
				level: "error",
				module: "logistics",
				subModule: "inv",
				message: `Error getting article info from prod query`,
				data: invError as any,
				notify: false,
			});
		}

		// shape the data to go into our table
		const plantToken = process.env.PROD_PLANT_TOKEN ?? "test1";
		const importInv = (inv.data ? inv.data : []) as Inventory[];
		const importData = importInv.map((i) => {
			return {
				histDate: sql`(NOW())::date`,
				plantToken: plantToken,
				article: i.article,
				articleDescription: i.alias,
				materialType:
					av.data.filter((a: any) => a.article === i.article).length > 0
						? av.data.filter((a: any) => a.article === i.article)[0]
								?.TypeOfMaterial
						: "Item not defined",
				total_QTY: i.total_palletQTY ?? "0.00",
				available_QTY: i.available_QTY ?? "0.00",
				coa_QTY: i.coa_QTY ?? "0.00",
				held_QTY: i.held_QTY ?? "0.00",
				consignment_QTY: i.consignment_qty ?? "0.00",
				lot_Number: i.lot ?? "0",
				locationId: i.locationId ?? "0",
				location: i.laneDescription ?? "Missing lane",
				whseId: i.warehouseId ?? "0",
				whseName: i.warehouseDescription ?? "Missing warehouse",
			};
		});

		const { data: dataImport, error: errorImport } = await tryCatch(
			db.insert(invHistoricalData).values(importData),
		);

		if (errorImport) {
			return returnFunc({
				success: false,
				level: "error",
				module: "logistics",
				subModule: "inv",
				message: `Error adding historical data to lst db`,
				data: errorImport as any,
				notify: false,
			});
		}

		if (dataImport) {
			return returnFunc({
				success: false,
				level: "info",
				module: "logistics",
				subModule: "inv",
				message: `Historical data was added to lst :D`,
				data: [],
				notify: false,
			});
		}
	} else {
		return returnFunc({
			success: false,
			level: "info",
			module: "logistics",
			subModule: "inv",
			message: `Historical Data for: ${format(today, "yyyy-MM-dd")}, is already added and nothing to do.`,
			data: [],
			notify: false,
		});
	}

	return returnFunc({
		success: false,
		level: "info",
		module: "logistics",
		subModule: "inv",
		message: `Some weird crazy error just happened and didnt get captured during the historical inv check.`,
		data: [],
		notify: true,
	});
};

export const historicalSchedule = async () => {
	// running the history in case my silly ass dose an update around the shift change time lol, this will prevent loss data. it might be off a little but no one cares
	historicalInvImport();

	const sqlQuery = sqlQuerySelector(`shiftChange`) as SqlQuery;

	if (!sqlQuery.success) {
		return returnFunc({
			success: false,
			level: "error",
			module: "logistics",
			subModule: "query",
			message: `Error getting shiftChange sql file`,
			data: [sqlQuery.message],
			notify: false,
		});
	}

	const { data, error } = await tryCatch(
		prodQuery(sqlQuery.query, "Shift Change data"),
	);

	if (error) {
		return returnFunc({
			success: false,
			level: "error",
			module: "logistics",
			subModule: "query",
			message: `Error getting shiftChange info`,
			data: error as any,
			notify: false,
		});
	}
	// shift split
	const shiftTimeSplit = data?.data[0]?.shiftChange.split(":");

	const cronSetup = `0 ${
		shiftTimeSplit?.length > 0 ? `${parseInt(shiftTimeSplit[1])}` : "0"
	} ${
		shiftTimeSplit?.length > 0 ? `${parseInt(shiftTimeSplit[0])}` : "7"
	} * * *`;

	createCronJob("historicalInv", cronSetup, () => historicalInvImport());
};
