import React, { useMemo, useRef } from 'react';
import { observer } from 'mobx-react-lite';
import { GlobalAudioPlayer } from '@wix/patterns-fields';
import { PatternsFieldsProvider } from '../../providers/PatternsFieldsProvider';
import type { FiltersMap, OptionalFiltersMap } from '@wix/bex-core';
import type { FieldsSourceProvider } from '../fieldsSourceProvider';
import { TableVirtual, type TableVirtualProps } from '../Table/TableVirtual';
import {
  type EditableColumn,
  EditableTableState,
} from '../../state/EditableTable';
import { EditableCell } from './EditableCell';
import { EditableTableContextMenu } from './EditableTableContextMenu';
import { useEditableTableContextMenu } from './useEditableTableContextMenu';
import { MessageActionModal } from '../ActionModal';
import { FieldManagementModals } from '../CustomFieldsPanel/FieldManagementModals';
import { useEditableTableCollectionSyncProps } from './useEditableTableCollectionSyncProps';
import { useKeyboardNavigation } from './useKeyboardNavigation';
import { useClipboardHandler } from './useClipboardHandler';
import { useClearFocusOnBlur } from './useClearFocusOnBlur';
import { useMouseSweepSelection } from './useMouseSweepSelection';
import { AddItemRow } from './AddItemRow';
import { useAddRow } from './useAddRow';
import type { TableColumn } from '../../model';
import { useHeaderActions } from './useHeaderActions';

export interface EditableTableProps<
  T,
  F extends FiltersMap = OptionalFiltersMap,
> extends Omit<
    TableVirtualProps<T, F>,
    | 'columns'
    | 'state'
    | 'onRowClick'
    | 'forceResize'
    | 'horizontalScroll'
    | 'showSelection'
    | 'showRowNumbers'
    | 'showAddFieldButton'
  > {
  /** EditableTableState instance, created via useEditableTableCollection */
  state: EditableTableState<T, F>;

  /** Column definitions with cell types. When a `fieldsSource` is wired, its
   *  columns are added by the state, so pass `[]` for source-only tables. */
  columns: EditableColumn<T>[];

  /** A fields source (e.g. `dataExtensionTableSource(...)`) whose fields become
   *  columns and whose field management wires into the table. Schema sources
   *  attach via the `@wix/patterns/schema` collection hooks instead. */
  fieldsSource?: FieldsSourceProvider;

  /** When true, hides the built-in header actions popover for all columns. */
  hideHeaderActions?: boolean;

  /** data-hook for testkit selectors */
  dataHook?: string;
}

function _EditableTable<T, F extends FiltersMap = OptionalFiltersMap>(
  props: EditableTableProps<T, F>,
) {
  const {
    state,
    columns,
    fieldsSource: _fieldsSource,
    hideHeaderActions,
    dataHook,
    children,
    ...tableBaseProps
  } = props;

  useEditableTableCollectionSyncProps(props);

  const editableColumns = useMemo(
    () => [...columns, ...state.sourceColumns],
    [columns, state.sourceColumns],
  );

  const containerRef = useRef<HTMLDivElement>(null);

  const keyboard = useKeyboardNavigation(state);
  useClipboardHandler(state, containerRef);
  const { onFocus, onBlur } = useClearFocusOnBlur(state.cellInteraction);
  useMouseSweepSelection(state, containerRef);

  const builtInActions = useHeaderActions(
    state,
    editableColumns,
    hideHeaderActions,
  );

  const { showAddItemRow, handleAddItem } = useAddRow(state);

  const tableColumns = useMemo(
    () =>
      editableColumns.map((col) => ({
        ...col,
        name: col.name ?? (typeof col.title === 'string' ? col.title : col.id),
        titleSuffix: builtInActions[col.id],
        render: (_item: T, rowNum: number) => {
          const rowKey = state.keyedItems[rowNum]?.key;
          return rowKey ? (
            <EditableCell state={state} rowKey={rowKey} columnId={col.id} />
          ) : null;
        },
      })) as TableColumn<T>[],
    [editableColumns, state, builtInActions],
  );

  const contextMenu = useEditableTableContextMenu(state.cellInteraction);

  return (
    <PatternsFieldsProvider>
      <div
        ref={containerRef}
        data-hook={dataHook}
        tabIndex={0}
        onKeyDown={keyboard.onKeyDown}
        onFocus={onFocus}
        onBlur={onBlur}
        onContextMenu={contextMenu.handleContextMenu}
      >
        <TableVirtual
          {...tableBaseProps}
          state={state.tableState}
          columns={tableColumns}
          forceResize
          horizontalScroll
          showSelection
          showRowNumbers
          showAddFieldButton
        >
          {showAddItemRow && <AddItemRow onAdd={handleAddItem} />}
        </TableVirtual>
      </div>
      <EditableTableContextMenu
        state={state}
        position={contextMenu.position}
        cell={contextMenu.cell}
        menuRef={contextMenu.menuRef}
        onClose={contextMenu.handleClose}
      />
      {state.deleteConfirmModal.value && (
        <MessageActionModal
          state={state.deleteConfirmModal}
          {...state.deleteConfirmModal.value}
        />
      )}
      {state.toolbar.collectionFieldsSource && (
        <FieldManagementModals source={state.toolbar.collectionFieldsSource} />
      )}
      {children}
      <GlobalAudioPlayer />
    </PatternsFieldsProvider>
  );
}

export const EditableTable = observer(_EditableTable);
