import {ReadingExam, UserSolution} from "@/interfaces/exam";
import {Fragment, useEffect, useState} from "react";
import Icon from "@mdi/react";
import {mdiArrowRight, mdiNotebook} from "@mdi/js";
import clsx from "clsx";
import {infoButtonStyle} from "@/constants/buttonStyles";
import {convertCamelCaseToReadable} from "@/utils/string";
import {Dialog, Transition} from "@headlessui/react";
import {renderExercise} from "@/components/Exercises";
import {renderSolution} from "@/components/Solutions";
import {Panel} from "primereact/panel";
import {Steps} from "primereact/steps";
import {BsAlarm, BsBook, BsClock, BsStopwatch} from "react-icons/bs";
import ProgressBar from "@/components/Low/ProgressBar";
import ModuleTitle from "@/components/Medium/ModuleTitle";
import {Divider} from "primereact/divider";
import Button from "@/components/Low/Button";
import BlankQuestionsModal from "@/components/BlankQuestionsModal";
import useExamStore from "@/stores/examStore";
import {defaultUserSolutions} from "@/utils/exams";
import {countExercises} from "@/utils/moduleUtils";

interface Props {
	exam: ReadingExam;
	showSolutions?: boolean;
	onFinish: (userSolutions: UserSolution[]) => void;
}

function TextModal({isOpen, title, content, onClose}: {isOpen: boolean; title: string; content: string; onClose: () => void}) {
	return (
		<Transition appear show={isOpen} as={Fragment}>
			<Dialog as="div" className="relative z-10" onClose={onClose}>
				<Transition.Child
					as={Fragment}
					enter="ease-out duration-300"
					enterFrom="opacity-0"
					enterTo="opacity-100"
					leave="ease-in duration-200"
					leaveFrom="opacity-100"
					leaveTo="opacity-0">
					<div className="fixed inset-0 bg-black bg-opacity-25" />
				</Transition.Child>

				<div className="fixed inset-0 overflow-y-auto">
					<div className="flex min-h-full items-center justify-center p-4 text-center">
						<Transition.Child
							as={Fragment}
							enter="ease-out duration-300"
							enterFrom="opacity-0 scale-95"
							enterTo="opacity-100 scale-100"
							leave="ease-in duration-200"
							leaveFrom="opacity-100 scale-100"
							leaveTo="opacity-0 scale-95">
							<Dialog.Panel className="w-full relative max-w-4xl transform rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all">
								<Dialog.Title as="h3" className="text-lg font-medium leading-6 text-gray-900">
									{title}
								</Dialog.Title>
								<div className="mt-2 overflow-auto mb-28">
									<p className="text-sm">
										{content.split("\\n").map((line, index) => (
											<Fragment key={index}>
												{line}
												<br />
											</Fragment>
										))}
									</p>
								</div>

								<div className="absolute bottom-8 right-8 max-w-[200px] self-end w-full">
									<Button color="purple" variant="outline" className="max-w-[200px] self-end w-full" onClick={onClose}>
										Close
									</Button>
								</div>
							</Dialog.Panel>
						</Transition.Child>
					</div>
				</div>
			</Dialog>
		</Transition>
	);
}

export default function Reading({exam, showSolutions = false, onFinish}: Props) {
	const [questionIndex, setQuestionIndex] = useState(0);
	const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
	const [exerciseIndex, setExerciseIndex] = useState(showSolutions ? 0 : -1);
	const [partIndex, setPartIndex] = useState(0);
	const [showTextModal, setShowTextModal] = useState(false);
	const [userSolutions, setUserSolutions] = useState<UserSolution[]>(
		exam.parts.flatMap((x) => x.exercises).map((x) => defaultUserSolutions(x, exam)),
	);
	const [showBlankModal, setShowBlankModal] = useState(false);

	const [hasExamEnded, setHasExamEnded] = useExamStore((state) => [state.hasExamEnded, state.setHasExamEnded]);

	const scrollToTop = () => Array.from(document.getElementsByTagName("body")).forEach((body) => body.scrollTo(0, 0));

	useEffect(() => {
		const listener = (e: KeyboardEvent) => {
			if (e.key === "F3" || ((e.ctrlKey || e.metaKey) && e.key === "f")) {
				e.preventDefault();
			}
		};

		document.addEventListener("keydown", listener);

		return () => {
			document.removeEventListener("keydown", listener);
		};
	}, []);

	useEffect(() => {
		setCurrentQuestionIndex(0);
	}, [questionIndex]);

	useEffect(() => {
		if (hasExamEnded && exerciseIndex === -1) {
			setExerciseIndex((prev) => prev + 1);
		}
	}, [hasExamEnded, exerciseIndex]);

	const confirmFinishModule = (keepGoing?: boolean) => {
		if (!keepGoing) {
			setShowBlankModal(false);
			return;
		}

		onFinish(userSolutions.map((x) => ({...x, module: "reading", exam: exam.id})));
	};

	const nextExercise = (solution?: UserSolution) => {
		scrollToTop();
		if (solution) {
			setUserSolutions((prev) => [...prev.filter((x) => x.exercise !== solution.exercise), solution]);
		}
		setQuestionIndex((prev) => prev + currentQuestionIndex);

		if (exerciseIndex + 1 < exam.parts[partIndex].exercises.length && !hasExamEnded) {
			setExerciseIndex((prev) => prev + 1);
			return;
		}

		if (partIndex + 1 < exam.parts.length && !hasExamEnded) {
			setPartIndex((prev) => prev + 1);
			setExerciseIndex(showSolutions ? 0 : -1);
			return;
		}

		if (
			solution &&
			![...userSolutions.filter((x) => x.exercise !== solution?.exercise).map((x) => x.score.missing), solution?.score.missing].every(
				(x) => x === 0,
			) &&
			!showSolutions &&
			!hasExamEnded
		) {
			setShowBlankModal(true);
			return;
		}

		setHasExamEnded(false);

		if (solution) {
			onFinish(
				[...userSolutions.filter((x) => x.exercise !== solution.exercise), solution].map((x) => ({...x, module: "reading", exam: exam.id})),
			);
		} else {
			onFinish(userSolutions.map((x) => ({...x, module: "reading", exam: exam.id})));
		}
	};

	const previousExercise = (solution?: UserSolution) => {
		scrollToTop();
		if (solution) {
			setUserSolutions((prev) => [...prev.filter((x) => x.exercise !== solution.exercise), solution]);
		}

		setExerciseIndex((prev) => prev - 1);
	};

	const getExercise = () => {
		const exercise = exam.parts[partIndex].exercises[exerciseIndex];
		return {
			...exercise,
			userSolutions: userSolutions.find((x) => x.exercise === exercise.id)?.solutions || [],
		};
	};

	const renderText = () => (
		<div className="flex flex-col gap-6 w-full bg-mti-gray-seasalt rounded-xl py-8 px-16 mt-4">
			<div className="flex flex-col w-full gap-2">
				<h4 className="text-xl font-semibold">
					Please read the following excerpt attentively, you will then be asked questions about the text you&apos;ve read.
				</h4>
				<span className="text-base">You will be allowed to read the text while doing the exercises</span>
			</div>
			<div className="flex flex-col gap-2 w-full">
				<h3 className="text-xl font-semibold">{exam.parts[partIndex].text.title}</h3>
				<div className="border border-mti-gray-dim w-full rounded-full opacity-10" />
				<span className="overflow-auto">
					{exam.parts[partIndex].text.content.split("\\n").map((line, index) => (
						<p key={index}>{line}</p>
					))}
				</span>
			</div>
		</div>
	);

	return (
		<>
			<div className="flex flex-col h-full w-full gap-8">
				<BlankQuestionsModal isOpen={showBlankModal} onClose={confirmFinishModule} />
				<TextModal {...exam.parts[partIndex].text} isOpen={showTextModal} onClose={() => setShowTextModal(false)} />
				<ModuleTitle
					minTimer={exam.minTimer}
					exerciseIndex={
						(exam.parts
							.flatMap((x) => x.exercises)
							.findIndex(
								(x) => x.id === exam.parts[partIndex].exercises[exerciseIndex === -1 ? exerciseIndex + 1 : exerciseIndex]?.id,
							) || 0) +
						(exerciseIndex === -1 ? 0 : 1) +
						questionIndex +
						currentQuestionIndex
					}
					module="reading"
					totalExercises={countExercises(exam.parts.flatMap((x) => x.exercises))}
					disableTimer={showSolutions}
					label={exerciseIndex === -1 ? undefined : convertCamelCaseToReadable(exam.parts[partIndex].exercises[exerciseIndex].type)}
				/>
				<div className={clsx("mb-20 w-full", exerciseIndex > -1 && "grid grid-cols-2 gap-4")}>
					{renderText()}
					{exerciseIndex > -1 &&
						exerciseIndex < exam.parts[partIndex].exercises.length &&
						!showSolutions &&
						renderExercise(getExercise(), nextExercise, previousExercise, setCurrentQuestionIndex)}
					{exerciseIndex > -1 &&
						exerciseIndex < exam.parts[partIndex].exercises.length &&
						showSolutions &&
						renderSolution(exam.parts[partIndex].exercises[exerciseIndex], nextExercise, previousExercise, setCurrentQuestionIndex)}
				</div>
				{exerciseIndex > -1 && exerciseIndex < exam.parts[partIndex].exercises.length && (
					<Button
						color="purple"
						variant="outline"
						onClick={() => setShowTextModal(true)}
						className="max-w-[200px] self-end w-full absolute bottom-[31px] right-64">
						Read text
					</Button>
				)}
			</div>
			{exerciseIndex === -1 && partIndex > 0 && (
				<div className="self-end flex justify-between w-full gap-8 absolute bottom-8 left-0 px-8">
					<Button
						color="purple"
						variant="outline"
						onClick={() => {
							setExerciseIndex(exam.parts[partIndex - 1].exercises.length - 1);
							setPartIndex((prev) => prev - 1);
						}}
						className="max-w-[200px] w-full">
						Back
					</Button>

					<Button color="purple" onClick={() => nextExercise()} className="max-w-[200px] self-end w-full">
						Next
					</Button>
				</div>
			)}
			{exerciseIndex === -1 && partIndex === 0 && (
				<Button color="purple" onClick={() => nextExercise()} className="max-w-[200px] self-end w-full">
					Start now
				</Button>
			)}
		</>
	);
}
