import {
  highlighted,
  highlightedOnActive,
  highlightedOnHover,
} from '@/analyst/utilities'
import type { NonIdealStateProps } from '@blueprintjs/core'
import { Checkbox, NonIdealState } from '@blueprintjs/core'
import { cx } from '@emotion/css'
import CenteredSpinner from '@inject/shared/components/CenteredSpinner'
import { ellipsized } from '@inject/shared/css/textOverflow'
import { useCallback } from 'react'
import { checkbox, clickable, preWrappedOnHover, tableCell } from './classes'
import type { Column, Row, SelectingRow } from './typing'

type BodyProps<T> = {
  columns: Column<T>[]
  loading?: boolean
  rows: Row<T>[] | SelectingRow<T>[]
  noDataStateProps?: NonIdealStateProps
  allowSelection?: boolean
}

const Body = <T,>({
  columns,
  rows,
  loading,
  noDataStateProps,
  allowSelection,
}: BodyProps<T>) => {
  const rowClass = useCallback(
    (row: Row<T> | SelectingRow<T>) => {
      const isSelected = 'isSelected' in row && row.isSelected

      return cx(highlightedOnHover, row.className, {
        [clickable]: row.onClick !== undefined,
        [highlightedOnActive]: row.onClick !== undefined,
        [highlighted]: allowSelection && isSelected,
      })
    },
    [allowSelection]
  )

  const MaybeCheckbox = ({ row }: { row: Row<T> | SelectingRow<T> }) => {
    const isSelectingRow = 'isSelected' in row
    if (!allowSelection || !isSelectingRow) {
      return null
    }

    return (
      <td className={tableCell}>
        <Checkbox
          className={checkbox}
          checked={row.isSelected}
          onChange={row.onClick}
        />
      </td>
    )
  }

  if (loading || rows?.length === 0) {
    return (
      <tbody>
        <tr>
          <td colSpan={columns.length} className={tableCell}>
            {loading ? (
              <CenteredSpinner />
            ) : (
              <NonIdealState
                title='No data'
                icon='low-voltage-pole'
                description='There is no data to display'
                {...noDataStateProps}
              />
            )}
          </td>
        </tr>
      </tbody>
    )
  }

  return (
    <tbody>
      {rows.map(row => (
        <tr
          key={row.id}
          className={rowClass(row)}
          style={row.style}
          onClick={row.onClick}
        >
          <MaybeCheckbox row={row} />
          {columns.map(column => (
            <td
              key={column.id}
              className={cx(
                tableCell,
                ellipsized,
                preWrappedOnHover,
                column.className,
                column.valueClassName?.(row.value)
              )}
              style={{
                ...column.style,
                ...column.valueStyle?.(row.value),
              }}
            >
              {column.renderValue(row.value)}
            </td>
          ))}
        </tr>
      ))}
    </tbody>
  )
}
export default Body
