import { Avatar, TableColumn as WSRTableColumn } from '@wix/design-system';
import React, {
  ComponentType,
  ReactElement,
  useCallback,
  useState,
} from 'react';
import { FiltersMap, KeyedItem } from '@wix/bex-core';
import { observer } from 'mobx-react-lite';
import { RowItem, RowKeyedItem, TableFoldersState } from '../../state';
import { ActionCell } from '../ActionCell';
import { PartialAllFilters } from '../../state/FoldersAndItemsCollectionsState';
import { FolderIcon } from '../FolderIcon';
import {
  CollectionTableWSRTable,
  CollectionTableWSRTableBaseProps,
  CollectionTableWSRTableProps,
} from '../CollectionTable/CollectionTableWSRTable';
import { CollectionTableContent } from '../CollectionTable/CollectionTableContent';
import {
  VirtualTableRepeater,
  VirtualTableRepeaterProps,
} from '../VirtualGridRepeater/VirtualTableRepeater';
import { VirtualGridStateProvider } from '../VirtualGridRepeater/VirtualGridStateContext';
import { TableFoldersColumn } from './TableFolders.types';
import { useOrFolderActionCellColumn } from './useOrFolderActionCellColumn';
import { TableFoldersInfiniteScroll } from './TableFoldersInfiniteScroll';
import {
  MultiCollectionBulkActionModalRenderProps,
  MultiCollectionBulkActionToolbar,
  MultiCollectionBulkActionToolbarRenderProps,
} from '../BulkAction';
import { TableColumn } from '../../model';
import { CollectionTableActionCellProps } from '../CollectionTable/CollectionTableBaseCommonProps';
import { SelectionDisabledProp } from '../../state/BulkActionToolbarState';
import { useCreateWSRColumnBase } from '../../hooks/useCreateWSRColumnBase';
import { TablePlaceholderStates } from '../TablePlaceholderStates/TablePlaceholderStates';
import { getVirtualTableProps } from '../Table/getVirtualTableProps';

type UnionTableProps<
  T1,
  F1 extends FiltersMap,
  T2,
  F2 extends FiltersMap,
> = CollectionTableWSRTableProps<
  RowItem<T1, T2>,
  T1,
  PartialAllFilters<F1, F2>
>;

type TableFolderWSRTableBaseProps<
  T1,
  F1 extends FiltersMap,
  T2,
  F2 extends FiltersMap,
> = CollectionTableWSRTableBaseProps<
  RowItem<T1, T2>,
  T1,
  PartialAllFilters<F1, F2>
>;

export interface TableFoldersContentProps<
  T1,
  F1 extends FiltersMap,
  T2,
  F2 extends FiltersMap,
> extends Omit<
      TableFolderWSRTableBaseProps<T1, F1, T2, F2>,
      'actionCell' | 'sticky' | 'topNotification' | 'selectionDisabled'
    >,
    CollectionTableActionCellProps<T1, F1> {
  dataHook?: string;
  /** A TableFoldersState instance created using [useTableFolders](./?path=/story/base-components-collections-tablefolders-usetablefolders--usetablefolders). */
  state: TableFoldersState<T1, F1, T2, F2>;
  /** The same as [Table.columns](./?path=/story/base-components-collections-table-table--table), with the addition of `renderFolder` property. */
  columns: TableFoldersColumn<T1, T2>[];
  /** Specific entry for rendering the item icon, defaults to simple `Avatar` (for folders a `Folder` icon is rendered). */
  iconColumn?: TableFoldersColumn<T1, T2>;

  onRowClick?: (item: T1, index: number) => void;
  /** Callback for folder row click  */
  onFolderRowClick?: (item: T2, index: number) => void;
  /** Disables row checkbox */
  selectionDisabled?: (item: T1 | T2) => void;
  folderActionCell?: ActionCell<T2, F2>;
  topNotification?: ReactElement;
  /**
   * A toolbar for performing bulk actions on multiple items.
   * Supported parameters:
   *  + `selectedValues`: Selected item values.
   *  + `uncheckedValues`: Unselected item values.
   *  + `isSelectAll`: [bool] Whether the **Select All** option is selected.
   *  + `openModal`: Opens a modal that contains the component from `bulkActionModal` render prop.
   *  + `clearSelection`: Clears all selections. Call this after the action on the selected items finishes.
   *  + `closeModal`: Closes the modal.
   *  + `openConfirmModal`: Opens a `<MessageModalLayout />` to confirm an action to be applied to the selected items.
   *  + `query`: [object] Instance of [ComputedQuery](./?path=/story/common-types--computedquery) that represents the query that resulted in an empty state. Representation of the current paging, sorting and filtering applied. Usually for using together with bulk action such as `updateAll` and `deleteAll`.
   * @external
   */
  bulkActionToolbar?: MultiCollectionBulkActionToolbarRenderProps;
  /**
   * Render a modal to be opened from `bulkActionToolbar`.<br>
   * The function accepts the following parameters
   *   * `allSelected`: Indicates whether the "Select All" checkbox is checked
   *   * `closeModal`: Closes the a modal
   */
  bulkActionModal?: MultiCollectionBulkActionModalRenderProps;
}

function _TableFoldersContent<
  T1,
  F1 extends FiltersMap,
  T2,
  F2 extends FiltersMap,
>(props: TableFoldersContentProps<T1, F1, T2, F2>) {
  const {
    state,
    columns,
    renderError,
    errorState = renderError &&
      (((err, { isOnline, retry }) =>
        renderError?.({ err, isOnline, retry })) as TableFoldersContentProps<
        T1,
        F1,
        T2,
        F2
      >['errorState']),
    emptyState,
    noResultsState,
    iconColumn,
    multiLevelSorting,
    actionCell,
    folderActionCell,
    actionCellWidth,
    actionCellProps,
    filters,
    customColumns,
    views,
    bulkActionToolbar,
    bulkActionModal,
    tableGridSwitchButton,
    topNotification,
    search,
    showTitleBar = !state.container.isPanelLayout,
    onRowClick,
    onFolderRowClick,
    selectionDisabled: selectionDisabledProp,
    horizontalScroll = true,
    rowVerticalPadding,
    ...rest
  } = props;

  const actionCellColumn = useOrFolderActionCellColumn({
    actionCell,
    folderActionCell,
    actionCellWidth,
    actionCellProps: {
      ...(actionCellProps ?? {}),
      stickyActionCell: true,
    },
    state: state.collections,
  });

  const {
    toolbar: { selectedOrderedColumnsOrAll },
  } = state;

  const createWSRColumnBase = useCreateWSRColumnBase({ horizontalScroll, showFieldTypeIcons: state.toolbar.showFieldTypeIcons });

  const finalColumns = [
    {
      key: 'cairo-avatar',
      title: '',
      width: '48px',
      ...iconColumn,
      style: undefined,
      render: ({ item }, rowNum) => {
        if (item._tag === 'folder') {
          return (
            iconColumn?.renderFolder?.(item.originalKeyedItem.item, rowNum) ?? (
              <FolderIcon data-hook="folder-icon" />
            )
          );
        }

        return (
          iconColumn?.render?.(item.originalKeyedItem.item, rowNum) ?? (
            <Avatar
              dataHook="item-avatar"
              name={state.collections.items.itemName(
                item.originalKeyedItem.item,
              )}
            />
          )
        );
      },
    },
    ...(selectedOrderedColumnsOrAll as TableFoldersColumn<T1, T2>[]).map(
      (column, index, { length }) => {
        const {
          id,
          title,
          width,
          sortable,
          infoTooltipProps,
          render,
          renderFolder,
          ...restColumn
        } = column;

        return {
          ...restColumn,
          ...createWSRColumnBase(column, index, length),
          sortDescending:
            sortable && id
              ? state.collections.query.sort.getIsSortDescending(id)
              : undefined,
          render: (row: RowKeyedItem<T1, T2>, rowNum: number) => {
            const item = row.item;
            if (item._tag === 'folder') {
              return renderFolder?.(item.originalKeyedItem.item, rowNum);
            }

            return render(item.originalKeyedItem.item, rowNum);
          },
        };
      },
    ),
    ...(actionCellColumn ? [actionCellColumn] : []),
  ] as WSRTableColumn<RowKeyedItem<T1, T2>>[];

  const [BodyElementType] = useState(
    () =>
      ({ children }: VirtualTableRepeaterProps) =>
        (
          <VirtualGridStateProvider value={state.virtual}>
            <VirtualTableRepeater>{children}</VirtualTableRepeater>
          </VirtualGridStateProvider>
        ),
  );

  const selectionDisabled = useCallback(
    ({ item }: KeyedItem<T1 | T2>) => selectionDisabledProp?.(item),
    [selectionDisabledProp],
  );

  if (selectionDisabled != null) {
    state.toolbar.bulk.selectionDisabledProp =
      selectionDisabled as SelectionDisabledProp;
  }

  const Table = CollectionTableWSRTable as ComponentType<
    UnionTableProps<T1, F1, T2, F2>
  >;

  const showSelection = bulkActionToolbar != null;

  return (
    <Table
      {...rest}
      showHeaderWhenEmpty
      state={state}
      sticky
      search={search}
      filters={filters}
      customColumns={customColumns}
      views={views}
      showSelection={showSelection}
      selectionToolbar={
        bulkActionToolbar && (
          <MultiCollectionBulkActionToolbar
            state={state.toolbar}
            bulkActionToolbar={bulkActionToolbar}
          />
        )
      }
      tableGridSwitchButton={tableGridSwitchButton}
      horizontalScroll={horizontalScroll}
      emptyState={emptyState}
      noResultsState={noResultsState}
      {...getVirtualTableProps({ horizontalScroll })}
      columns={finalColumns}
      showTitleBar={showTitleBar}
      isApplyColumnWidthStyle={true}
      BodyElementType={BodyElementType}
      onSortClick={(col: TableColumn<{}>) => {
        if (col.id != null) {
          state.collections.items.sort(
            { id: col.id, sortMode: col.sortMode },
            {
              clearResult: true,
              multiple: multiLevelSorting !== undefined,
            },
          );
        }
      }}
      onRowClick={
        (onRowClick || onFolderRowClick) &&
        (({ item }, index) => {
          if (item._tag === 'folder') {
            onFolderRowClick?.(item.originalKeyedItem.item, index);
          } else {
            onRowClick?.(item.originalKeyedItem.item, index);
          }
        })
      }
      selectionDisabled={
        selectionDisabledProp &&
        (({ item }) => selectionDisabledProp?.(item.originalKeyedItem.item))
      }
      topNotification={topNotification}
    >
      <TablePlaceholderStates
        state={state}
        emptyState={emptyState}
        noResultsState={noResultsState}
        errorState={errorState}
        rowVerticalPadding={rowVerticalPadding}
        showTitleBar={showTitleBar}
      />

      <CollectionTableContent state={state.table}>
        <TableFoldersInfiniteScroll state={state} />
      </CollectionTableContent>
    </Table>
  );
}

export const TableFoldersContent = observer(_TableFoldersContent);
