import { eq } from "drizzle-orm";
import { db } from "../db/db.controller.js";
import { notifications } from "../db/schema/notifications.schema.js";
import { notificationSub } from "../db/schema/notifications.sub.schema.js";
import { createLogger } from "../logger/logger.controller.js";
import { minutesToCron } from "../utils/croner.minConvert.js";
import { createCronJob, stopCronJob } from "../utils/croner.utils.js";
import { tryCatch } from "../utils/trycatch.utils.js";

const log = createLogger({ module: "notifications", subModule: "start" });

export const startNotifications = async () => {
	// get active notification

	const { data, error } = await tryCatch(
		db.select().from(notifications).where(eq(notifications.active, true)),
	);

	if (error) {
		log.error(
			{ error: error },
			"There was an error when getting notifications.",
		);
		return;
	}

	if (data) {
		if (data.length === 0) {
			log.info(
				{},
				"There are know currently active notifications to start up.",
			);
			return;
		}

		// get the subs and see if we have any subs currently so we can fire up the notification
		const { data: sub, error: subError } = await tryCatch(
			db.select().from(notificationSub),
		);

		if (subError) {
			log.error(
				{ error: error },
				"There was an error when getting subscriptions.",
			);
			return;
		}

		if (sub.length === 0) {
			log.info({}, "There are know currently active subscriptions.");
			return;
		}

		const emailString = [
			...new Set(
				sub.flatMap((e) =>
					e.emails?.map((email) => email.trim().toLowerCase()),
				),
			),
		].join(";");

		for (const n of data) {
			createCronJob(
				n.name,
				minutesToCron(parseInt(n.interval ?? "15", 10)),
				async () => {
					try {
						const { default: runFun } = await import(
							`./notification.${n.name.trim()}.js`
						);
						await runFun(n, emailString);
					} catch (error) {
						log.error(
							{ error: error },
							"There was an error starting the notification",
						);
					}
				},
			);
		}
	}
};

export const modifiedNotification = async (id: string) => {
	// when a notifications subscribed to, updated, deleted we want to get the info and rerun the startup on the single notification.
	const { data, error } = await tryCatch(
		db.select().from(notifications).where(eq(notifications.id, id)),
	);

	if (error) {
		log.error(
			{ error: error },
			"There was an error when getting notifications.",
		);
		return;
	}

	if (data) {
		if (!data[0]?.active) {
			stopCronJob(data[0]?.name ?? "");
			return;
		}

		// get the subs for the specific id as we only want to up the modified one
		const { data: sub, error: subError } = await tryCatch(
			db
				.select()
				.from(notificationSub)
				.where(eq(notificationSub.notificationId, id)),
		);

		if (subError) {
			log.error(
				{ error: error },
				"There was an error when getting subscriptions.",
			);

			return;
		}

		if (sub.length === 0) {
			log.info({}, "There are know currently active subscriptions.");
			stopCronJob(data[0]?.name ?? "");
			return;
		}

		const emailString = [
			...new Set(
				sub.flatMap((e) =>
					e.emails?.map((email) => email.trim().toLowerCase()),
				),
			),
		].join(";");

		createCronJob(
			data[0].name,
			minutesToCron(parseInt(data[0].interval ?? "15", 10)),
			async () => {
				try {
					const { default: runFun } = await import(
						`./notification.${data[0]?.name.trim()}.js`
					);
					await runFun(data[0], emailString);
				} catch (error) {
					log.error(
						{ error: error },
						"There was an error starting the notification",
					);
				}
			},
		);
	}
};
