/* eslint-disable @next/next/no-img-element */
import Head from "next/head";
import { withIronSessionSsr } from "iron-session/next";
import { sessionOptions } from "@/lib/session";
import { toast, ToastContainer } from "react-toastify";
import Layout from "@/components/High/Layout";
import { shouldRedirectHome } from "@/utils/navigation.disabled";
import { Radio, RadioGroup } from "@headlessui/react";
import clsx from "clsx";
import { MODULE_ARRAY } from "@/utils/moduleUtils";
import { capitalize } from "lodash";
import Input from "@/components/Low/Input";
import { checkAccess, findAllowedEntities } from "@/utils/permissions";
import { User } from "@/interfaces/user";
import useExamEditorStore from "@/stores/examEditor";
import ExamEditorStore from "@/stores/examEditor/types";
import ExamEditor from "@/components/ExamEditor";
import MultipleAudioUploader from "@/components/ExamEditor/Shared/AudioEdit";
import { mapBy, redirect, serialize } from "@/utils";
import { requestUser } from "@/utils/api";
import { Module } from "@/interfaces";
import { getExam, getExams } from "@/utils/exams.be";
import { Exam, Exercise, InteractiveSpeakingExercise, ListeningPart, SpeakingExercise } from "@/interfaces/exam";
import { useEffect, useState } from "react";
import { getEntitiesWithRoles } from "@/utils/entities.be";
import { isAdmin } from "@/utils/users";
import axios from "axios";

type Permission = { [key in Module]: boolean }

export const getServerSideProps = withIronSessionSsr(async ({ req, res, query }) => {
	const user = await requestUser(req, res)
	if (!user) return redirect("/login")

	if (shouldRedirectHome(user)) return redirect("/")

	const entityIDs = mapBy(user.entities, 'id')
	const entities = await getEntitiesWithRoles(isAdmin(user) ? undefined : entityIDs)

	const permissions: Permission = {
		reading: findAllowedEntities(user, entities, `generate_reading`).length > 0,
		listening: findAllowedEntities(user, entities, `generate_listening`).length > 0,
		writing: findAllowedEntities(user, entities, `generate_writing`).length > 0,
		speaking: findAllowedEntities(user, entities, `generate_speaking`).length > 0,
		level: findAllowedEntities(user, entities, `generate_level`).length > 0,
	}

	if (Object.keys(permissions).every(p => !permissions[p as Module])) return redirect("/")

	const { id, module: examModule } = query as { id?: string, module?: Module }
	if (!id || !examModule) return { props: serialize({ user, permissions }) };

	//if (!permissions[module]) return redirect("/generation")

	const exam = await getExam(examModule, id)
	if (!exam) return redirect("/generation")

	return {
		props: serialize({ id, user, exam, examModule, permissions }),
	};
}, sessionOptions);

export default function Generation({ id, user, exam, examModule, permissions }: { id: string, user: User; exam?: Exam, examModule?: Module, permissions: Permission }) {
	const { title, currentModule, modules, dispatch } = useExamEditorStore();
	const [examLevelParts, setExamLevelParts] = useState<number | undefined>(undefined);

	const updateRoot = (updates: Partial<ExamEditorStore>) => {
		dispatch({ type: 'UPDATE_ROOT', payload: { updates } });
	};

	useEffect(() => {
		if (id && exam && examModule) {
			if (examModule === "level" && exam.module === "level") {
				setExamLevelParts(exam.parts.length);
			}
			updateRoot({currentModule: examModule})
			dispatch({ type: "INIT_EXAM_EDIT", payload: { exam, id, examModule } })
		}
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [id, exam, module])

	useEffect(() => {
		const fetchAvatars = async () => {
			const response = await axios.get("/api/exam/avatars");
			updateRoot({ speakingAvatars: response.data });
		};

		fetchAvatars();
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, []);

	// media cleanup on unmount
	useEffect(() => {
		return () => {
			const state = modules;

			if (state.writing.academic_url) {
				URL.revokeObjectURL(state.writing.academic_url);
			}

			state.listening.sections.forEach(section => {
				const listeningPart = section.state as ListeningPart;
				if (listeningPart.audio?.source) {
					URL.revokeObjectURL(listeningPart.audio.source);
					dispatch({
						type: "UPDATE_SECTION_SINGLE_FIELD", payload: {
							sectionId: section.sectionId, module: "listening", field: "state", value: { ...listeningPart, audio: undefined }
						}
					})
				}
			});

			state.speaking.sections.forEach(section => {
				const sectionState = section.state as Exercise;
				if (sectionState.type === 'speaking') {
					const speakingExercise = sectionState as SpeakingExercise;
					URL.revokeObjectURL(speakingExercise.video_url);
					dispatch({
						type: "UPDATE_SECTION_SINGLE_FIELD", payload: {
							sectionId: section.sectionId, module: "listening", field: "state", value: { ...speakingExercise, video_url: undefined }
						}
					})
				}
				if (sectionState.type === 'interactiveSpeaking') {
					const interactiveSpeaking = sectionState as InteractiveSpeakingExercise;
					interactiveSpeaking.prompts.forEach(prompt => {
						URL.revokeObjectURL(prompt.video_url);
					});
					dispatch({
						type: "UPDATE_SECTION_SINGLE_FIELD", payload: {
							sectionId: section.sectionId, module: "listening", field: "state", value: {
								...interactiveSpeaking, prompts: interactiveSpeaking.prompts.map((p) => ({ ...p, video_url: undefined }))
							}
						}
					})
				}
			});
			dispatch({ type: 'FULL_RESET' });
		};
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, []);

	return (
		<>
			<Head>
				<title>Exam Generation | EnCoach</title>
				<meta
					name="description"
					content="A training platform for the IELTS exam provided by the Muscat Training Institute and developed by eCrop."
				/>
				<meta name="viewport" content="width=device-width, initial-scale=1" />
				<link rel="icon" href="/favicon.ico" />
			</Head>
			<ToastContainer />
			{user && (
				<Layout user={user} className="gap-6">
					<h1 className="text-2xl font-semibold">Exam Editor</h1>
					<div className="flex flex-col gap-3">
						<Input
							type="text"
							placeholder="Insert a title here"
							name="title"
							label="Title"
							onChange={(title) => updateRoot({ title })}
							roundness="xl"
							value={title}
							defaultValue={title}
							required
						/>
						{/*<MultipleAudioUploader />*/}
						<label className="font-normal text-base text-mti-gray-dim">Module</label>
						<RadioGroup
							value={currentModule}
							onChange={(currentModule) => updateRoot({ currentModule })}
							className="flex flex-row -2xl:flex-wrap w-full gap-4 -md:justify-center justify-between">
							{[...MODULE_ARRAY].filter(m => permissions[m]).map((x) => (
								<Radio value={x} key={x}>
									{({ checked }) => (
										<span
											className={clsx(
												"px-6 py-4 w-64 h-[72px] flex justify-center items-center text-sm font-normal rounded-full border focus:outline-none cursor-pointer",
												"transition duration-300 ease-in-out",
												x === "reading" &&
												(!checked
													? "bg-white border-mti-gray-platinum"
													: "bg-ielts-reading/70 border-ielts-reading text-white"),
												x === "listening" &&
												(!checked
													? "bg-white border-mti-gray-platinum"
													: "bg-ielts-listening/70 border-ielts-listening text-white"),
												x === "writing" &&
												(!checked
													? "bg-white border-mti-gray-platinum"
													: "bg-ielts-writing/70 border-ielts-writing text-white"),
												x === "speaking" &&
												(!checked
													? "bg-white border-mti-gray-platinum"
													: "bg-ielts-speaking/70 border-ielts-speaking text-white"),
												x === "level" &&
												(!checked
													? "bg-white border-mti-gray-platinum"
													: "bg-ielts-level/70 border-ielts-level text-white"),
											)}>
											{capitalize(x)}
										</span>
									)}
								</Radio>
							))}
						</RadioGroup>
					</div>
					<ExamEditor levelParts={examLevelParts} />
				</Layout>
			)}
		</>
	);
}
