import { renderExercise } from "@/components/Exercises";
import ModuleTitle from "@/components/Medium/ModuleTitle";
import { renderSolution } from "@/components/Solutions";
import { UserSolution, SpeakingExam, SpeakingExercise, InteractiveSpeakingExercise, Exercise } from "@/interfaces/exam";
import useExamStore, { usePersistentExamStore } from "@/stores/exam";
import { countExercises } from "@/utils/moduleUtils";
import { convertCamelCaseToReadable } from "@/utils/string";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import PartDivider from "./Navigation/SectionDivider";
import { ExamProps } from "./types";
import useExamTimer from "@/hooks/useExamTimer";
import useExamNavigation from "./Navigation/useExamNavigation";
import ProgressButtons from "./components/ProgressButtons";
import { calculateExerciseIndexSpeaking } from "./utils/calculateExerciseIndex";
import SectionNavbar from "./Navigation/SectionNavbar";


const Speaking: React.FC<ExamProps<SpeakingExam>> = ({ exam, showSolutions = false, preview = false }) => {
	const updateTimers = useExamTimer(exam.module, preview || showSolutions);
	const userSolutionRef = useRef<(() => UserSolution) | null>(null);
	const [solutionWasUpdated, setSolutionWasUpdated] = useState(false);

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

	const {
		exerciseIndex, userSolutions, flags,
		timeSpentCurrentModule, questionIndex,
		setBgColor, setUserSolutions, setTimeIsUp,
		dispatch,
	} = !preview ? examState : persistentExamState;

	const { finalizeModule, timeIsUp } = flags;

	const timer = useRef(exam.minTimer - timeSpentCurrentModule / 60);

	const {
		nextExercise, previousExercise,
		showPartDivider, setShowPartDivider,
		setSeenParts, seenParts, setIsBetweenParts
	} = useExamNavigation({ exam, module: "speaking", showSolutions, preview, disableBetweenParts: true });

	useEffect(() => {
		if (finalizeModule || timeIsUp) {
			updateTimers();

			if (timeIsUp) {
				setTimeIsUp(false);
			}
			dispatch({ type: "FINALIZE_MODULE", payload: { updateTimers: false } })
		}
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [finalizeModule, timeIsUp])


	const registerSolution = useCallback((updateSolution: () => UserSolution) => {
		userSolutionRef.current = updateSolution;
		setSolutionWasUpdated(true);
	}, []);

	useEffect(() => {
		if (solutionWasUpdated && userSolutionRef.current) {
			const solution = userSolutionRef.current();
			setUserSolutions([...userSolutions.filter((x) => x.exercise !== solution.exercise), { ...solution, module: "speaking", exam: exam.id }]);
			setSolutionWasUpdated(false);
		}
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [solutionWasUpdated])


	const currentExercise = useMemo<Exercise>(() => {
		const exercise = exam.exercises[exerciseIndex];
		return {
			...exercise,
			variant: exerciseIndex < 2 && exercise.type === "interactiveSpeaking" ? "initial" : undefined,
			userSolutions: userSolutions.find((x) => x.exercise === exercise.id)?.solutions || [],
		} as SpeakingExercise | InteractiveSpeakingExercise;
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [exerciseIndex]);


	const progressButtons = useMemo(() =>
		// Do not remove the ()=> in handle next
		<ProgressButtons handlePrevious={previousExercise} handleNext={() => nextExercise()} />
		, [nextExercise, previousExercise]);


	const handlePartDividerClick = () => {
		setShowPartDivider(false);
		setBgColor("bg-white");
		setSeenParts((prev) => new Set(prev).add(exerciseIndex));
	}

	const memoizedExerciseIndex = useMemo(() =>
		calculateExerciseIndexSpeaking(exam, exerciseIndex, questionIndex)
		// eslint-disable-next-line react-hooks/exhaustive-deps
		, [exerciseIndex, questionIndex]
	);


	return (
		<>
			{(showPartDivider) ?
				<PartDivider
					module="speaking"
					sectionLabel="Speaking"
					defaultTitle="Speaking exam"
					section={exam.exercises[exerciseIndex]}
					sectionIndex={exerciseIndex}
					onNext={handlePartDividerClick}
				/> : (
					<>
						{exam.exercises.length > 1 && <SectionNavbar
							module="speaking"
							sectionLabel="Part"
							seenParts={seenParts}
							setShowPartDivider={setShowPartDivider}
							setSeenParts={setSeenParts}
							preview={preview}
						/>}
						<div className="flex flex-col h-full w-full gap-8 items-center">
							<ModuleTitle
								label={convertCamelCaseToReadable(exam.exercises[exerciseIndex].type)}
								minTimer={timer.current}
								exerciseIndex={memoizedExerciseIndex}
								module="speaking"
								totalExercises={countExercises(exam.exercises)}
								disableTimer={showSolutions || preview}
								preview={preview}
							/>
							{!showPartDivider && !showSolutions && renderExercise(currentExercise, exam.id, registerSolution, preview, progressButtons, progressButtons)}
							{showSolutions && renderSolution(currentExercise, progressButtons, progressButtons)}
						</div>
					</>
				)}
		</>
	);
}

export default Speaking;
