import React, { ReactElement, useEffect, useLayoutEffect } from 'react';
import { observer } from 'mobx-react-lite';
import { FiltersMap } from '@wix/bex-core';
import { GridBaseState, LayoutType } from '../../state';
import { InitialSkeletonLoader } from '../InitialLoader/InitialSkeletonLoader';
import { PageGridInfiniteScrollLoader } from '../PageGridInfiniteScrollLoader';
import { AddItemProps, Box } from '@wix/design-system';
import { useGridBaseSyncProps } from './useGridBaseSyncProps';
import { useRenderItem } from './useRenderItem';
import { VirtualGridRepeater } from '../VirtualGridRepeater/VirtualGridRepeater';
import { SupportedCardGalleryItemProps } from './SupportedCardGalleryItemProps';
import { DragAndDropCancel, DragAndDropSubmit } from '../DragAndDrop';
import { ActionCell } from '../ActionCell';
import { GridDragAndDrop } from '../GridDragAndDropDndKit/GridDragAndDrop';
import type { Preset } from './Grid.types';

export interface GridContentBaseProps<T, F extends FiltersMap> {
  preset?: Preset;
  imagePlacement?: 'side' | 'top';
  renderItem?: (
    item: T,
    index: number,
  ) => Partial<SupportedCardGalleryItemProps>;
  actionCell?: ActionCell<T, F>;
  renderAddItem?: () => ReactElement<AddItemProps>;
  dragAndDrop?: typeof GridDragAndDrop;
  dragAndDropSubmit?: DragAndDropSubmit<T, F>;
  dragAndDropCancel?: DragAndDropCancel<T, F>;
  layoutType?: LayoutType;
}

export interface GridContentProps<T, F extends FiltersMap>
  extends GridContentBaseProps<T, F> {
  state: GridBaseState<T, F>;
  range?: { start: number; length: number };
  withInfiniteScrollLoader?: boolean;
  paddingTop?: string;
  paddingBottom?: string;
}

function _GridContent<T, F extends FiltersMap = FiltersMap>(
  props: GridContentProps<T, F>,
) {
  const {
    state,
    withInfiniteScrollLoader,
    dragAndDrop,
    dragAndDropSubmit,
    paddingTop,
    paddingBottom,
  } = props;

  const {
    toolbar: {
      contentPaddingPx,
      showInitialLoader,
      multi: { showRefreshLoader },
    },
  } = state;

  useGridBaseSyncProps(props);

  useEffect(() => state.init(), []);

  const renderItem = useRenderItem(props);

  let child = <VirtualGridRepeater renderItem={renderItem} gridState={state} />;

  if (dragAndDrop) {
    const { DraggableCardOverlay, SortableContext } = dragAndDrop;

    child = (
      <SortableContext state={state} onSubmit={dragAndDropSubmit}>
        {child}
        <DraggableCardOverlay state={state} renderItem={renderItem} />
      </SortableContext>
    );
  }

  if (showRefreshLoader || showInitialLoader) {
    child = (
      <InitialSkeletonLoader
        dataHook={
          showInitialLoader ? 'grid-initial-loader' : 'grid-refresh-loader'
        }
        state={state}
      />
    );
  } else {
    child = (
      <>
        {child}
        {withInfiniteScrollLoader && (
          <PageGridInfiniteScrollLoader
            dataHook="infinite-scroll-loader"
            state={state}
            scrollMoreAlways
          />
        )}
      </>
    );
  }

  useLayoutEffect(() => {
    state._containerRectState._syncThrottled();
  }, []);

  useEffect(() => state._containerRectState.init(), []);

  return (
    <Box
      direction="vertical"
      paddingTop={paddingTop}
      paddingBottom={paddingBottom}
      paddingRight={contentPaddingPx}
      paddingLeft={contentPaddingPx}
    >
      <div
        ref={(el) => {
          state._containerRectState.element = el;
        }}
      >
        {child}
      </div>
    </Box>
  );
}

export const GridContent = observer(_GridContent);
