import { useCallback, useEffect, useMemo, useState } from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import { createContext } from '@/hooks/useContextSelector';

export const useMultiSelect = () => {
  const { menus } = useStores();

  const [selectedClipIds, setSelectedClipIds] = useState<string[]>([]);
  const [lastSelectedClipId, setLastSelectedClipId] = useState<string | null>(
    null
  );

  const toggleClip = useCallback((clipId: string) => {
    setSelectedClipIds((prev) => {
      if (prev.includes(clipId)) {
        return prev.filter((id) => id !== clipId);
      }
      return [...prev, clipId];
    });
    setLastSelectedClipId(clipId);
  }, []);

  const selectRange = useCallback(
    (clipId: string, allClipIds: string[]) => {
      if (!lastSelectedClipId) {
        setSelectedClipIds([clipId]);
        setLastSelectedClipId(clipId);
        return;
      }

      const lastIndex = allClipIds.indexOf(lastSelectedClipId);
      const currentIndex = allClipIds.indexOf(clipId);

      if (lastIndex === -1 || currentIndex === -1) {
        toggleClip(clipId);
        return;
      }

      const start = Math.min(lastIndex, currentIndex);
      const end = Math.max(lastIndex, currentIndex);
      const range = allClipIds.slice(start, end + 1);

      setSelectedClipIds((prev) => {
        const newSet = new Set([...prev, ...range]);
        return Array.from(newSet);
      });
      setLastSelectedClipId(clipId);
    },
    [lastSelectedClipId, toggleClip]
  );

  const clear = useCallback(() => {
    setSelectedClipIds([]);
    // Don't clear lastSelectedClipId - it should persist as the anchor point
    // for the next shift+click operation
  }, []);

  const setLastSelected = useCallback((clipId: string) => {
    setLastSelectedClipId(clipId);
  }, []);

  useEffect(() => {
    menus.setSelected(new Set(selectedClipIds));
  }, [selectedClipIds, menus.setSelected]);

  const setSelectedClipIdsFromArray = useCallback((clipIds: string[]) => {
    setSelectedClipIds(clipIds);
  }, []);

  return useMemo(
    () => ({
      selectedClipIds,
      toggleClip,
      selectRange,
      clear,
      setSelectedClipIds: setSelectedClipIdsFromArray,
      setLastSelected,
    }),
    [
      selectedClipIds,
      toggleClip,
      selectRange,
      clear,
      setSelectedClipIdsFromArray,
      setLastSelected,
    ]
  );
};

const MultiSelectContext = createContext<ReturnType<typeof useMultiSelect>>({
  selectedClipIds: [],
  toggleClip: () => {},
  selectRange: () => {},
  clear: () => {},
  setSelectedClipIds: () => {},
  setLastSelected: () => {},
});

export const MultiSelectContextProvider = ({
  children,
}: {
  children: React.ReactNode;
}) => {
  const value = useMultiSelect();
  return (
    <MultiSelectContext.Provider value={value}>
      {children}
    </MultiSelectContext.Provider>
  );
};

export default MultiSelectContext;
