import React, { useEffect } from 'react';
import { FiltersMap } from '@wix/bex-core';
import { GridPresetProps } from './Grid.types';
import { GridState, LayoutType } from '../../state';
import { getToolbarCollectionFeaturesInitializers } from '../../state/getToolbarCollectionFeaturesInitializers';
import { ToolbarCollectionContentAutoSizer } from '../ToolbarCollectionContentAutoSizer';
import { BulkActionToolbarRenderProp } from '../BulkAction';
import { GridItemBaseProps } from './GridItemBaseProps';
import { GridPlaceholderStates } from './GridPlaceholderStates';
import { CollectionCard } from '../CollectionCard';
import {
  ToolbarCollection,
  ToolbarCollectionBaseProps,
} from '../ToolbarCollection';
import { observer } from 'mobx-react-lite';
import { useToolbarCollectionSyncProps } from '../ToolbarCollection/useToolbarCollectionSyncProps';
import type { GridSectionsContent } from '../GridSections/GridSectionsContent';
import type { GroupBy, RenderSection } from '../CollectionSectionHeader';
import { GridSingleGridContent } from './GridSingleGridContent';
import { GridDragAndDrop } from '../GridDragAndDropDndKit/GridDragAndDrop';

interface GridBaseProps<T, F extends FiltersMap>
  extends Omit<ToolbarCollectionBaseProps<T, F>, 'sticky' | 'maxSelection'>,
    GridItemBaseProps<T, F> {
  dataHook?: string;
  /**
   * Adds functionality to allow visitors to reorder items manually.
   * For more information, see the [Drag and Drop Overview](./?path=/story/features-sort-drag-and-drop--overview).
   * @overrideType [GridDragAndDrop](./?path=/story/features-sort-drag-and-drop--griddraganddrop)
   * @external
   */
  dragAndDrop?: typeof GridDragAndDrop;

  /**
   * Grid state instance created using [`useGridCollection`](./?path=/story/base-components-collections-grid-usegridcollection--usegridcollection).
   * @overrideType [GridState](./?path=/story/base-components-collections-grid-gridstate--gridstate)
   * @external
   */
  state: GridState<T, F>;

  /**
   * A toolbar for performing bulk actions on multiple items.<br> <br>
   * Supported parameters: <br>
   * -`selectedValues`: [array] Items that are checked in the selection column. <br>
   * -`uncheckedValues`: [array] Items that are unchecked in the selection column. <br>
   * -`isSelectAll`: [bool] Whether **Select All** is checked. <br>
   * -`openModal`: [func] Opens a modal that contains the component from `bulkActionModal` render prop. <br>
   * -`clearSelection`: [func] Clears all selections. Call this after the action on the selected items finishes. <br>
   * -`total`: [number] Total number of items in the server. <br>
   * -`openConfirmModal`: [func] Opens a `<MessageModalLayout>` to confirm an action is about to be applied to the selected items. <br>
   * -`query`: [object] Current paging, sorting, and filtering. Often used together with bulk actions, such as `updateAll`. <br>
   * @external
   */
  bulkActionToolbar?: BulkActionToolbarRenderProp<T, F>;

  /**
   * Creates [grid sections](./?path=/story/features-display-grid-sections--grid-sections) that group data based on the values of a specific field.
   * @external
   * @overrideType [SectionsProp](./?path=/story/common-types--sectionsprop)
   */
  sections?: {
    GridSections: typeof GridSectionsContent;
    groupBy: GroupBy<T>;
    renderSection?: RenderSection<T>;
  };

  layoutType?: LayoutType;
}

export type GridBasePropsWithoutPreset<T, F extends FiltersMap> = Omit<
  GridBaseProps<T, F>,
  'preset' | 'renderItem'
>;

export type GridProps<T, F extends FiltersMap> = GridPresetProps<
  T,
  GridBasePropsWithoutPreset<T, F>
>;

function _Grid<T, F extends FiltersMap = FiltersMap>(props: GridProps<T, F>) {
  const {
    state,
    dragAndDrop,
    renderError,
    errorState = renderError &&
      (((err, { isOnline, retry }) =>
        renderError?.({ err, isOnline, retry })) as GridProps<
        T,
        F
      >['errorState']),
    emptyState,
    noResultsState,
    cardProps,
    dataHook,
    exportModal,
    importModal,
    sections,
  } = props;

  const { toolbar } = state;

  useToolbarCollectionSyncProps({
    ...props,
    state: state.toolbar,
    isUsingDragAndDrop: !!dragAndDrop,
    isUsingBulkActionsToolbar: false,
    isUsingHorizontalScroll: false,
    isUsingFolders: false,
    isUsingTableVirtualization: false,
  });

  useEffect(
    () =>
      state.init({
        featuresInitializers: getToolbarCollectionFeaturesInitializers(props),
      }),
    [],
  );

  return (
    <CollectionCard
      errorState={false}
      state={toolbar}
      dataHook={dataHook}
      {...cardProps}
    >
      <ToolbarCollection {...props} sticky state={toolbar}>
        <GridPlaceholderStates
          state={state.toolbar}
          errorState={errorState}
          emptyState={emptyState}
          noResultsState={noResultsState}
        >
          <ToolbarCollectionContentAutoSizer>
            {sections ? (
              <sections.GridSections
                {...props}
                groupBy={sections.groupBy}
                renderSection={sections.renderSection}
                state={state}
              />
            ) : (
              <GridSingleGridContent {...props} state={state} />
            )}
          </ToolbarCollectionContentAutoSizer>
        </GridPlaceholderStates>
      </ToolbarCollection>
      {exportModal ?? toolbar.featuredComponents.exportModal.value}
      {importModal ?? toolbar.featuredComponents.importModal.value}
    </CollectionCard>
  );
}

export const Grid = observer(_Grid);
