import { css, cx } from '@emotion/css'
import { useMemo, useState } from 'react'
import Body from './Body'
import Head from './Head'
import type { SortingOrders, TableProps } from './typing'
import { SortingOrder } from './typing'

const wrapper = css`
  height: 100%;
  overflow-y: auto;
`

const table = css`
  border-collapse: collapse;
  table-layout: fixed;
  width: 100%;
`

const Table = <T,>({
  columns: columnsUnfiltered,
  className,
  style,
  loading,
  rows,
  noDataStateProps,
  defaultSortByColumnId,
  ...selectingProps
}: TableProps<T>) => {
  const columns = useMemo(
    () => columnsUnfiltered.filter(column => column.display !== false),
    [columnsUnfiltered]
  )

  const [sortByColumnId, setSortByColumnId] = useState(defaultSortByColumnId)
  const [sortingOrders, setSortingOrders] = useState<SortingOrders>(
    columnsUnfiltered.reduce((acc, column) => {
      acc[column.id] = column.defaultSortingOrder ?? SortingOrder.ASC
      return acc
    }, {} as SortingOrders)
  )

  const sortedRows = useMemo(() => {
    if (!sortByColumnId) {
      return rows
    }

    const column = columns.find(column => column.id === sortByColumnId)
    if (!column) {
      return rows
    }

    const sortingOrder = sortingOrders[sortByColumnId]
    const sortingFunction = column.sortingFunction
    if (!sortingFunction) {
      return rows
    }

    return [...rows].sort(
      (a, b) =>
        sortingFunction(a.value, b.value) *
        (sortingOrder === SortingOrder.ASC ? 1 : -1)
    )
  }, [columns, rows, sortByColumnId, sortingOrders])

  return (
    <div className={cx(className, wrapper)}>
      <table style={style} className={table}>
        <Head
          columns={columns}
          sortByColumnId={sortByColumnId}
          setSortByColumnId={setSortByColumnId}
          sortingOrders={sortingOrders}
          setSortingOrders={setSortingOrders}
          {...selectingProps}
        />
        <Body
          columns={columns}
          loading={loading}
          rows={sortedRows}
          noDataStateProps={noDataStateProps}
          allowSelection={!!selectingProps.onSelectAll}
        />
      </table>
    </div>
  )
}

export default Table
