import {
  Box,
  Table as WSRTable,
  TableColumn as WSRTableColumn,
  TableProps,
} from '@wix/design-system';
import React, {
  ComponentType,
  ForwardRefExoticComponent,
  ReactElement,
  useCallback,
} from 'react';
import { observer } from 'mobx-react-lite';
import { FiltersMap, KeyedItem } from '@wix/bex-core';
import { cairoCtaClicked } from '@wix/bex-core/bi';
import { CollectionProvider } from '../CollectionContext';
import { TableState, ToolbarCollectionState } from '../../state';
import { ToolbarCollectionBaseProps } from '../ToolbarCollection';
import { CollectionTableContentBaseProps } from './CollectionTableContent';
import { classes, st } from '../common.st.css.js';
import {
  classes as wsrTableClasses,
  st as wsrTableSt,
} from './CollectionTableWSRTable.st.css.js';
import { CollectionToolbars } from '../CollectionToolbars/CollectionToolbars';
import { BorderOnlyBox } from '../BorderOnlyBox';
import { usePageContext, useWixPatternsContainer } from '@wix/bex-core/react';
import { useIsMobile } from '../../hooks/useIsMobile';
import { CollectionToolbarsVisualizationProps } from '../CollectionToolbars/CollectionToolbarsVisualization';
import { buildMobileColumns } from './buildMobileColumns';
import { TableColumn } from '../../model';

export interface CollectionTableWSRTableBaseProps<U, T, F extends FiltersMap>
  extends ToolbarCollectionBaseProps<T, F>,
    CollectionTableContentBaseProps,
    Omit<
      TableProps<KeyedItem<U>>,
      | 'columns'
      | 'data'
      | 'rowDataHook'
      | 'onRowClick'
      | 'onDragEnd'
      | 'onDragStart'
      | 'onDragCancel'
      | 'isDragAndDropDisabled'
      | 'hideBulkSelectionCheckbox'
      | 'skin'
    > {
  /**
   * @deprecated The table skin is fixed to `"neutral"` and any value passed here is ignored. This prop will be removed in a future release.
   */
  skin?: TableProps<KeyedItem<U>>['skin'];

  useShowLoaderWhenEmpty?: boolean;
  useNewInfiniteScrollLoader?: boolean;

  /**
   * Whether to add a sticky column. <br>
   * Sticky columns allow you to display specific columns at all times while the visitor scrolls the table horizontally.
   * @external
   */
  stickySelectionColumn?: boolean;

  /**
   * Limits the amount of rows a visitor can select.
   * @external
   */
  maxSelection?: number;

  /**
   * Hides bulk selection checkbox in the table titlebar, If the [`MultiBulkActionToolbar`](./?path=/story/features-actions-bulk-actions--multibulkactiontoolbar) feature is enabled, this flag will have no effect.
   * @external
   */
  hideBulkSelectionCheckbox?: boolean;

  BodyElementType?: ComponentType<{ children: ReactElement[] }>;

  TrElementType?: ForwardRefExoticComponent<{
    children: ReactElement[];
    rowData: any;
    className: string;
  }>;
  visualization?: CollectionToolbarsVisualizationProps<T, F>['visualization'];
}

export interface CollectionTableWSRTableProps<U, T, F extends FiltersMap>
  extends CollectionTableWSRTableBaseProps<U, T, F> {
  state: {
    tableState: TableState<T, F>;
    toolbar: ToolbarCollectionState<T, F>;
    keyedItems: KeyedItem<U>[];
    showLoadingState: boolean;
    showEmptyState: boolean;
  };

  sticky: boolean;

  columns: WSRTableColumn<KeyedItem<U>>[];
  onRowClick?: (item: KeyedItem<U>, index: number) => void;
  keyedItems?: KeyedItem<U>[];
}

function _CollectionTableWSRTable<U, T, F extends FiltersMap = FiltersMap>(
  props: CollectionTableWSRTableProps<U, T, F>,
) {
  const {
    state,
    filters,
    title,
    tabs,
    customColumns: customColumnsProp,
    multiLevelSorting: multiLevelSortingProp,
    views,
    extraToolbar,
    summaryBar,
    topNotification,
    selectionToolbar,
    dragAndDropReorderModeToolbar,
    showSelection: showSelectionProp,
    exportButton,
    importButton,
    tags,
    sticky,
    onRowClick,
    search,
    children,
    tableGridSwitchButton,
    useShowLoaderWhenEmpty,
    dragAndDrop,
    showTitleBar,
    horizontalScroll,
    stickyColumns,
    stickySelectionColumn,
    hideBulkSelectionCheckbox,
    columns,
    primaryActionButton,
    secondaryActions,
    onSelectionChanged,
    moreActions,
    visualization,
    resizable,
  } = props;

  const isMobile = useIsMobile();
  const {
    toolbar,
    showEmptyState,
    tableState: table,
    keyedItems: stateKeyedItems,
  } = state;
  const { isPanelLayout } = useWixPatternsContainer();

  const { bulk, initTask } = toolbar;

  const keyedItems = props.keyedItems ?? stateKeyedItems;
  const { collection } = table;
  const { showRefreshLoader, showErrorState } = collection;

  const { stackingRootRef } = usePageContext();

  const handleRowCLick = useCallback(
    (item: KeyedItem<U>, index: number) => {
      state.toolbar.reportBi(
        cairoCtaClicked({
          ctaName: 'row_area',
          ctaIndex: index,
          itemId: item.id,
          itemIndex: item.index,
          url: typeof window !== 'undefined' ? window.location.href : '',
        }),
      );
      onRowClick?.(item, index);
    },
    [onRowClick],
  );

  const Table = WSRTable as ComponentType<TableProps<KeyedItem<U>>>;

  const showSelection = showSelectionProp ?? selectionToolbar != null;

  const hideTitleBar =
    isMobile ||
    showEmptyState ||
    toolbar.showInitialLoader ||
    initTask.status.isError;

  const showBorderBox =
    !isPanelLayout &&
    (!table.showLoadingState || !showTitleBar) &&
    (hideTitleBar || !showTitleBar);

  const actionCellColumn = columns.find(
    (column) => column.key === 'cairo-action-cell',
  );

  const columnsWithoutActionCell = columns.filter(
    (column) => column.key !== 'cairo-action-cell',
  );

  const tableColumns = isMobile
    ? [
        ...buildMobileColumns(
          columnsWithoutActionCell as TableColumn<KeyedItem<U>>[],
        ),
        ...(actionCellColumn ? [actionCellColumn] : []),
      ]
    : columns;

  const keyedItemsWithTooltip = keyedItems.map((item) => {
    const isDisabled = bulk.isRowCheckboxDisabled(item);
    if (isDisabled) {
      const tooltipContent = bulk.getCheckboxTooltipContent(item);
      if (tooltipContent) {
        return {
          ...item,
          checkboxTooltipContent: tooltipContent,
        };
      }
    }
    return item;
  });

  return (
    <div
      data-hook="collection-table"
      className={wsrTableSt(
        wsrTableClasses.root,
        { resizable: !!resizable },
        st(classes.fullHeight, classes.column),
      )}
    >
      <Table
        {...props}
        skin="neutral"
        withWrapper={false}
        data={keyedItemsWithTooltip}
        viewportRef={stackingRootRef}
        columns={tableColumns}
        onRowClick={onRowClick ? handleRowCLick : undefined}
        // this forces WSR <Table/> to render the loader even when `data.length=0`
        showHeaderWhenEmpty={
          useShowLoaderWhenEmpty &&
          !showRefreshLoader &&
          !showErrorState &&
          !showEmptyState
        }
        hideBulkSelectionCheckbox={
          selectionToolbar ? false : hideBulkSelectionCheckbox
        }
        bulkSelectionCheckboxRef={bulk.bulkSelectionCheckboxRef}
        dragAndDrop={dragAndDrop}
        rowDataHook={(rowData) => `table-row-${rowData.key}`}
        controlled
        horizontalScroll={horizontalScroll}
        stickyColumns={table.getStickyColumnsCount({
          horizontalScroll,
          stickyColumns,
          showSelection,
          stickySelectionColumn,
        })}
        showSelection={showSelection}
        selectedIds={bulk.selectedIds}
        onSelectionStarted={state.toolbar.onSelectionStarted}
        onSelectionChanged={
          onSelectionChanged ??
          ((_selectedIds, _change) => {
            state.toolbar.onSelectionChanged(_selectedIds, _change);
          })
        }
      >
        <CollectionToolbars
          sticky={sticky}
          state={toolbar}
          search={search}
          customColumns={customColumnsProp}
          multiLevelSorting={multiLevelSortingProp}
          views={views}
          title={title}
          tabs={tabs}
          filters={filters}
          selectionToolbar={selectionToolbar}
          dragAndDropReorderModeToolbar={dragAndDropReorderModeToolbar}
          extraToolbar={extraToolbar}
          summaryBar={summaryBar}
          topNotification={
            typeof topNotification === 'function'
              ? () => topNotification({ query: collection.result.originQuery })
              : topNotification
          }
          titleBar={
            <>
              {showBorderBox && <BorderOnlyBox />}
              {!hideTitleBar && (
                <div
                  data-hook="titlebar-a11y-wrapper"
                  ref={(el) => {
                    table.headerElement = el;
                  }}
                  style={{ display: showTitleBar ? undefined : 'none' }}
                >
                  <WSRTable.Titlebar />
                </div>
              )}
            </>
          }
          tableGridSwitchButton={tableGridSwitchButton}
          exportButton={exportButton}
          importButton={importButton}
          tags={tags}
          primaryActionButton={primaryActionButton}
          secondaryActions={secondaryActions}
          moreActions={moreActions}
          visualization={visualization}
        />
        <CollectionProvider value={collection}>
          <Box
            width="100%"
            direction="vertical"
            minHeight={0}
            flex={1}
            verticalAlign="middle"
          >
            {children}
          </Box>
        </CollectionProvider>
      </Table>
    </div>
  );
}

export const CollectionTableWSRTable = observer(_CollectionTableWSRTable);
