import React from 'react'
import { comparePValues, formatPValue, isPValueColumn } from '../pValues'
import TruncatedCellContent from './TruncatedCellContent'

const LIMIAR_RENDERIZACAO_VIRTUAL = 1500
const ESTIMATIVA_ALTURA_LINHA_PX = 68
const OVERSCAN_LINHAS = 40
const MIN_JANELA_LINHAS = 220
const SORT_COLLATOR = new Intl.Collator('pt-BR', { numeric: true, sensitivity: 'base' })

function normalizeSortText(value) {
  if (value === null || value === undefined) return ''
  return String(value).trim()
}

function parseSortableNumber(value) {
  if (typeof value === 'number') {
    return Number.isFinite(value) ? value : null
  }
  const raw = normalizeSortText(value)
  if (!raw) return null

  const compact = raw
    .replace(/\u00a0/g, '')
    .replace(/\s+/g, '')
    .replace('%', '')
  if (!compact) return null

  const candidates = [
    compact,
    compact.replace(/\./g, '').replace(',', '.'),
    compact.replace(/,/g, ''),
  ]
  for (let index = 0; index < candidates.length; index += 1) {
    const parsed = Number(candidates[index])
    if (Number.isFinite(parsed)) return parsed
  }
  return null
}

function DataTable({
  table,
  maxHeight = 320,
  highlightedRowIndices = null,
  highlightIndexColumn = 'INDICE',
  highlightClassName = 'table-row-highlight',
}) {
  if (!table || !table.columns || !table.rows) {
    return <div className="empty-box">Sem dados.</div>
  }

  const columns = Array.isArray(table.columns) ? table.columns : []
  const sourceRows = Array.isArray(table.rows) ? table.rows : []
  const [sortConfig, setSortConfig] = React.useState(null)
  const sortedRows = React.useMemo(() => {
    if (!sortConfig || !columns.includes(sortConfig.column)) return sourceRows

    const direction = sortConfig.direction === 'desc' ? 'desc' : 'asc'
    const column = sortConfig.column
    const indexedRows = sourceRows.map((row, index) => ({ row, index }))

    indexedRows.sort((leftItem, rightItem) => {
      const leftValue = leftItem.row?.[column]
      const rightValue = rightItem.row?.[column]
      const leftText = normalizeSortText(leftValue)
      const rightText = normalizeSortText(rightValue)
      const leftEmpty = leftText === ''
      const rightEmpty = rightText === ''
      if (leftEmpty || rightEmpty) {
        if (leftEmpty && rightEmpty) return leftItem.index - rightItem.index
        return leftEmpty ? 1 : -1
      }

      const leftNumber = parseSortableNumber(leftValue)
      const rightNumber = parseSortableNumber(rightValue)
      let comparison = 0
      const pValueComparison = isPValueColumn(column)
        ? comparePValues(leftValue, rightValue)
        : null
      if (pValueComparison !== null) {
        comparison = pValueComparison
      } else if (leftNumber !== null && rightNumber !== null) {
        if (leftNumber < rightNumber) comparison = -1
        else if (leftNumber > rightNumber) comparison = 1
      } else {
        comparison = SORT_COLLATOR.compare(leftText, rightText)
      }

      if (comparison === 0) return leftItem.index - rightItem.index
      return direction === 'asc' ? comparison : -comparison
    })

    return indexedRows.map((item) => item.row)
  }, [columns, sourceRows, sortConfig])
  const totalRows = sortedRows.length
  const colSpan = Math.max(1, columns.length)
  const virtualizacaoAtiva = totalRows > LIMIAR_RENDERIZACAO_VIRTUAL
  const wrapperRef = React.useRef(null)
  const [scrollTop, setScrollTop] = React.useState(0)
  const [viewportHeight, setViewportHeight] = React.useState(Number(maxHeight) || 320)
  const tableIdentity = React.useMemo(() => {
    const colunas = columns.join("|")
    return `${colunas}::${sourceRows.length}`
  }, [columns, sourceRows.length])

  React.useEffect(() => {
    setSortConfig((prev) => {
      if (!prev) return prev
      if (!columns.includes(prev.column)) return null
      return prev
    })
  }, [columns])

  React.useEffect(() => {
    setScrollTop(0)
    if (wrapperRef.current) {
      wrapperRef.current.scrollTop = 0
      setViewportHeight(wrapperRef.current.clientHeight || Number(maxHeight) || 320)
    }
  }, [tableIdentity, maxHeight])

  React.useEffect(() => {
    if (!wrapperRef.current) return undefined
    const target = wrapperRef.current
    if (typeof ResizeObserver === 'undefined') return undefined
    const observer = new ResizeObserver(() => {
      setViewportHeight(target.clientHeight || Number(maxHeight) || 320)
    })
    observer.observe(target)
    return () => observer.disconnect()
  }, [maxHeight])

  const onWrapperScroll = React.useCallback((event) => {
    if (!virtualizacaoAtiva) return
    setScrollTop(event.currentTarget.scrollTop || 0)
  }, [virtualizacaoAtiva])
  const onToggleSort = React.useCallback((column) => {
    setSortConfig((prev) => {
      if (!prev || prev.column !== column) {
        return { column, direction: 'asc' }
      }
      if (prev.direction === 'asc') {
        return { column, direction: 'desc' }
      }
      return null
    })
  }, [])

  const alturaViewport = Math.max(1, Number(viewportHeight) || Number(maxHeight) || 320)
  const linhasVisiveis = Math.max(1, Math.ceil(alturaViewport / ESTIMATIVA_ALTURA_LINHA_PX))
  const janelaLinhas = Math.max(MIN_JANELA_LINHAS, linhasVisiveis + (OVERSCAN_LINHAS * 2))

  let startIndex = 0
  let endIndex = totalRows
  if (virtualizacaoAtiva) {
    const primeiraLinhaVisivel = Math.max(0, Math.floor(scrollTop / ESTIMATIVA_ALTURA_LINHA_PX))
    startIndex = Math.max(0, primeiraLinhaVisivel - OVERSCAN_LINHAS)
    endIndex = Math.min(totalRows, startIndex + janelaLinhas)
    if (endIndex - startIndex < janelaLinhas && startIndex > 0) {
      startIndex = Math.max(0, endIndex - janelaLinhas)
    }
  }

  const rowsToRender = virtualizacaoAtiva
    ? sortedRows.slice(startIndex, endIndex)
    : sortedRows
  const topSpacerHeight = virtualizacaoAtiva ? startIndex * ESTIMATIVA_ALTURA_LINHA_PX : 0
  const bottomSpacerHeight = virtualizacaoAtiva ? Math.max(0, (totalRows - endIndex) * ESTIMATIVA_ALTURA_LINHA_PX) : 0

  const highlightedSet = Array.isArray(highlightedRowIndices) && highlightedRowIndices.length > 0
    ? new Set(highlightedRowIndices.map((item) => String(item)))
    : null

  return (
    <div ref={wrapperRef} className="table-wrapper" style={{ maxHeight }} onScroll={onWrapperScroll}>
      <table>
        <thead>
          <tr>
            {columns.map((col) => {
              const isActiveSort = sortConfig?.column === col
              const direction = isActiveSort ? sortConfig.direction : null
              const sortIndicator = !direction ? '-' : (direction === 'asc' ? '^' : 'v')
              const ariaSort = direction === 'asc' ? 'ascending' : direction === 'desc' ? 'descending' : 'none'
              return (
                <th key={col} aria-sort={ariaSort}>
                  <button
                    type="button"
                    className={`table-sort-trigger${isActiveSort ? ' is-active' : ''}`}
                    onClick={() => onToggleSort(col)}
                    title={isActiveSort ? `Ordenado por ${col} (${direction === 'asc' ? 'crescente' : 'decrescente'})` : `Ordenar por ${col}`}
                  >
                    <span className="table-sort-label">{col}</span>
                    <span className="table-sort-indicator" aria-hidden="true">{sortIndicator}</span>
                  </button>
                </th>
              )
            })}
          </tr>
        </thead>
        <tbody>
          {virtualizacaoAtiva && topSpacerHeight > 0 ? (
            <tr className="table-virtual-spacer" aria-hidden="true">
              <td colSpan={colSpan} style={{ height: `${topSpacerHeight}px` }} />
            </tr>
          ) : null}
          {rowsToRender.map((row, i) => {
            const absoluteIndex = virtualizacaoAtiva ? startIndex + i : i
            const rowIndex = row?.[highlightIndexColumn] ?? row?.INDICE ?? row?.['Índice'] ?? row?.Indice ?? row?._index
            const rowClassName = highlightedSet && rowIndex != null && highlightedSet.has(String(rowIndex))
              ? highlightClassName
              : ''
            return (
              <tr key={absoluteIndex} className={rowClassName}>
                {columns.map((col) => (
                  <td key={`${absoluteIndex}-${col}`}>
                    <TruncatedCellContent tooltipContent={String(row[col] ?? '')}>
                      {isPValueColumn(col) ? formatPValue(row[col]) : String(row[col] ?? '')}
                    </TruncatedCellContent>
                  </td>
                ))}
              </tr>
            )
          })}
          {virtualizacaoAtiva && bottomSpacerHeight > 0 ? (
            <tr className="table-virtual-spacer" aria-hidden="true">
              <td colSpan={colSpan} style={{ height: `${bottomSpacerHeight}px` }} />
            </tr>
          ) : null}
        </tbody>
      </table>
      {virtualizacaoAtiva ? (
        <div className="table-hint">
          Exibindo janela virtual com {rowsToRender.length} linhas de {totalRows} (ativada acima de {LIMIAR_RENDERIZACAO_VIRTUAL} linhas, sem supressão de dados).
        </div>
      ) : null}
      {table.truncated ? (
        <div className="table-hint">Mostrando {table.returned_rows} de {table.total_rows} linhas.</div>
      ) : null}
    </div>
  )
}

export default React.memo(DataTable)
