import { RefObject, useEffect, useRef, useState } from 'react';

interface FetchFunction<T> {
  (page: number): Promise<T[]>;
}

const useLoadOnScroll = <T>(executeFetch: FetchFunction<T>) => {
  const [data, setData] = useState<T[]>([]);
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const [page, setPage] = useState<number>(1);
  const [listener, setListener] = useState<number>(1);
  const [lastPage, setLastPage] = useState<boolean>(false);

  const fetchData = async (isSearch?: boolean) => {
    if (!lastPage || isSearch === true)
      if (isLoading === false) {
        setIsLoading(true);
        if (isSearch === true) {
          const newData = await executeFetch(1);
          if (newData.length > 0) {
            setData(newData);
            setPage((prevPage) => 2);
          } else {
            setLastPage(true);
            setData([]);
          }
        } else {
          const newData = await executeFetch(page);
          if (newData.length > 0) {
            setData((prevData) => [...prevData, ...newData]);
            setPage((prevPage) => prevPage + 1);
          } else {
            setLastPage(true);
          }
        }

        setIsLoading(false);
      }
  };

  const refetchData = () => {
    setPage(1);
    setListener((prev) => prev + 1);
  };

  const resetLastPage = () => {
    setLastPage(false);
  };

  useEffect(() => {
    fetchData();
  }, [listener]);

  // useEffect(() => {
  //   if (data.length === 0) {
  //     fetchData();
  //   }
  // }, [data]);

  const handleScroll = () => {
    const { scrollTop, clientHeight, scrollHeight } = document.documentElement;

    if (scrollTop + clientHeight >= scrollHeight - 1) {
      setListener((prevListener) => prevListener + 1);
    }
  };

  const resetSearch = () => {
    console.log('reset search');
    fetchData(true);
    resetLastPage();
  };

  useEffect(() => {
    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  const onClose = () => {
    setData([]);
    setPage(1);
    setLastPage(false);
  };

  const onOpen = () => {
    setData([]);
    setLastPage(false);
    fetchData(true);
  };

  // setData and setPage to reset when the dialog closed
  return { data, isLoading, setPage, setData, resetSearch, resetLastPage, onClose, onOpen, refetchData };
};

export default useLoadOnScroll;
