import { useEffect, useRef, useState } from 'react'
import { VariableSizeGrid } from 'react-window'
import { COL_COUNT, ROW_COUNT, SHEET_NAMES, SpreadsheetProps } from '../types'
import { getColumnLabel } from '../utils'
import { CellRenderer } from './CellRenderer'

const Grid = VariableSizeGrid as unknown as React.ComponentType<any>

export const Spreadsheet = ({
  sheetType,
  columnWidths,
  spreadsheetWidths,
  getCachedCellData,
  selectedCell,
  multiSelection,
  activeSheet,
  isEditing,
  editingValue,
  highlightedCells,
  handleCellClick,
  handleCellDoubleClick,
  handleCellChange,
  handleCellReferenceClick,
  handleCellMouseDown,
  handleCellMouseEnter,
  handleCellMouseUp,
  isInEditMode,
  stopEditing,
  setActiveSheet,
  activeCellInputRef,
  containerRefs,
  handleKeyDown,
  headerRefs,
  rowHeaderRefs,
  gridRefs,
  onGridScroll,
  handleColumnResize,
  mergedCells,
  copiedCells,
}: SpreadsheetProps) => {
  const cachedData = getCachedCellData(sheetType)
  const isActiveSheet = activeSheet === sheetType

  const itemData = {
    sheetType,
    widths: columnWidths,
    selectedCell,
    multiSelection,
    activeSheet,
    isEditing,
    editingValue,
    cachedData,
    mergedCells,
    highlightedCells,
    copiedCells,
    handleCellClick,
    handleCellDoubleClick,
    handleCellChange,
    handleCellReferenceClick,
    handleCellMouseDown,
    handleCellMouseEnter,
    handleCellMouseUp,
    isInEditMode,
    stopEditing,
    setActiveSheet,
    activeCellInputRef,
  }

  const parentRef = useRef<HTMLDivElement>(null)
  const [gridSize, setGridSize] = useState({ width: 0, height: 0 })
  const [scrollPos, setScrollPos] = useState({ left: 0, top: 0 })

  useEffect(() => {
    const parent = parentRef.current
    if (!parent) return

    const resizeObserver = new ResizeObserver(() => {
      const { width, height } = parent.getBoundingClientRect()
      const headerHeight =
        parent.querySelector('.column-headers')?.clientHeight || 0
      setGridSize({ width, height: height - headerHeight })
    })

    resizeObserver.observe(parent)
    return () => resizeObserver.disconnect()
  }, [])

  // Вычисляем выделенные строки и колонки для активного листа
  const getSelectedRowsAndCols = () => {
    const selectedRows = new Set<number>()
    const selectedCols = new Set<number>()

    if (isActiveSheet && multiSelection.length > 0) {
      multiSelection.forEach(sel => {
        const top = Math.min(sel.startRow, sel.endRow)
        const bottom = Math.max(sel.startRow, sel.endRow)
        const left = Math.min(sel.startCol, sel.endCol)
        const right = Math.max(sel.startCol, sel.endCol)
        for (let r = top; r <= bottom; r++) selectedRows.add(r)
        for (let c = left; c <= right; c++) selectedCols.add(c)
      })
    }

    return { selectedRows, selectedCols }
  }

  const { selectedRows, selectedCols } = getSelectedRowsAndCols()

  const handleColumnResizeStart =
    (colIndex: number) => (e: React.MouseEvent) => {
      e.preventDefault()
      const startX = e.clientX
      const startWidth = columnWidths[colIndex]

      const handleMouseMove = (me: MouseEvent) => {
        const newWidth = startWidth + (me.clientX - startX)
        handleColumnResize(sheetType, colIndex, newWidth)
      }

      const handleMouseUp = () => {
        document.removeEventListener('mousemove', handleMouseMove)
        document.removeEventListener('mouseup', handleMouseUp)
      }

      document.addEventListener('mousemove', handleMouseMove)
      document.addEventListener('mouseup', handleMouseUp)
    }

  // Вычисляем границы множественного выделения
  const getSelectionBounds = () => {
    if (!isActiveSheet || multiSelection.length === 0) return null

    return {
      topRow: Math.min(
        ...multiSelection.map(sel => Math.min(sel.startRow, sel.endRow))
      ),
      bottomRow: Math.max(
        ...multiSelection.map(sel => Math.max(sel.startRow, sel.endRow))
      ),
      leftCol: Math.min(
        ...multiSelection.map(sel => Math.min(sel.startCol, sel.endCol))
      ),
      rightCol: Math.max(
        ...multiSelection.map(sel => Math.max(sel.startCol, sel.endCol))
      ),
    }
  }

  const selectionBounds = getSelectionBounds()

  const renderSelectionOverlay = () => {
    if (!selectionBounds) return null

    const topPx = selectionBounds.topRow * 28 - scrollPos.top
    const heightPx =
      (selectionBounds.bottomRow - selectionBounds.topRow + 1) * 28
    const leftPx =
      columnWidths
        .slice(0, selectionBounds.leftCol)
        .reduce((a, b) => a + b, 0) - scrollPos.left
    const widthPx = columnWidths
      .slice(selectionBounds.leftCol, selectionBounds.rightCol + 1)
      .reduce((a, b) => a + b, 0)

    return (
      <div
        style={{
          position: 'absolute',
          top: topPx,
          left: leftPx,
          width: widthPx,
          height: heightPx,
          border: '2px solid hsl(var(--primary))',
          pointerEvents: 'none',
          boxSizing: 'border-box',
          zIndex: 5,
        }}
      />
    )
  }

  return (
    <div
      ref={parentRef}
      className="flex min-w-0 flex-col overflow-hidden"
      style={{
        flexBasis: `${spreadsheetWidths[SHEET_NAMES[sheetType]] * 100}%`,
      }}
      onClick={() => setActiveSheet(sheetType)}
    >
      <div
        ref={el => {
          containerRefs.current[sheetType] = el
        }}
        className="flex h-full flex-col overflow-hidden border bg-card shadow-sm"
        onKeyDown={handleKeyDown}
        style={{ userSelect: isEditing ? 'text' : 'none' }}
        tabIndex={0}
      >
        <div className="flex flex-1">
          {/* Row Headers */}
          <div className="flex-shrink-0 bg-muted">
            <div className="relative flex h-7 w-10 items-center justify-center border-b border-r border-border">
              <div className="absolute inset-0 flex items-end justify-end p-0.5">
                <span
                  className={`flex h-3 w-3 items-center justify-center rounded-sm text-[9px] font-medium text-white ${
                    sheetType === 'report'
                      ? 'bg-primary/70'
                      : 'bg-emerald-500/70'
                  }`}
                >
                  {SHEET_NAMES[sheetType]}
                </span>
              </div>
            </div>
            <div
              ref={el => {
                rowHeaderRefs.current[sheetType] = el
              }}
              className="overflow-y-hidden"
              style={{ height: gridSize.height }}
            >
              <div>
                {Array.from({ length: ROW_COUNT }).map((_, rowIndex) => {
                  const isActiveRow =
                    (selectedCell?.row === rowIndex && isActiveSheet) ||
                    selectedRows.has(rowIndex)
                  return (
                    <div
                      key={rowIndex}
                      className={`flex h-7 w-10 items-center justify-center border-b border-r border-border text-xs font-medium ${
                        isActiveRow
                          ? 'bg-primary/15 font-medium text-foreground'
                          : 'text-muted-foreground'
                      }`}
                    >
                      {rowIndex + 1}
                    </div>
                  )
                })}
              </div>
            </div>
          </div>

          <div className="flex-1 overflow-hidden">
            {/* Column Headers */}
            <div
              ref={el => {
                headerRefs.current[sheetType] = el
              }}
              className="column-headers overflow-x-hidden"
            >
              <div className="flex">
                {Array.from({ length: COL_COUNT }).map((_, colIndex) => {
                  const isActiveColumn =
                    (selectedCell?.col === colIndex && isActiveSheet) ||
                    selectedCols.has(colIndex)

                  return (
                    <div
                      key={colIndex}
                      className={`relative flex h-7 flex-shrink-0 items-center justify-center border-b border-r border-border bg-muted text-center text-xs font-medium ${
                        isActiveColumn
                          ? 'bg-primary/15 font-medium text-foreground'
                          : 'text-muted-foreground'
                      }`}
                      style={{ width: columnWidths[colIndex] }}
                    >
                      {getColumnLabel(colIndex)}
                      <div
                        className="resizer absolute right-0 top-0 h-full w-1 cursor-col-resize hover:bg-primary hover:bg-opacity-50"
                        onMouseDown={handleColumnResizeStart(colIndex)}
                      />
                    </div>
                  )
                })}
              </div>
            </div>

            {/* Grid */}
            <div className="relative min-h-0 flex-1">
              {renderSelectionOverlay()}
              <Grid
                ref={(el: any) => {
                  if (gridRefs.current) {
                    gridRefs.current[sheetType] = el
                  }
                }}
                columnCount={COL_COUNT}
                rowCount={ROW_COUNT}
                columnWidth={(index: number) => columnWidths[index]}
                rowHeight={() => 28}
                height={gridSize.height}
                width={gridSize.width}
                itemData={itemData}
                overscanColumnCount={20}
                overscanRowCount={10}
                onScroll={(e: any) => {
                  setScrollPos({ left: e.scrollLeft, top: e.scrollTop })
                  onGridScroll(sheetType, e)
                }}
              >
                {CellRenderer}
              </Grid>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}
