import { ReactElement, ReactNode, useEffect } from 'react';
import { useInView } from 'react-intersection-observer';
import { InfiniteQueryObserverBaseResult } from 'react-query';

import { TableBodyProps } from '@material-hu/mui/TableBody';

import CircularProgress from '@material-hu/components/design-system/ProgressIndicators/Spinner';
import TableBody from '@material-hu/components/design-system/Table/components/TableBody';
import TableCell from '@material-hu/components/design-system/Table/components/TableCell';
import TableRow from '@material-hu/components/design-system/Table/components/TableRow';

export type InfiniteTableProps = TableBodyProps &
  Pick<
    InfiniteQueryObserverBaseResult,
    'isFetchingNextPage' | 'hasNextPage' | 'fetchNextPage'
  > & {
    withEnd?: boolean;
    children: ReactNode;
    totalColumns: number;
    isEmpty?: boolean;
    isLoading: boolean;
    renderSkeleton?: ReactElement;
    renderEmptyState?: ReactElement;
  };

const InfiniteTable = ({
  fetchNextPage,
  hasNextPage,
  isFetchingNextPage,
  children,
  isLoading,
  isEmpty,
  renderSkeleton,
  totalColumns,
  renderEmptyState,
  ...bodyProps
}: InfiniteTableProps) => {
  const [ref, inView] = useInView({
    threshold: 0,
  });

  useEffect(() => {
    if (inView && hasNextPage && !isEmpty) {
      fetchNextPage();
    }
  }, [inView, hasNextPage, isEmpty]);

  return (
    <TableBody {...bodyProps}>
      {children}
      {!isLoading && hasNextPage && (
        // Using TableRow because HuTableRow seems to not be passing the ref
        <TableRow
          sx={{ height: '2px' }}
          className="loadingMoreRef"
          ref={ref}
        />
      )}
      {isFetchingNextPage &&
        (renderSkeleton || (
          <TableRow>
            <TableCell
              colSpan={totalColumns}
              sx={{ textAlign: 'center' }}
            >
              <CircularProgress />
            </TableCell>
          </TableRow>
        ))}
      {isEmpty && renderEmptyState && (
        <TableRow>
          <TableCell
            colSpan={totalColumns}
            sx={{ textAlign: 'center' }}
          >
            {renderEmptyState}
          </TableCell>
        </TableRow>
      )}
    </TableBody>
  );
};

export default InfiniteTable;
