import React, { useMemo } from 'react'

import { css, styled, useStyleConfig, vui, VuiComponent } from '../core'
import { compareBy, cs } from '../utils'
import { TableProvider } from './context'
import { TableProps } from './table.types'
import TableSortIcon from './tableSortIcon'
import Tbody from './tbody'
import Td from './td'
import Tfoot from './tfoot'
import Th from './th'
import Thead from './thead'
import Tr from './tr'
import useTable from './useTable'

/**
 * Displays a Table with support for columns, rows and sort.
 */
export const TableBase = styled.tableBox<TableProps>`
  border-collapse: separate;
  border-spacing: 0px;
  display: table;
  position: relative;
  width: 100%;

  ${p =>
    p.stickyColumn &&
    css`
      thead tr:last-of-type th:first-of-type,
      td:first-of-type {
        left: 0;
        position: sticky;
        z-index: 2;

        ::after {
          bottom: -1px;
          box-shadow: inset 10px 0 8px -8px #00000026;
          content: '';
          pointer-events: none;
          position: absolute;
          right: 0;
          top: 0;
          transform: translate(100%);
          transition: box-shadow 0.3s;
          width: 10px;
        }
      }

      thead tr:last-of-type th:first-of-type:not([data-active='true']):not([data-disabled='true']),
      td:first-of-type {
        background-color: white;
      }
    `}
`

/** Displays a Table with support for columns, rows and sort. */
export const Table = vui<'table', TableProps>((props, ref) => {
  const {
    children,
    className,
    columns,
    defaultSort,
    onSortChange,
    rows,
    size,
    sort: sortProp,
    stickyColumn,
    stickyHeader,
    variant,
    ...rest
  } = props
  const styles = useStyleConfig('Table', props)
  const tableProps = useTable({ defaultSort, onSortChange, sort: sortProp })
  const { isControlled, sort } = tableProps

  // Rows are sorted internally only in uncontrolled mode, that is when 'sort' prop is not provided.
  const sortedRows = useMemo(
    () => (!isControlled ? rows?.slice().sort(compareBy(sort.key, sort.order)) : rows),
    [rows, sort, isControlled],
  )

  const context = { ...tableProps, columns, rows: sortedRows, size, stickyColumn, stickyHeader, variant }

  return (
    <TableProvider value={context}>
      <TableBase
        className={cs('vui-table', className)}
        ref={ref}
        stickyColumn={stickyColumn}
        {...styles.container}
        {...rest}
      >
        {children ?? (
          <>
            <Thead />
            <Tbody />
          </>
        )}
      </TableBase>
    </TableProvider>
  )
}) as VuiComponent<'table', TableProps> & {
  SortIcon: typeof TableSortIcon
  Tbody: typeof Tbody
  Td: typeof Td
  Tfoot: typeof Tfoot
  Th: typeof Th
  Thead: typeof Thead
  Tr: typeof Tr
}

Table.SortIcon = TableSortIcon
Table.Tbody = Tbody
Table.Td = Td
Table.Tfoot = Tfoot
Table.Th = Th
Table.Thead = Thead
Table.Tr = Tr

Table.displayName = 'Table'

export default Table
