import { renderExercise } from "@/components/Exercises";
import ModuleTitle from "@/components/Medium/ModuleTitle";
import { renderSolution } from "@/components/Solutions";
import { UserSolution, WritingExam } from "@/interfaces/exam";
import useExamStore, { usePersistentExamStore } from "@/stores/examStore";
import { countExercises } from "@/utils/moduleUtils";
import PartDivider from "./Navigation/SectionDivider";
import { useEffect, useState } from "react";

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

export default function Writing({ exam, showSolutions = false, preview = false, onFinish }: Props) {
	const writingBgColor = "bg-ielts-writing-light";

	const examState = useExamStore((state) => state);
	const persistentExamState = usePersistentExamStore((state) => state);

	const {
		userSolutions,
		exerciseIndex,
		hasExamEnded,
		setBgColor,
		setUserSolutions,
		setHasExamEnded,
		setExerciseIndex,
	} = !preview ? examState : persistentExamState;

	const [seenParts, setSeenParts] = useState<Set<number>>(new Set(showSolutions ? exam.exercises.map((_, index) => index) : []));
	const [showPartDivider, setShowPartDivider] = useState<boolean>(typeof exam.exercises[0].intro === "string" && exam.exercises[0].intro !== "");

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

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

	useEffect(() => {
		if (!showSolutions && exam.exercises[exerciseIndex]?.intro !== undefined && exam.exercises[exerciseIndex]?.intro !== "" && !seenParts.has(exerciseIndex)) {
			setShowPartDivider(true);
			setBgColor(writingBgColor);
		}
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [exerciseIndex]);


	const nextExercise = (solution?: UserSolution) => {
		scrollToTop();
		if (solution) {
			setUserSolutions([...userSolutions.filter((x) => x.exercise !== solution.exercise), { ...solution, module: "writing", exam: exam.id }]);
		}

		if (exerciseIndex + 1 < exam.exercises.length) {
			setExerciseIndex(exerciseIndex + 1);
			return;
		}

		if (exerciseIndex >= exam.exercises.length) return;

		setHasExamEnded(false);

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

	const previousExercise = (solution?: UserSolution) => {
		scrollToTop();
		if (solution) {
			setUserSolutions([...userSolutions.filter((x) => x.exercise !== solution.exercise), { ...solution, module: "writing", exam: exam.id }]);
		}

		if (exerciseIndex > 0) {
			setExerciseIndex(exerciseIndex - 1);
		}
	};

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

	return (
		<>
			{(showPartDivider) ?
				<PartDivider
					module="writing"
					sectionLabel="Task"
					defaultTitle="Writing exam"
					section={exam.exercises[exerciseIndex]}
					sectionIndex={exerciseIndex}
					onNext={() => { setShowPartDivider(false); setBgColor("bg-white"); setSeenParts((prev) => new Set(prev).add(exerciseIndex))}}
				/> : (
					<div className="flex flex-col h-full w-full gap-8 items-center">
						<ModuleTitle
							minTimer={exam.minTimer}
							exerciseIndex={exerciseIndex + 1}
							module="writing"
							totalExercises={countExercises(exam.exercises)}
							disableTimer={showSolutions || preview}
						/>
						{exerciseIndex > -1 &&
							exerciseIndex < exam.exercises.length &&
							!showSolutions &&
							renderExercise(getExercise(), exam.id, nextExercise, previousExercise, preview)}
						{exerciseIndex > -1 &&
							exerciseIndex < exam.exercises.length &&
							showSolutions &&
							renderSolution(exam.exercises[exerciseIndex], nextExercise, previousExercise)}
					</div>
				)
			}
		</>
	);
}
