import React, { useMemo } from 'react';
import ColumnResizer from './ColumnResizer';
import { columnPinningDefault } from '../constants/columnConfig';

const getPinnedColumnIds = (table) =>
  (table.getState().columnPinning.left || []).filter(Boolean);

const getSortedColumns = (table) => {
  const allLeafColumns = table.getAllLeafColumns();
  const pinnedColumns = getPinnedColumnIds(table);

  return [...allLeafColumns].sort((a, b) => {
    const aIsPinned = pinnedColumns.includes(a.id);
    const bIsPinned = pinnedColumns.includes(b.id);

    if (aIsPinned && bIsPinned) {
      return pinnedColumns.indexOf(a.id) - pinnedColumns.indexOf(b.id);
    }
    if (aIsPinned) return -1;
    if (bIsPinned) return 1;
    return 0;
  });
};

const getColumnId = (header) => {
  //в header.id содержаться колонки по типу depth_idColParent_idChild, а в pinningColumn только idCol, которые закреплены
  //header.id.split('_').at(-1) - получение самой нижней колонки
  let columnId = header?.id?.match(/data\..*$/)?.[0] || header?.id || header;
  columnPinningDefault.left.forEach(colPinned => {
    if (columnId.includes(colPinned)) {
      columnId = colPinned;
    }
  })
  return columnId;
}

// Ширина закреплённых дочерних колонок группового заголовка
const getPinnedColumnsWidth = (header, pinningColumn) => {
  let width = 0;
  for (const leaf of header.getLeafHeaders()) {
    if (pinningColumn.includes(leaf.column.id)) {
      width += leaf.column.getSize();
    } else {
      break;
    }
  }
  return width;
};

const calculateLeftOffset = (table, columnOrHeader) => {
  const columnId = getColumnId(columnOrHeader);
  const pinnedColumns = getPinnedColumnIds(table);
  const currentPinnedIndex = pinnedColumns.indexOf(columnId);

  let leftOffset = 0;

  if (currentPinnedIndex > 0) {
    for (let i = 0; i < currentPinnedIndex; i++) {
      const prevColumn = table.getColumn(pinnedColumns[i]);
      if (prevColumn) {
        leftOffset += prevColumn.getSize();
      }
    }
  }

  return leftOffset;
};

const isColumnPin = (table, header) => {
  const pinningColumn = getPinnedColumnIds(table);
  const columnId = getColumnId(header);
  const isPinned = pinningColumn.includes(columnId);
  return isPinned;
};

const ColumnNumbersRow = ({ table, selectedColumnId, onColumnSelect }) => {
  const sortedColumns = getSortedColumns(table);
  const tableState = table.getState();
  const filteredColumns = sortedColumns.filter(
    (col) =>
      !(col.id in tableState.columnVisibility) ||
      (col.id in tableState.columnVisibility &&
        tableState.columnVisibility[col.id]),
  );

  return (
    <div
      style={{
        display: 'flex',
        position: 'sticky',
        top: 0,
        zIndex: (theme) => theme.zIndex.table + 1,
        backgroundColor: 'white',
      }}
    >
      {filteredColumns.map((column) => (
        <ColumnNumberCell
          key={`col-number-${column.id}`}
          column={column}
          table={table}
          selectedColumnId={selectedColumnId}
          onColumnSelect={onColumnSelect}
        />
      ))}
    </div>
  );
};

const ColumnNumberCell = ({ column, table, selectedColumnId, onColumnSelect }) => {
  const isPinned = isColumnPin(table, column);
  const allLeafColumns = table.getAllLeafColumns();
  const originalIndex = allLeafColumns.findIndex((col) => col.id === column.id);
  const leftOffset = calculateLeftOffset(table, column);
  const selected = selectedColumnId === column.id;

  return (
    <div
      key={`col-number-${column.id}`}
      data-col-select-id={column.id}
      onClick={(e) => {
        e.stopPropagation();
        onColumnSelect?.(column.id);
      }}
      onMouseDown={(e) => e.stopPropagation()}
      style={{
        width: column.getSize(),
        minWidth: column.getSize(),
        maxWidth: column.getSize(),
        padding: '2px 6px',
        textAlign: 'center',
        backgroundColor: selected ? '#589A2F' : '#FBFBFB',
        color: selected ? '#ffffff' : '#5E5E5E',
        boxSizing: 'border-box',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        height: '1.5rem',
        border: '.063rem solid rgba(209, 213, 220, 1)',
        borderBottom: 'none',
        position: isPinned ? 'sticky' : 'relative',
        left: isPinned ? leftOffset : 'auto',
        zIndex: selected ? 16 : isPinned ? 20 : 'auto',
        cursor: 'pointer',
        userSelect: 'none',
      }}
    >
      {originalIndex}
    </div>
  );
};

const getColorBrightness = (hexColor) => {
  if (!hexColor) return 255;
  const color = hexColor.replace('#', '');
  let r, g, b;
  if (color.length === 3) {
    r = parseInt(color[0] + color[0], 16);
    g = parseInt(color[1] + color[1], 16);
    b = parseInt(color[2] + color[2], 16);
  } else if (color.length === 6) {
    r = parseInt(color.substring(0, 2), 16);
    g = parseInt(color.substring(2, 4), 16);
    b = parseInt(color.substring(4, 6), 16);
  } else {
    return 255;
  }
  return (0.299 * r + 0.587 * g + 0.114 * b);
};

const HeaderCell = ({ header, table, onClick, onChangeWidth }) => {
  const column = header.column;
  const pinningColumn = getPinnedColumnIds(table);
  const isGroup = header.subHeaders?.length > 0;
  const isPinned = isColumnPin(table, header);
  const leftOffset = calculateLeftOffset(table, header);
  const headerSize = header.getSize();
  const pinnedBandWidth = isGroup ? getPinnedColumnsWidth(header, pinningColumn) : 0;
  const splitGroup = isGroup && isPinned && pinnedBandWidth > 0 && pinnedBandWidth < headerSize;

  const customBgColor = column.columnDef?.muiTableHeadCellProps?.sx?.backgroundColor;

  const backgroundColor = customBgColor
    ? customBgColor
    : 'rgba(243, 244, 246, 1)';

  const color = useMemo(() => {
    const brightness = getColorBrightness(backgroundColor);
    return brightness < 128 ? '#ffffff' : '#000000';
  }, [backgroundColor]);

  const handleChangeWidth = (deltaWidth) => {
    const size = header.getSize();
    onChangeWidth(header, size + deltaWidth);
  };

  // Вычисляем отступ для текста внутри ячейки
  // Если колонка закреплена, текст должен быть привязан к левому краю ячейки
  // Если колонка не закреплена, текст должен начинаться после всех закрепленных колонок
  const getTextLeftOffset = () => {
    if (isPinned) {
      return '0';
    }
    // Для незакрепленных колонок текст должен начинаться после всех закрепленных
    // Получаем общую ширину всех закрепленных колонок
    const pinnedColumns = getPinnedColumnIds(table);
    let totalPinnedWidth = 0;
    for (const pinnedId of pinnedColumns) {
      const pinnedCol = table.getColumn(pinnedId);
      if (pinnedCol) {
        totalPinnedWidth += pinnedCol.getSize();
      }
    }
    return `${totalPinnedWidth}px`;
  };

  const renderCell = (width, textLeft) => (
    <div style={{ position: 'relative' }}>
      <div
        onClick={() => onClick(header)}
        style={{
          width: width + 'px',
          minWidth: width + 'px',
          maxWidth: width + 'px',
          position: 'relative',
          padding: '4px 6px',
          textAlign: 'center',
          fontWeight: 600,
          fontSize: '12px',
          lineHeight: 1,
          backgroundColor: backgroundColor,
          color: '#424242',
          boxSizing: 'border-box',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          height: '3rem',
          border: '.063rem solid rgba(209, 213, 220, 1)',
        }}
      >
        <div
          style={{
            textAlign: 'center',
            position: 'sticky',
            left: textLeft,
            right: 0,
            paddingRight: '0.5rem',
            paddingLeft: '0.5rem',
            backgroundColor: backgroundColor,
            color: color,
          }}
        >
          {header.isPlaceholder ? null : column.columnDef.header}
        </div>
        <ColumnResizer reportDragDeltaX={handleChangeWidth} />
      </div>
    </div>
  );

  if (splitGroup) {
    return (
      <>
        <div style={{ position: 'sticky', left: leftOffset, zIndex: 21, flexShrink: 0 }}>
          {renderCell(pinnedBandWidth, '0')}
        </div>
        <div style={{ position: 'relative', flexShrink: 0 }}>
          {renderCell(headerSize - pinnedBandWidth, getTextLeftOffset(true))}
        </div>
      </>
    );
  }

  return (
    <div
      style={{
        position: isPinned ? 'sticky' : 'relative',
        left: isPinned ? leftOffset : 'auto',
        zIndex: isPinned ? 21 : 'auto',
      }}
    >
      {renderCell(headerSize, getTextLeftOffset())}
    </div>
  );
};

const FilterRow = ({ table }) => {
  const sortedColumns = getSortedColumns(table);
  const tableState = table.getState();

  const filteredColumns = sortedColumns.filter(
    (col) =>
      !(col.id in tableState.columnVisibility) ||
      (col.id in tableState.columnVisibility &&
        tableState.columnVisibility[col.id]),
  );

  return (
    <div
      style={{
        display: 'flex',
        position: 'sticky',
        top: '1.5rem',
        zIndex: 20,
        backgroundColor: 'white',
      }}
    >
      {filteredColumns.map((column) => (
        <FilterCell key={`filter-${column.id}`} column={column} table={table} />
      ))}
    </div>
  );
};

// Компонент ячейки фильтра
const FilterCell = ({ column, table }) => {
  const isPinned = isColumnPin(table, column);
  const leftOffset = calculateLeftOffset(table, column);

  // Определяем тип фильтра на основе колонки
  const filterVariant = column.columnDef.filterVariant || 'text';

  // Для select фильтра
  const selectOptions = column.columnDef.filterSelectOptions || [];

  const handleFilterChange = (value) => {
    column.setFilterValue(value);
  };

  // Рендер разных типов фильтров
  const renderFilterInput = () => {
    switch (filterVariant) {
      case 'select':
        return (
          <select
            value={column.getFilterValue() ?? ''}
            onChange={(e) => handleFilterChange(e.target.value)}
            style={{
              width: '100%',
              padding: '0.25rem 0.375rem',
              fontSize: '0.6875rem',
              border: '1px solid #ddd',
              borderRadius: '0.25rem',
              backgroundColor: 'white',
            }}
          >
            <option value="">Все</option>
            {selectOptions.map((option) => (
              <option key={option} value={option}>
                {option}
              </option>
            ))}
          </select>
        );

      case 'range': {
        const [min, max] = column.getFilterValue() || ['', ''];
        return (
          <div style={{ display: 'flex', gap: '0.25rem' }}> {/* 4px */}
            <input
              type="number"
              placeholder="От"
              value={min}
              onChange={(e) => column.setFilterValue([e.target.value, max])}
              style={{
                width: '50%',
                padding: '0.25rem',
                fontSize: '0.6875rem'
              }}
            />
            <input
              type="number"
              placeholder="До"
              value={max}
              onChange={(e) => column.setFilterValue([min, e.target.value])}
              style={{
                width: '50%',
                padding: '0.25rem',
                fontSize: '0.6875rem'
              }}
            />
          </div>
        );
      }

      default: // 'text'
        return (
          <input
            type="text"
            value={column.getFilterValue() ?? ''}
            onChange={(e) => handleFilterChange(e.target.value)}
            placeholder="Поиск..."
            style={{
              width: '100%',
              padding: '0.25rem 0.375rem',
              fontSize: '0.6875rem',
              border: '1px solid #ddd',
              borderRadius: '0.25rem',
              boxSizing: 'border-box',
            }}
          />
        );
    }
  };

  return (
    <div
      style={{
        width: column.getSize(),
        minWidth: column.getSize(),
        maxWidth: column.getSize(),
        padding: '4px 6px',
        backgroundColor: isPinned ? '#f5f5f5' : 'white',
        boxSizing: 'border-box',
        height: '2.5rem',
        border: '.063rem solid rgba(209, 213, 220, 1)',
        borderTop: 'none',
        position: isPinned ? 'sticky' : 'relative',
        left: isPinned ? leftOffset : 'auto',
        zIndex: isPinned ? 19 : 'auto',
      }}
    >
      {renderFilterInput()}
    </div>
  );
};

export const TableHead = ({
  table,
  selectedColumnId,
  onColumnSelect,
  onChangeWidth,
  isLoadingData,
}) => {
  const handleHeaderClick = (header) => {
    if (!header.subHeaders?.length && header.column?.id) {
      onColumnSelect?.(header.column.id);
    }
  };

  if (!isLoadingData) {
    return <div></div>
  }

  return (
    <>
      <div
        style={{
          zIndex: (theme) => theme.zIndex.table,
          position: 'relative',
          width: 'max-content',
        }}
      >
        {/* Строка с номерами колонок */}
        <ColumnNumbersRow
          table={table}
          selectedColumnId={selectedColumnId}
          onColumnSelect={onColumnSelect}
        />

        {table.getState().showColumnFilters && (
          <FilterRow table={table} />
        )}

        {/* Существующие строки заголовков */}
        {table.getHeaderGroups().map((headerGroup) => (
          <div key={headerGroup.id} style={{ display: 'flex' }}>
            {headerGroup.headers.map((header) => (
              <React.Fragment key={header.id}>
                <HeaderCell
                  header={header}
                  table={table}
                  onClick={handleHeaderClick}
                  onChangeWidth={onChangeWidth}
                />
              </React.Fragment>
            ))}
          </div>
        ))}
      </div>
    </>
  );
};
