import { create } from "zustand";
import { createJSONStorage, persist } from "zustand/middleware";
import { immer } from "zustand/middleware/immer";
import { ExamFunctions, ExamState, Navigation, StateFlags } from "./types";
import { rootReducer } from "./reducers";
import axios from "axios";
import { v4 } from "uuid";
import { Stat } from "@/interfaces/user";
import { Exam, Shuffles, UserSolution } from "@/interfaces/exam";
import { Module } from "@/interfaces";

export const initialState: ExamState = {
    exams: [],
    userSolutions: [],
    showSolutions: false,
    selectedModules: [],
    assignment: undefined,
    timeSpent: 0,
    timeSpentCurrentModule: 0,
    sessionId: "",
    exam: undefined,
    moduleIndex: 0,
    partIndex: 0,
    exerciseIndex: 0,
    questionIndex: 0,
    inactivity: 0,
    shuffles: [],
    bgColor: "bg-white",
    user: undefined,
    navigation: {
        previousDisabled: false,
        nextDisabled: false,
        previousLoading: false,
        nextLoading: false,
    },
    flags: {
        timeIsUp: false,
        reviewAll: false,
        finalizeModule: false,
        finalizeExam: false,
    },
};

const useExamStore = create<ExamState & ExamFunctions>((set, get) => ({
    ...initialState,
    setUser: (user: string) => set(() => ({ user })),
    setShowSolutions: (showSolutions: boolean) => set(() => ({ showSolutions })),
    setExams: (exams: Exam[]) => set(() => ({ exams })),
    setExam: (exam?: Exam) => set(() => ({ exam })),
    setModuleIndex: (moduleIndex: number) => set(() => ({ moduleIndex })),
    setSelectedModules: (modules: Module[]) => set(() => ({ selectedModules: modules })),

    setSessionId: (sessionId: string) => set(() => ({ sessionId })),
    setUserSolutions: (userSolutions: UserSolution[]) => set(() => ({ userSolutions })),

    setShuffles: (shuffles: Shuffles[]) => set(() => ({ shuffles })),

    setPartIndex: (partIndex: number) => set(() => ({ partIndex })),
    setExerciseIndex: (exerciseIndex: number) => set(() => ({ exerciseIndex })),
    setQuestionIndex: (questionIndex: number) => set(() => ({ questionIndex })),
    setBgColor: (bgColor: string) => set(() => ({ bgColor })),

    setNavigation: (updates: Partial<Navigation>) => set((state) => ({
        navigation: {
            ...state.navigation,
            ...updates
        }
    })),

    setFlags: (updates: Partial<StateFlags>) => set((state) => ({
        flags: {
            ...state.flags,
            ...updates
        }
    })),

    setTimeIsUp: (timeIsUp: boolean) => set((state) => ({ flags: { ...state.flags, timeIsUp } })),

    reset: () => set(() => initialState),

    saveSession: async () => {
        console.log("Saving your session...");
        const state = get();
        await axios.post("/api/sessions", {
            id: state.sessionId,
            sessionId: state.sessionId,
            date: new Date().toISOString(),
            userSolutions: state.userSolutions.filter((s) => s.type !== "speaking" && s.type !== "interactiveSpeaking"),
            moduleIndex: state.moduleIndex,
            selectedModules: state.selectedModules,
            assignment: state.assignment,
            timeSpent: state.timeSpent,
            timeSpentCurrentModule: state.timeSpentCurrentModule,
            inactivity: state.inactivity,
            exams: state.exams,
            exam: state.exam,
            partIndex: state.partIndex,
            exerciseIndex: state.exerciseIndex,
            questionIndex: state.questionIndex,
            user: state.user,
        });
    },
    saveStats: async () => {
        const state = get();
        const newStats: Stat[] = state.userSolutions.map((solution) => ({
            ...solution,
            id: solution.id || v4(),
            timeSpent: state.timeSpent,
            inactivity: state.inactivity,
            session: state.sessionId,
            exam: solution.exam!,
            module: solution.module!,
            user: state.user || "",
            date: new Date().getTime(),
            isDisabled: solution.isDisabled,
            shuffleMaps: solution.shuffleMaps,
            ...(state.assignment ? { assignment: state.assignment.id } : {}),
            isPractice: solution.isPractice
        }));
        await axios.post<{ ok: boolean }>("/api/stats", newStats);
    },
    dispatch: (action) => set((state) => rootReducer(state, action))
}));

export const usePersistentExamStore = create<ExamState & ExamFunctions>()(
    persist(
        immer((set) => ({
            ...initialState,
            setUser: (user: string) => set(() => ({ user })),
            setShowSolutions: (showSolutions: boolean) => set(() => ({ showSolutions })),
            setExams: (exams: Exam[]) => set(() => ({ exams })),
            setExam: (exam?: Exam) => set(() => ({ exam })),
            setModuleIndex: (moduleIndex: number) => set(() => ({ moduleIndex })),
            setSelectedModules: (modules: Module[]) => set(() => ({ selectedModules: modules })),

            setSessionId: (sessionId: string) => set(() => ({ sessionId })),
            setUserSolutions: (userSolutions: UserSolution[]) => set(() => ({ userSolutions })),

            setShuffles: (shuffles: Shuffles[]) => set(() => ({ shuffles })),

            setPartIndex: (partIndex: number) => set(() => ({ partIndex })),
            setExerciseIndex: (exerciseIndex: number) => set(() => ({ exerciseIndex })),
            setQuestionIndex: (questionIndex: number) => set(() => ({ questionIndex })),
            setBgColor: (bgColor: string) => set(() => ({ bgColor })),

            setNavigation: (updates: Partial<Navigation>) => set((state) => ({
                navigation: {
                    ...state.navigation,
                    ...updates
                }
            })),

            setFlags: (updates: Partial<StateFlags>) => set((state) => ({
                flags: {
                    ...state.flags,
                    ...updates
                }
            })),


            setTimeIsUp: (timeIsUp: boolean) => set((state) => ({ flags: { ...state.flags, timeIsUp } })),

            saveStats: async () => { },
            saveSession: async () => { },
            setEvalSolutions: (evaluated: UserSolution[]) => {},
            reset: () => set(() => initialState),
            dispatch: (action) => set((state) => rootReducer(state, action))

        })),
        {
            name: 'persistent-exam-store',
            storage: createJSONStorage(() => localStorage),
            partialize: (state) => ({ ...state }),
        }
    )
);

export default useExamStore;
