import { ExerciseOnlyExam, ModuleExam, PartExam } from "@/interfaces/exam";
import { useState, useEffect } from "react";
import scrollToTop from "../utils/scrollToTop";
import { Module } from "@/interfaces";
import { answeredEveryQuestion, answeredEveryQuestionInPart } from "../utils/answeredEveryQuestion";
import useExamStore, { usePersistentExamStore } from "@/stores/exam";
import hasDivider from "../utils/hasDivider";

const MC_PER_PAGE = 2;

type UseExamNavigation = (props: {
    exam: ModuleExam;
    module: Module;
    modalKwargs?: () => void;
    showBlankModal?: boolean;
    setShowBlankModal?: React.Dispatch<React.SetStateAction<boolean>>;
    showSolutions: boolean;
    preview: boolean;
    disableBetweenParts?: boolean;
    allPartExercisesRender?: boolean;
    modalBetweenParts?: boolean;
}) => {
    showPartDivider: boolean;
    seenParts: Set<number>;
    isBetweenParts: boolean;
    startNow: boolean;
    nextExercise: (isBetweenParts?: boolean) => void;
    previousExercise: (isBetweenParts?: boolean) => void;
    setShowPartDivider: React.Dispatch<React.SetStateAction<boolean>>;
    setSeenParts: React.Dispatch<React.SetStateAction<Set<number>>>;
    setIsBetweenParts: React.Dispatch<React.SetStateAction<boolean>>;
    setStartNow: React.Dispatch<React.SetStateAction<boolean>>;
};

const useExamNavigation: UseExamNavigation = ({
    exam,
    module,
    setShowBlankModal,
    modalKwargs,
    showSolutions,
    preview,
    disableBetweenParts = false,
    allPartExercisesRender = false,
    modalBetweenParts = false,
}) => {

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

    const {
        exerciseIndex, setExerciseIndex,
        partIndex, setPartIndex,
        questionIndex, setQuestionIndex,
        userSolutions, setBgColor,
        dispatch,
    } = !preview ? examState : persistentExamState;

    const [isBetweenParts, setIsBetweenParts] = useState(module === "reading"
        ? (partIndex !== 0 && exerciseIndex === 0 && !disableBetweenParts)
        : (exerciseIndex === 0 && !disableBetweenParts)
    );
    const isPartExam = ["reading", "listening", "level"].includes(exam.module);

    const [seenParts, setSeenParts] = useState<Set<number>>(
        new Set(showSolutions ?
            (isPartExam ?
                (exam as PartExam).parts.map((_, index) => index) :
                (exam as ExerciseOnlyExam).exercises.map((_, index) => index)
            ) :
            []
        )
    );
    const [showPartDivider, setShowPartDivider] = useState<boolean>(hasDivider(exam, 0));
    const [startNow, setStartNow] = useState(!showPartDivider && !showSolutions);

    // when navbar is used
    useEffect(() => {
        if (startNow && !showPartDivider && partIndex !== 0) {
            setStartNow(false);
        }
    }, [partIndex, startNow, showPartDivider])

    useEffect(() => {
        if (
            (
                module === "level" ?
                    (startNow || hasDivider(exam, isPartExam ? partIndex : exerciseIndex))
                    :
                    (hasDivider(exam, isPartExam ? partIndex : exerciseIndex))
            )
            && !showSolutions && !seenParts.has(partIndex)

        ) {
            if (
                // partIndex === 0 -> startNow
                (module === "level" && (partIndex === 0 || hasDivider(exam, isPartExam ? partIndex : exerciseIndex))) ||
                module !== "level"
            ) {
                setShowPartDivider(true);
            }
            setBgColor(`bg-ielts-${module}-light`);
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [partIndex, startNow]);

    const nextExercise = (keepGoing: boolean = false) => {
        scrollToTop();

        if (isPartExam) {
            nextPartExam(keepGoing);
        } else {
            nextExerciseOnlyExam();
        }
    };

    const previousExercise = () => {
        scrollToTop();

        if (isPartExam) {
            previousPartExam();
        } else {
            previousExerciseOnlyExam();
        }
    };

    const nextPartExam = (keepGoing: boolean) => {
        const partExam = (exam as PartExam);

        if (startNow) {
            setStartNow(false);
            return;
        }

        if (isBetweenParts) {
            setIsBetweenParts(false);
            return;
        }

        if (allPartExercisesRender) {
            if (partIndex < partExam.parts.length - 1) {
                if (!disableBetweenParts) setIsBetweenParts(true);
                setPartIndex(partIndex + 1);
                return;
            }

            if (!answeredEveryQuestion(exam as PartExam, userSolutions) && !keepGoing && setShowBlankModal && !showSolutions && !preview) {
                if (modalKwargs) modalKwargs();
                setShowBlankModal(true);
                return;
            }

            if (preview) {
                setPartIndex(0);
            } else if (!showSolutions) {
                dispatch({ type: "FINALIZE_MODULE", payload: { updateTimers: true } });
            } else {
                dispatch({ type: "FINALIZE_MODULE_SOLUTIONS" });
            }
            return;
        }

        const reachedFinalExercise = exerciseIndex + 1 === partExam.parts[partIndex].exercises.length;
        const currentExercise = partExam.parts[partIndex].exercises[exerciseIndex];

        if (currentExercise.type === "multipleChoice") {
            const nextQuestionIndex = questionIndex + MC_PER_PAGE;
            if (nextQuestionIndex < currentExercise.questions!.length) {
                setQuestionIndex(nextQuestionIndex);
                return;
            }
        }

        if (!reachedFinalExercise) {
            setExerciseIndex(exerciseIndex + 1);
            setQuestionIndex(0);
            return;
        }

        if (modalBetweenParts && !seenParts.has(partIndex + 1) && !answeredEveryQuestionInPart(exam as PartExam, partIndex, userSolutions) && !keepGoing && setShowBlankModal && !showSolutions && !preview) {
            if (modalKwargs) modalKwargs();
            setShowBlankModal(true);
            return;
        }

        if (partIndex < partExam.parts.length - 1) {
            if (!disableBetweenParts) setIsBetweenParts(true);
            setPartIndex(partIndex + 1);
            setExerciseIndex(0);
            setQuestionIndex(0);
            return;
        }


        if (!modalBetweenParts && !answeredEveryQuestion(exam as PartExam, userSolutions) && !keepGoing && setShowBlankModal && !showSolutions && !preview) {
            if (modalKwargs) modalKwargs();
            setShowBlankModal(true);
            return;
        }


        if (preview) {
            setPartIndex(0);
            setExerciseIndex(0);
            setQuestionIndex(0);
        } else if (!showSolutions) {
            dispatch({ type: "FINALIZE_MODULE", payload: { updateTimers: true } });
        } else {
            dispatch({ type: "FINALIZE_MODULE_SOLUTIONS" });
        }
    };

    const previousPartExam = () => {

        if (!showPartDivider && partIndex === 0 && exerciseIndex === 0 && questionIndex === 0 && !startNow) {
            if (module !== "level") setStartNow(true);
            return;
        }

        if (!disableBetweenParts && isBetweenParts) {
            setIsBetweenParts(false);
        }

        if (allPartExercisesRender) {
            if (isBetweenParts && partIndex !== 0) {
                setPartIndex(partIndex - 1);
                setIsBetweenParts(false);
                return;
            }
            if (disableBetweenParts) {
                if (partIndex !== 0) {
                    setPartIndex(partIndex - 1);
                }
            } else {
                setIsBetweenParts(true);
            }
            return;
        }

        const currentExercise = (exam as PartExam).parts[partIndex].exercises[exerciseIndex];
        if (currentExercise.type === "multipleChoice" && questionIndex > 0 && !allPartExercisesRender) {
            setQuestionIndex(Math.max(0, questionIndex - MC_PER_PAGE));
            return;
        }

        if (exerciseIndex !== 0) {
            setExerciseIndex(exerciseIndex - 1);
            setQuestionIndex(0);
        }

        if (partIndex !== 0) {
            setPartIndex(partIndex - 1);
            setExerciseIndex((exam as PartExam).parts[partIndex].exercises.length - 1);
            if (isBetweenParts) setIsBetweenParts(false);
            return;
        }

    };

    const nextExerciseOnlyExam = () => {
        const exerciseOnlyExam = (exam as ExerciseOnlyExam);
        const reachedFinalExercise = exerciseIndex + 1 === exerciseOnlyExam.exercises.length;
        const currentExercise = exerciseOnlyExam.exercises[exerciseIndex];

        if (currentExercise.type === "interactiveSpeaking" && questionIndex < currentExercise.prompts.length - 1) {
            setQuestionIndex(questionIndex + 1)
            return;
        }

        if (!reachedFinalExercise) {
            setQuestionIndex(0);
            setExerciseIndex(exerciseIndex + 1);
            return;
        }

        if (preview) {
            setPartIndex(0);
            setExerciseIndex(0);
            setQuestionIndex(0);
        }

        if (!showSolutions) {
            dispatch({ type: "FINALIZE_MODULE", payload: { updateTimers: true } });
        } else {
            dispatch({ type: "FINALIZE_MODULE_SOLUTIONS" });
        }
    }


    const previousExerciseOnlyExam = () => {
        const currentExercise = (exam as ExerciseOnlyExam).exercises[exerciseIndex];

        if (currentExercise.type === "interactiveSpeaking" && questionIndex !== 0) {
            setQuestionIndex(questionIndex - 1);
            return;
        }

        if (exerciseIndex !== 0) {
            setExerciseIndex(exerciseIndex - 1);
            return;
        }
    };

    return {
        seenParts,
        showPartDivider,
        nextExercise,
        previousExercise,
        setShowPartDivider,
        setSeenParts,
        isBetweenParts,
        setIsBetweenParts,
        startNow,
        setStartNow
    };
}

export default useExamNavigation;