// components/RealtimeTable/index.js
import React, { useState, useMemo, useRef, useEffect, useCallback, useTransition } from 'react';
import { createPortal } from 'react-dom';
import {
  useMaterialReactTable,
  MaterialReactTable,
} from 'material-react-table';

import useRealtimeData from './hooks/useRealtimeData';
import { getTableColumns } from './tableColumns';
import { Cell, EditCell } from './index';
import { TableHead } from './TableHead/TableHead';
import SettingsPanel from './SettingPanel/SettingPanel';
import { ColumnSelectionOverlay } from './ColumnSelectionOverlay/ColumnSelectionOverlay';

import { useColumnSettings } from './hooks/useColumnSettings';
import { useTableScale } from './hooks/useTableScale';
import { useHeaderPortal } from './hooks/useHeaderPortal';
import {
  BASE_TABLE_CONFIG,
  getTableBodyCellProps,
  getTablePaperStyles,
  TABLE_ROW_HEIGHT,
} from './constants/tableConfig';
import { useRealtime } from './contexts/RealtimeContext';
import { toast } from 'react-toastify';
import { CircularProgress } from '@mui/material';
import { additionVspRowTable } from './constants/addingRowConfig';
import { SelectVspModal } from './Modals/selectVspModal';
import { getRowId } from './utils/rowUtils';

const RealtimeTable = ({ formType, formId, sheetName, direction }) => {
  const { data, setData, isLoading: isTableLoading, editingCells: dataEditingCells } = useRealtimeData(formId, sheetName, direction);
  const [globalFilter, setGlobalFilter] = useState('');
  const [showColumnFilters, setShowColumnFilters] = useState(false);
  const [selectedColumnId, setSelectedColumnId] = useState();
  const [rowSelection, setRowSelection] = useState({});
  const [isLoadingData, setIsLoadingData] = useState(false);
  const [isPending, startTransition] = useTransition();
  const [editingCell, setEditingCell] = useState(null);

  const [isOpenModalSelectVsp, setIsOpenModalSelectVsp] = useState(false);

  const isVspAdditionRow = useMemo(() => {
    if (!formType || !sheetName) return false;
    if (!additionVspRowTable[formType]) return false;
    return additionVspRowTable[formType].includes(sheetName);
  }, [formType, sheetName]);

  const handleGlobalFilterChange = (value) => {
    startTransition(() => {
      setGlobalFilter(value);
    });
  };

  const {
    isConnected,
    isAuthenticated,
    subscribeToErrors,
    subscribeToAuthSuccess,
    error: wsError,
    updateCell: contextUpdateCell,
    addRow: contextAddRow,
    deleteRow: contextDeleteRow,
    startEditing: contextStartEditing,
    endEditing: contextEndEditing,
  } = useRealtime();

  const {
    columnSizing,
    columnPinning,
    columnVisibility,
    setColumnSizing,
    setColumnPinning,
    handlePinColumn,
    handleUnpinColumn,
    handleSetColumnWidth,
    handleToggleColumnVisibility,
  } = useColumnSettings(`${formId}_${formType}_${sheetName}_${direction}`);

  const { headerPortalRef, containerRef } = useHeaderPortal();
  const rowVirtualizerRef = useRef(null);

  const { sizeMult, setSizeMult, tableScaleStyle, tableWrapperStyle } =
    useTableScale();

  useEffect(() => {
    rowVirtualizerRef.current?.measure?.();
  }, [sizeMult]);

  const [columnsConfig, setColumnsConfig] = useState(null);

  useEffect(() => {
    const loadConfig = async () => {
      try {
        const { config } = await import(`./constants/${formType}/${sheetName}.js`);
        setColumnsConfig(config.config);
      } catch (error) {
        console.error(`Failed to load config for ${formType}/${sheetName}:`, error);
        setColumnsConfig({ columns: [], colors: {} });
      }
    };

    loadConfig();
  }, [formType, sheetName]);

  const handleUpdateCell = useCallback(async (row, column, value) => {
    return await contextUpdateCell(row, column, value);
  }, [contextUpdateCell]);

  const handleClickRowCell = useCallback((rowId) => {
    setRowSelection((prev) => ({
      [rowId]: !prev[rowId],
    }));
  }, [])

  const handleColumnSelect = useCallback((columnId) => {
    setSelectedColumnId((prev) => {
      const next = prev === columnId ? undefined : columnId;
      return next;
    });
  }, []);

  useEffect(() => {
    if (!selectedColumnId) return;

    const handleDocumentClick = (e) => {
      if (e.target.closest('[data-col-select-id]')) return;
      if (e.target.closest('[data-pin-panel]')) return;

      setSelectedColumnId(undefined);
    };

    document.addEventListener('mousedown', handleDocumentClick);
    return () => document.removeEventListener('mousedown', handleDocumentClick);
  }, [selectedColumnId]);

  const columns = useMemo(() => {
    if (!columnsConfig || !columnsConfig.columns) return [];
    try {
      return getTableColumns({
        Cell,
        EditCell,
        columnsConfig,
        onCellUpdate: handleUpdateCell,
        onCellNumberClick: handleClickRowCell,
        onCellUpdateError: (rowId, columnId, error) => {
          console.error(`Error updating cell ${rowId}_${columnId}:`, error);
          toast.error('Ошибка обновления ячейки')
        }
      });
    } catch (error) {
      console.error('Error creating columns:', error);
      return [];
    }
  }, [columnsConfig, handleUpdateCell, handleClickRowCell]);

  const tableMeta = useMemo(() => ({
    updateCell: handleUpdateCell,
    selectedColumnId,
  }), [handleUpdateCell, selectedColumnId]);

  // Конфигурация таблицы
  const tableConfig = useMemo(
    () => ({
      ...BASE_TABLE_CONFIG,
      columns,
      data: data,
      enableRowVirtualization: true,
      enableColumnVirtualization: true,
      rowVirtualizerInstanceRef: rowVirtualizerRef,
      rowVirtualizerOptions: {
        overscan: 30,
        scrollPaddingStart: 0,
        scrollPaddingEnd: 0,
        estimateSize: () => TABLE_ROW_HEIGHT,
        measureElement: (el) => el?.offsetHeight || TABLE_ROW_HEIGHT,
      },
      onEditingCellChange: (cell) => {
        if (cell) {
          if (editingCell) return;
          contextStartEditing?.(cell.row, cell.column);
        } else {
          contextEndEditing?.(editingCell.row, editingCell.column);
        }
      },
      columnVirtualizerOptions: ({ table }) => ({
        overscan: 10,
        measureElement: (el) => {
          if (!el) return 150;
          const index = Number(el?.getAttribute?.('data-index'));
          const isPinned = Boolean(el?.getAttribute?.('data-pinned'));
          if (isPinned) {
            const colId = table.getState().columnPinning.left[index];
            const column = table.getColumn(colId);
            return column?.getSize() ?? 150;
          }
          const allCols = [...table.getLeftVisibleLeafColumns(), ...table.getCenterVisibleLeafColumns()]
          return allCols[index]?.getSize() ?? 150;

        },
      }),
      enableRowSelection: true,
      onRowSelectionChange: setRowSelection,
      onColumnSizingChange: setColumnSizing,
      onColumnPinningChange: setColumnPinning,
      onGlobalFilterChange: handleGlobalFilterChange,
      state: {
        columnSizing,
        columnPinning,
        columnVisibility,
        globalFilter,
        showColumnFilters,
        rowSelection,
        editingCell,
      },
      initialState: {
        expanded: true,
      },
      meta: tableMeta,
      muiTableHeadCellProps: {
        sx: { boxSizing: 'border-box' },
      },
      muiTableBodyCellProps: getTableBodyCellProps,
      muiTableHeadProps: {
        sx: {
          display: 'table-header-group',
          height: '1px',
          minHeight: '1px',
          maxHeight: '1px',
          visibility: 'hidden',
        },
      },
      muiTablePaperProps: getTablePaperStyles(),
      muiTableContainerProps: {
        ref: containerRef,
        sx: {
          position: 'relative',
          contain: 'layout',
          minHeight: '100%',
          '& .MuiTable-root': { position: 'relative' },
        },
      },
      muiTableHeadCellFilterTextFieldProps: {
        placeholder: 'Поиск...',
        size: 'small',
      },
    }),
    [
      columns,
      data,
      setColumnSizing,
      setColumnPinning,
      columnSizing,
      columnPinning,
      columnVisibility,
      globalFilter,
      showColumnFilters,
      containerRef,
      tableMeta,
      rowSelection,
      editingCell
    ],
  );

  const table = useMaterialReactTable(tableConfig);

  useEffect(() => {
    if (!dataEditingCells || !dataEditingCells.line_id) {
      setEditingCell(null);
      return;
    }
    if (editingCell) return;
    const rowId = dataEditingCells.line_id;
    const columnId = dataEditingCells.column;
    try {
      const row = table.getRow(rowId);
      const column = table.getColumn(columnId);
      const cell = row?.getVisibleCells().find(c => c.column.id === columnId);
      if (cell) {
        setEditingCell(cell);
      }
    } catch (error) {
      console.error(error);
      toast.error('Ошибка редактирования ячейки');
    }
  }, [dataEditingCells, editingCell]);

  useEffect(() => {
    if (table && data && columns.length !== 0) {
      setIsLoadingData(true)
    }
  }, [data, columns, table])

  useEffect(() => {
    // Принудительно обновляем состояние закрепленных колонок
    // если так не сделать при скролле будут пропадать закрепленные колонки
    if (columnPinning && Object.keys(columnPinning).length > 0) {
      const timer = setTimeout(() => {
        setColumnPinning(prev => ({ ...prev }));
      }, 100);

      return () => clearTimeout(timer);
    }
  }, []);

  const handleAddRow = useCallback(() => {
    const allRows = table.getRowModel().rows;

    const selectedRows = allRows.filter(row => rowSelection[row.id]);
    if (selectedRows.length === 0) {
      toast.error('Выделите строку для вставки');
      return;
    }
    const row = selectedRows[0];
    const expense_item_id = row.original.data.header.expense_item_id;
    contextAddRow({ expense_item_id: expense_item_id })
  }, [rowSelection, table])

  const handleAddVspRow = useCallback((vsp_id) => {
    contextAddRow({ vsp_id: vsp_id });
  }, [rowSelection, table]);

  const handleOpenModalSelectVsp = useCallback(() => {
    setIsOpenModalSelectVsp(true);
  }, [rowSelection, table])

  const handleDeleteRow = useCallback(() => {
    const allRows = table.getRowModel().rows;

    const selectedRows = allRows.filter(row => rowSelection[row.id]);
    if (selectedRows.length === 0) {
      toast.error('Выделите строку для удаления');
      return;
    }
    const row = selectedRows[0];
    const rowId = getRowId(row);
    contextDeleteRow(rowId);
    setRowSelection({});
  }, [rowSelection, table])

  return (
    <>
      <SettingsPanel
        selectedColumnId={selectedColumnId}
        columnPinning={columnPinning}
        table={table}
        columns={columns}
        onPinColumn={handlePinColumn}
        onUnpinColumn={handleUnpinColumn}
        onToggleColumnVisibility={handleToggleColumnVisibility}
        columnVisibility={columnVisibility}
        onChangeSizeMult={setSizeMult}
        onGlobalFilterChange={handleGlobalFilterChange}
        sizeMult={sizeMult}
        onChangeShowColumnFilters={setShowColumnFilters}
        onAddRow={isVspAdditionRow ? handleOpenModalSelectVsp : handleAddRow}
        onDeleteRow={handleDeleteRow}
        isLoadingData={isLoadingData}
        formId={formId}
        sheetName={sheetName}
        direction={direction}
      />

      <div style={tableWrapperStyle}>
        <div style={tableScaleStyle}>
          <div
            style={{
              position: 'relative',
              width: '100%',
              flex: 1,
              minHeight: 0,
              height: '100%',
            }}
          >
            <MaterialReactTable table={table} />

            <ColumnSelectionOverlay
              selectedColumnId={selectedColumnId}
              containerRef={containerRef}
              scale={sizeMult}
              columnSizing={columnSizing}
              columnPinning={columnPinning}
              showColumnFilters={showColumnFilters}
            />

            {isTableLoading && (
              <div
                style={{
                  position: 'absolute',
                  inset: 0,
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  background: 'rgba(255, 255, 255, 0.6)',
                  zIndex: 2,
                }}
              >
                <CircularProgress />
              </div>
            )}

            {headerPortalRef.current &&
              createPortal(
                <TableHead
                  table={table}
                  style={{ zIndex: (theme) => theme.zIndex.modal - 1 }}
                  selectedColumnId={selectedColumnId}
                  onColumnSelect={handleColumnSelect}
                  onChangeWidth={handleSetColumnWidth}
                  isLoadingData={isLoadingData}
                />,
                headerPortalRef.current,
              )}
          </div>
        </div>
      </div>
      <SelectVspModal
        isOpen={isOpenModalSelectVsp}
        onClose={() => setIsOpenModalSelectVsp(false)}
        formId={formId}
        onSelect={handleAddVspRow}
        // vspOptions={}
        // selectedVSP={}
        title="Выбор ВСП"
      />
    </>
  );
};

export default React.memo(RealtimeTable);