import {
  type Dispatch,
  type SetStateAction,
  useCallback,
  useEffect,
  useRef,
  useState,
} from 'react'

export function useCardSelection<T>(cardData: T[]) {
  const selectedItemsRef = useRef<T[]>([])
  const setCheckedItemsRef = useRef<
    Dispatch<SetStateAction<Record<number, boolean>>>
  >(() => {})
  const [isCheckAll, setIsCheckAll] = useState(false)
  const [selectedItems, setSelectedItems] = useState<T[]>([])

  useEffect(() => {
    if (selectedItemsRef.current.length !== selectedItems.length) {
      setSelectedItems([...selectedItemsRef.current])
    }
    setIsCheckAll(selectedItemsRef.current.length === cardData.length)
  }, [cardData.length, selectedItems.length, selectedItemsRef.current.length])

  useEffect(() => {
    // Always update the state from the ref to ensure they stay in sync
    setSelectedItems([...selectedItemsRef.current])
    setIsCheckAll(selectedItemsRef.current.length === cardData.length)
  }, [cardData.length])

  useEffect(() => {
    // When cardData changes, reset selectedItemsRef if needed
    selectedItemsRef.current = selectedItems
  }, [cardData, selectedItems])

  const selectAll = useCallback(
    (setCheckedItems: Dispatch<SetStateAction<Record<number, boolean>>>) => {
      const allCheckedItems = cardData.reduce(
        (acc, _, index) => {
          acc[index] = true
          return acc
        },
        {} as Record<number, boolean>,
      )

      setCheckedItems(allCheckedItems)
    },
    [cardData],
  )

  const unselectAll = useCallback(
    (setCheckedItems: Dispatch<SetStateAction<Record<number, boolean>>>) => {
      const allCheckedItems = cardData.reduce(
        (acc, _, index) => {
          acc[index] = false
          return acc
        },
        {} as Record<number, boolean>,
      )

      setCheckedItems(allCheckedItems)
    },
    [cardData],
  )

  const handleCheckAll = useCallback(
    (checked: boolean) => {
      setIsCheckAll(checked)
      setSelectedItems(checked ? [...cardData] : [])

      if (setCheckedItemsRef.current) {
        checked
          ? selectAll(setCheckedItemsRef.current)
          : unselectAll(setCheckedItemsRef.current)
      }
    },
    [cardData, selectAll, unselectAll],
  )

  return {
    selectedItemsRef,
    setCheckedItemsRef,
    isCheckAll,
    selectedItems,
    handleCheckAll,
    setSelectedItems,
  }
}
