import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import useExamEditorStore from "@/stores/examEditor";
import { Module } from "@/interfaces";
import { debounce } from "lodash";
import { SectionSettings } from "@/stores/examEditor/types";


// Since all the other components have a local state
// that then gets updated all at once, if the keydowns 
// aren't here aren't throttled things can get messy
const useSettingsState = <T extends SectionSettings>(
    module: Module,
    sectionId: number,
) => {
    const globalSettings = useExamEditorStore((state) => {
        const settings = state.modules[module].sections.find(
            (section) => section.sectionId === sectionId
        )?.settings;
        return settings as T;
    });

    const dispatch = useExamEditorStore((state) => state.dispatch);

    const [localSettings, setLocalSettings] = useState<T>(() =>
        globalSettings || {} as T
    );

    const pendingUpdatesRef = useRef<Partial<T>>({});

    useEffect(() => {
        if (globalSettings) {
            setLocalSettings(globalSettings);
        }
    }, [globalSettings]);

    const debouncedUpdateGlobal = useMemo(() => {
        const debouncedFn = debounce(() => {
            if (Object.keys(pendingUpdatesRef.current).length > 0) {
                dispatch({
                    type: 'UPDATE_SECTION_SETTINGS',
                    payload: { sectionId, update: pendingUpdatesRef.current, module}
                });
                pendingUpdatesRef.current = {};
            }
        }, 1000);

        return debouncedFn;
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [dispatch, sectionId]);

    useEffect(() => {
        return () => {
            if (Object.keys(pendingUpdatesRef.current).length > 0) {
                dispatch({
                    type: 'UPDATE_SECTION_SETTINGS',
                    payload: {sectionId, update: pendingUpdatesRef.current, module}
                });
            }
        };
    }, [dispatch, module, sectionId]);


    const updateLocalAndScheduleGlobal = useCallback((updates: Partial<T>, schedule: boolean = true) => {
        setLocalSettings(prev => ({
            ...prev,
            ...updates
        }));

        pendingUpdatesRef.current = {
            ...pendingUpdatesRef.current,
            ...updates
        };
        if (schedule) {
            debouncedUpdateGlobal();
        }
    }, [debouncedUpdateGlobal]);

    return {
        localSettings,
        updateLocalAndScheduleGlobal
    };
};

export default useSettingsState;
