// 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 { useColumnSettings } from './hooks/useColumnSettings';
import { useTableScale } from './hooks/useTableScale';
import { useHeaderPortal } from './hooks/useHeaderPortal';
import {
  BASE_TABLE_CONFIG,
  getTableHeadCellStyles,
  getTablePaperStyles,
} from './constants/tableConfig';
import { useRealtime } from './contexts/RealtimeContext';
import { toast } from 'react-toastify';
import { CircularProgress } from '@mui/material';

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 [selectedColumn, setSelectedColumn] = useState();
  const [rowSelection, setRowSelection] = useState({});
  const [isLoadingData, setIsLoadingData] = useState(false);
  const [isPending, startTransition] = useTransition();
  const [editingCell, setEditingCell] = useState(null);

  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 { sizeMult, setSizeMult, tableScaleStyle, tableWrapperStyle } =
    useTableScale();

  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 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]);

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

  // Конфигурация таблицы
  const tableConfig = useMemo(
    () => ({
      ...BASE_TABLE_CONFIG,
      columns,
      data: data,
      enableRowVirtualization: true,
      enableColumnVirtualization: true,
      rowVirtualizerOptions: {
        overscan: 30,
        scrollPaddingStart: 0,
        scrollPaddingEnd: 0,
      },
      onEditingCellChange: (cell) => {
        if (cell) {
          if (editingCell) return;
          contextStartEditing?.(cell.row, cell.column);
        } else {
          contextEndEditing?.(editingCell.row, editingCell.column);
        }
      },
      columnVirtualizerOptions: ({ table }) => ({
        overscan: 1,
        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.columnDef.size;

          }
          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: getTableHeadCellStyles,
      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]);
  console.log(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 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 expense_item_id = row.original.data.line_id;
    contextDeleteRow(expense_item_id)
    setRowSelection({});
  }, [rowSelection, table])

  return (
    <>
      <SettingsPanel
        selectedColumn={selectedColumn}
        table={table}
        columns={columns}
        onPinColumn={handlePinColumn}
        onUnpinColumn={handleUnpinColumn}
        onToggleColumnVisibility={handleToggleColumnVisibility}
        columnVisibility={columnVisibility}
        onChangeSizeMult={setSizeMult}
        onGlobalFilterChange={handleGlobalFilterChange}
        sizeMult={sizeMult}
        onChangeShowColumnFilters={setShowColumnFilters}
        onAddRow={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} />

            {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 }}
                  onHeaderSelect={setSelectedColumn}
                  selectHeader={selectedColumn}
                  onChangeWidth={handleSetColumnWidth}
                  isLoadingData={isLoadingData}
                />,
                headerPortalRef.current,
              )}
          </div>
        </div>
      </div>
    </>
  );
};

export default React.memo(RealtimeTable);