import { getMoodleCourseCompletionStatus, getMoodleUserById } from "./moodle";
import { CronJob } from "cron";
import { DISCORD_ROLES, prisma } from "@repo/db";
import { sendCourseCompletedEmail } from "modules/mail";
import { handleParticipantFinished } from "modules/event";
import { eventCompleted } from "helper/events";
import { addRolesToMember, removeRolesFromMember } from "modules/discord";

const syncMoodleIds = async () => {
	try {
		const user = await prisma.user.findMany({
			where: {
				moodleId: null,
			},
		});

		await Promise.all(
			user.map(async (u) => {
				const moodleUser = await getMoodleUserById(u.id.toString());
				const moodleId = moodleUser?.id.toString();
				if (u.moodleId === parseInt(moodleId)) return;
				await prisma.user.update({
					where: {
						id: u.id,
					},
					data: {
						moodleId: parseInt(moodleId),
					},
				});
			}),
		);
	} catch (error) {
		console.error(error);
	}
};

const updateParticipantMoodleResults = async () => {
	const participantsMoodlePending = await prisma.participant.findMany({
		where: {
			finisherMoodleCurseCompleted: false,
			Event: {
				finisherMoodleCourseId: {
					not: null,
				},
			},
		},
		include: {
			Event: true,
			User: true,
		},
	});
	await Promise.all(
		participantsMoodlePending.map(async (p) => {
			if (!p.User) return;
			if (!p.User.moodleId) return;

			const quizzResult = await getMoodleCourseCompletionStatus(
				p.User.moodleId.toString(),
				p.Event.finisherMoodleCourseId!,
			);

			if (quizzResult?.completionstatus?.completed === true) {
				return prisma.participant.update({
					where: {
						id: p.id,
					},
					data: {
						finisherMoodleCurseCompleted: true,
						statusLog: {
							push: {
								event: "Moodle-Kurs abgeschlossen",
								timestamp: new Date(),
								user: "system",
							},
						},
					},
				});
			}
		}),
	);
};

export const checkFinishedParticipants = async () => {
	const participantsPending = await prisma.participant.findMany({
		where: {
			completetionWorkflowFinished: false,
		},
		include: {
			Event: true,
			User: true,
		},
	});
	participantsPending.forEach(async (p) => {
		if (!p.User) return;
		const completed = eventCompleted(p.Event, p);

		if (!completed) return;
		console.log(
			`User ${p.User.firstname} ${p.User.lastname} - ${p.User.publicId} finished event ${p.Event.name}`,
		);
		handleParticipantFinished(p.Event, p, p.User);
	});
};

const checkUnfinishedParticipants = async () => {
	const participantsPending = await prisma.participant.findMany({
		where: {
			completetionWorkflowFinished: false,
		},
		include: {
			Event: true,
			User: {
				include: {
					discordAccounts: true,
				},
			},
		},
	});
	participantsPending.forEach(async (p) => {
		if (!p.User) return;
		const completed = eventCompleted(p.Event, p);

		if (completed) return;

		if (p.User.discordAccounts[0] && p.Event.discordRoleId) {
			await addRolesToMember(p.User.discordAccounts[0].discordId, [p.Event.discordRoleId]);
			prisma.participant.update({
				where: {
					id: p.id,
				},
				data: {
					inscriptionWorkflowCompleted: true,
					statusLog: {
						push: {
							event: "Discord-Rolle hinzugefügt",
							timestamp: new Date(),
							user: "system",
						},
					},
				},
			});
		}
	});
};

const checkDiscordRoles = async () => {
	const user = await prisma.user.findMany({
		where: {
			discordAccounts: {
				some: {},
			},
		},
		include: {
			discordAccounts: true,
		},
	});

	for (const u of user) {
		// Here ony member Roles regarding their rights are checked
		if (!u.discordAccounts[0]) continue;
		const discordAccount = u.discordAccounts[0];

		// For Pilot
		if (u.permissions.includes("PILOT")) {
			await addRolesToMember(discordAccount.discordId, [DISCORD_ROLES.PILOT]); // ONLINE_PILOT
		} else {
			await removeRolesFromMember(discordAccount.discordId, [DISCORD_ROLES.PILOT]); // ONLINE_PILOT
		}
		// for Dispatcher
		if (u.permissions.includes("DISPO")) {
			await addRolesToMember(discordAccount.discordId, [DISCORD_ROLES.DISPATCHER]); // ONLINE_DISPATCHER
		} else {
			await removeRolesFromMember(discordAccount.discordId, [DISCORD_ROLES.DISPATCHER]); // ONLINE_DISPATCHER
		}
	}
};

CronJob.from({ cronTime: "0 * * * *", onTick: syncMoodleIds, start: true });
CronJob.from({
	cronTime: "*/1 * * * *",
	onTick: async () => {
		await updateParticipantMoodleResults();
		await checkFinishedParticipants();
		await checkUnfinishedParticipants();
	},
	start: true,
});
CronJob.from({
	cronTime: "0 * * * *",
	onTick: checkDiscordRoles,
	start: true,
});
