import {
  IconButton,
  ListItemIcon,
  TableBody,
  TableHead,
  TableRow,
  Theme,
} from '@mui/material'
import { SxProps } from '@mui/system'
import _ from 'lodash'
import { useEffect, useState } from 'react'
import Spinner from '../../Spinner'
import NoRecordsFound from '../common/NoRecordsFound'
import { SortAscIcon, SortDescIcon, SortIcon } from '../common/icons'
import TableFooter from './TableFooter'
import {
  StyledMuiTable,
  StyledTableCell,
  StyledTableContainer,
  StyledTableRow,
} from './styles'

type Order = 'asc' | 'desc' | ''
type Sort = {}
type DataType = 'currency' | 'string' | 'number'

export interface TableColumn<T> {
  dataIndex: string
  key: string
  title: any
  render?: (cellData: any, row: any, index: number) => any
  textColor?: string
  sort?: boolean
  width?: string //pixels
  dataType?: DataType
}

interface TableProps<T> {
  showSerialNumber?: boolean
  columns: Array<TableColumn<T>>
  rowKey?: string
  dataSource?: T[]
  loading?: boolean
  onRowClick?: (row: any) => void
  pagination?: {
    page: number
    limit: number
    totalCount: number
    onChange: (v: number) => void
    onChangeLimit?: (v: number) => void
    handlePageInput?: (v: number) => void
  }
  onSort?: (sort: any) => void
  dense?: boolean
  showTotal?: boolean
  showNoDataIllustration?: boolean
  sx?: Record<string, SxProps<Theme>>
  totalColumns?: number[]
  showTotalInFirstCellOfTotalRow?: boolean
}

export default function Table<T>({
  showSerialNumber = false,
  columns,
  dataSource,
  onRowClick,
  pagination,
  loading,
  onSort,
  dense = false,
  showTotal = false,
  showNoDataIllustration = true,
  sx,
  totalColumns,
  showTotalInFirstCellOfTotalRow,
}: TableProps<T>) {
  const [sort, setSort] = useState<Sort>({})
  let totalCount = []
  let totalCols = []
  if (showTotalInFirstCellOfTotalRow) {
    totalCols = totalColumns ? [...totalColumns, 1] : [1]
  } else {
    totalCols = totalColumns ? [...totalColumns] : []
  }

  const handleSortClick = (sortByKey) => {
    setSort((prev) => {
      if (prev[sortByKey]) {
        if (prev[sortByKey] === 'desc') return { ...prev, [sortByKey]: 'asc' }
        if (prev[sortByKey] === 'asc') {
          delete prev[sortByKey]
          return { ...prev }
        }
      } else {
        return {
          ...prev,
          [sortByKey]: 'desc',
        }
      }
    })
  }

  useEffect(() => {
    if (!onSort) return

    onSort({
      sortBy: Object.keys(sort).join(','),
      sortOrder: Object.keys(sort)
        .map((item) => sort[item])
        .join(','),
    })
  }, [sort])

  const calculateTotal = (row) => {
    columns.forEach((col, colIndex) => {
      const colValue = col?.render
        ? col.render(row[col.dataIndex], row, colIndex)
        : _.get(row, col.dataIndex)

      if (!totalCount[colIndex]) {
        totalCount[colIndex] = 0
      }

      if (showTotalInFirstCellOfTotalRow && colIndex === 0) {
        totalCount[colIndex] = 'Total'
        return
      }

      totalCount[colIndex] += colValue
    })
  }

  const convertToAmount = (data) => {
    return data.toLocaleString('en-IN', {
      style: 'currency',
      currency: 'INR',
    })
  }

  return (
    <StyledTableContainer sx={sx}>
      <>
        <StyledMuiTable sx={sx}>
          <TableHead>
            <TableRow>
              {showSerialNumber && (
                <StyledTableCell
                  sx={sx}
                  columnIndex={0}
                  rowIndex={0}
                  columnsLength={1}
                >
                  S. No.
                </StyledTableCell>
              )}
              {columns.map((col, columnIndex) => (
                <StyledTableCell
                  key={columnIndex}
                  columnsLength={columns.length}
                  columnIndex={columnIndex + 1}
                  rowIndex={0}
                  col={col}
                  sx={sx}
                  isHeaderCell
                >
                  {col.title}

                  {col.sort && (
                    <IconButton onClick={() => handleSortClick(col.dataIndex)}>
                      <ListItemIcon>
                        {sort[col.dataIndex] === 'asc' ? (
                          <SortAscIcon />
                        ) : sort[col.dataIndex] === 'desc' ? (
                          <SortDescIcon />
                        ) : (
                          <SortIcon />
                        )}
                      </ListItemIcon>
                    </IconButton>
                  )}
                </StyledTableCell>
              ))}
            </TableRow>
          </TableHead>
          {!loading ? (
            <>
              {dataSource?.length ? (
                <TableBody>
                  {dataSource?.map((row, rowIndex) => (
                    <StyledTableRow
                      canRowClick={!!onRowClick}
                      hover={!!onRowClick}
                      key={rowIndex}
                      onClick={() => {
                        return onRowClick && onRowClick(row)
                      }}
                    >
                      {showSerialNumber && (
                        <StyledTableCell
                          sx={sx}
                          columnIndex={0}
                          rowIndex={rowIndex + 1}
                          columnsLength={1}
                        >
                          {rowIndex + 1}
                        </StyledTableCell>
                      )}
                      <> {showTotal && calculateTotal(row)}</>
                      {columns.map((col, colIndex) => (
                        <StyledTableCell
                          key={colIndex}
                          columnsLength={columns.length}
                          columnIndex={colIndex + 1}
                          rowIndex={rowIndex + 1}
                          col={col}
                          isBodyCell
                          sx={sx}
                        >
                          {col?.dataType && col?.dataType == 'currency' ? (
                            <>{convertToAmount(row[col.dataIndex])}</>
                          ) : (
                            <>
                              {col?.render
                                ? col.render(row[col.dataIndex], row, rowIndex)
                                : _.get(row, col.dataIndex)}
                            </>
                          )}
                        </StyledTableCell>
                      ))}
                    </StyledTableRow>
                  ))}

                  {showTotal && (
                    <StyledTableRow canRowClick={false}>
                      {columns.map((col, colIndex) => (
                        <>
                          <StyledTableCell
                            key={colIndex}
                            columnsLength={columns.length}
                            columnIndex={colIndex + 1}
                            rowIndex={dataSource.length + 1}
                            col={col}
                            isBodyCell
                            sx={sx}
                          >
                            {totalCols.includes(colIndex + 1) ? (
                              col?.dataType && col?.dataType == 'currency' ? (
                                <>{convertToAmount(totalCount[colIndex])}</>
                              ) : (
                                <>{totalCount[colIndex]}</>
                              )
                            ) : (
                              '---'
                            )}
                          </StyledTableCell>
                        </>
                      ))}
                    </StyledTableRow>
                  )}
                </TableBody>
              ) : (
                <>
                  {showNoDataIllustration ? (
                    <NoRecordsFound colLength={columns?.length} />
                  ) : null}
                </>
              )}
            </>
          ) : (
            <Spinner />
          )}
        </StyledMuiTable>
      </>
      <>
        {pagination && (
          <TableFooter
            page={pagination.page + 1}
            limit={pagination.limit}
            totalCount={pagination.totalCount ?? 0}
            handlePagination={pagination.onChange}
            handlePageLimit={pagination.onChangeLimit}
            handlePageInput={pagination.handlePageInput}
          />
        )}
      </>
    </StyledTableContainer>
  )
}
