import React, { useState, useMemo } from 'react'
import * as S from "./styles"
import {
  flexRender,
  getCoreRowModel,
  getSortedRowModel,
  useReactTable,
  getFilteredRowModel,
  ColumnFiltersState,
  getPaginationRowModel
} from '@tanstack/react-table'
import { format, isAfter, isBefore } from "date-fns"
import { Button } from "@mui/material";
import { TablePropos } from './interface';
import { Pagination, Header, TBody } from "./components"

const Table:React.FC<TablePropos> = ({ data, columns, onClick, onMouseOver, onMouseOut, showTotalResults, showSettings, pagination, rowCount, onChangePage, customTotalResult }) => {
  const [openFilterDialog, setOpenFilterDialog] = useState('')
  const [sorting, setSorting] = useState<any>([])
  const [openFilterOptions, setOpenFilterOptions] = useState(false)
  const [filterByColumn, setFilterByColumn] = useState<ColumnFiltersState>([])
  const [filterInputSelected, setFilterInputSelected] = useState<any>()
  const [globalFilters, setGlobalFilters] = useState<any>([])
  const [value, setValue] = useState<any>()
  const [orderSmallest, setOrderSmallest] = useState(false)
  const [orderLargest, setOrderLargest] = useState(false)

  const customFilterText = (row: any, value: string) => {
    const itensFinded = globalFilters.map((item: any) => {
      if (item.type === 'Horario Igual a') {
        return item.value === row.original[item.acessor]
      }
      if (item.type === 'Horario maior que') {
        const date = new Date()
        const rowDate = new Date()
        const hourSplited = item?.value?.split(':')
        const rowDateSplited = row.original[item.acessor].split(':')

        date.setHours(Number(hourSplited[0]), Number(hourSplited[1]), 0, 0)
        rowDate.setHours(Number(rowDateSplited[0]), Number(rowDateSplited[1]), 0 ,0)
        
        return isAfter(rowDate, date)
      }
      if (item.type === 'Horario menor que') {
        const date = new Date()
        const rowDate = new Date()
        const hourSplited = item?.value?.split(':')
        const rowDateSplited = row.original[item.acessor].split(':')

        date.setHours(Number(hourSplited[0]), Number(hourSplited[1]), 0, 0)
        rowDate.setHours(Number(rowDateSplited[0]), Number(rowDateSplited[1]), 0 ,0)
        
        return isBefore(rowDate, date)
      }
      if (item.type === 'Data Igual a') {
        const dateSplited = item?.value?.split('-')
        return row.original[item.acessor] === format(new Date(dateSplited[0], dateSplited[1] - 1, dateSplited[2], 0 , 0), "dd/MM/yyyy")
      }
      if (item.type === 'Data maior que') {
        const dateSplited = item?.value?.split('-')
        const rowDateSplited = row.original[item.acessor].split('/')
        return isAfter(new Date(rowDateSplited[2], rowDateSplited[1], rowDateSplited[0]), new Date(dateSplited[0], dateSplited[1], dateSplited[2]))
      }
      if (item.type === 'Data menor que') {
        const dateSplited = item?.value?.split('-')
        const rowDateSplited = row.original[item.acessor].split('/')
        return isBefore(new Date(rowDateSplited[2], rowDateSplited[1], rowDateSplited[0]), new Date(dateSplited[0], dateSplited[1], dateSplited[2]))
      }
      if (item.type === 'Igual a' && typeof value === 'number') {
        return row.original[item.acessor] === item.value
      }
      if (item.type === 'Igual a') {
        return row.original[item.acessor] === item.value
      }
      if (item.type === 'Contém') {
        return !!row.original[item.acessor].includes(item.value)
      }
      if (item.type === 'Não é igual a') {
        return row.original[item.acessor] !== item.value
      }
      if (item.type === 'Maior que') {
        return row.original[item.acessor] > item.value
      }
      if (item.type === 'Menor que') {
        return row.original[item.acessor] < item.value
      }
    })

    const result = itensFinded.every((item: any) => item)

    return result
  }

  const reactTableConfig = useMemo(() => {
    const config:any = {
      data,
      columns,
      filterFns:{
        'customFilterText': customFilterText
      },
      state: {
        sorting: sorting,
        columnFilters: filterByColumn,
      },
      rowCount: rowCount || 10,
      getCoreRowModel: getCoreRowModel(),
      getSortedRowModel: getSortedRowModel(),
      getFilteredRowModel: getFilteredRowModel(),
      onSortingChange: setSorting,
      onColumnFiltersChange: setFilterByColumn
    }
    config.rowCount = rowCount || 10

    if(!pagination) {
      config.getPaginationRowModel = getPaginationRowModel()
    } else {
      config.state.pagination = pagination
      config.manualPagination = true
      config.pageCount = pagination.totalPages
    }
    return config
  }, [data, sorting, filterByColumn, columns, pagination])

  const table = useReactTable(reactTableConfig)

  return (
    <S.Container>
      <Header 
        table={table} 
        customTotalResult={customTotalResult}
        globalFilters={globalFilters} 
        orderSmallest={orderSmallest}
        orderLargest={orderLargest}
        showTotalResults={showTotalResults}
        showSettings={showSettings}
        setGlobalFilters={setGlobalFilters}
        setOrderLargest={setOrderLargest}
        setOrderSmallest={setOrderSmallest}
      />
      <S.Content>
        <S.Table>
          <thead>
            {table.getHeaderGroups().map((headerGroup: any) => (
              <tr key={headerGroup.id}>
                {headerGroup.headers.map((header: any) => (
                  <th key={header.id}>
                    <div>
                      <S.ColumnContent>
                        <S.TextColumn>
                          {header.isPlaceholder
                            ? null
                            : flexRender(
                              header.column.columnDef.header,
                              header.getContext()
                          )}
                        </S.TextColumn>
                        <S.IconFilterDialog onClick={() => {
                          setOpenFilterDialog(header.column.columnDef.accessorKey)
                        }}>
                          <svg fill='#666' focusable="false" aria-hidden="true" viewBox="0 0 24 24" data-testid="ArrowDropDownIcon"><path d="m7 10 5 5 5-5z"></path></svg>
                        </S.IconFilterDialog>
                      </S.ColumnContent>
                      { openFilterDialog === header.column.columnDef.accessorKey
                        ? (
                          <>
                            <S.backgroundDialog onClick={() => {
                              setOpenFilterDialog('')
                              setOpenFilterOptions(false)
                            }}></S.backgroundDialog>
                            <S.FilterDialog>
                              {  
                                openFilterOptions 
                                  ? (
                                    <S.ListFilterDialog>
                                      <p className='label'>Selecione um filtro</p>
                                      <select className='select' value={filterInputSelected} onChange={(event) => {
                                        setFilterInputSelected(event.target.value)
                                      }}>
                                        <option>Selecione...</option>
                                        { header?.headerGroup?.headers[header.index].column.columnDef.type === 'text' ? <option>Igual a</option> : null }
                                        { header?.headerGroup?.headers[header.index].column.columnDef.type === 'text' ? <option>Não é igual a</option> : null }
                                        { header?.headerGroup?.headers[header.index].column.columnDef.type === 'text' ? <option>Contém</option> : null }
                                        { header?.headerGroup?.headers[header.index].column.columnDef.type === 'number' ? <option>Maior que</option> : null }
                                        { header?.headerGroup?.headers[header.index].column.columnDef.type === 'number' ? <option>Menor que</option> : null }
                                        { header?.headerGroup?.headers[header.index].column.columnDef.type === 'number' ? <option>Igual a</option> : null }
                                        { header?.headerGroup?.headers[header.index]. column.columnDef.type === 'date' ? <option>Data Igual a</option> : null }
                                        { header?.headerGroup?.headers[header.index]. column.columnDef.type === 'date' ? <option>Data maior que</option> : null }
                                        { header?.headerGroup?.headers[header.index]. column.columnDef.type === 'date' ? <option>Data menor que</option> : null }
                                        { header?.headerGroup?.headers[header.index]. column.columnDef.type === 'time' ? <option>Horario Igual a</option> : null }
                                        { header?.headerGroup?.headers[header.index]. column.columnDef.type === 'time' ? <option>Horario maior que</option> : null }
                                        { header?.headerGroup?.headers[header.index]. column.columnDef.type === 'time' ? <option>Horario menor que</option> : null }
                                      </select>
                                      <div>
                                        { header.column.getCanFilter()
                                          ? filterInputSelected === 'Igual a' || 
                                            filterInputSelected === 'Não é igual a' || 
                                            filterInputSelected === 'Contém' || 
                                            filterInputSelected === 'Maior que' ||
                                            filterInputSelected === 'Menor que' ||
                                            filterInputSelected === 'Data Igual a' ||
                                            filterInputSelected === 'Data maior que' ||
                                            filterInputSelected === 'Data menor que' ||
                                            filterInputSelected === 'Horario Igual a' ||
                                            filterInputSelected === 'Horario maior que' ||
                                            filterInputSelected === 'Horario menor que'
                                              ?  (
                                                <div>
                                                  <p className='label' style={{ marginTop: '10px' }}>Valor</p>
                                                  <input 
                                                    type={header?.headerGroup?.headers[header.index].column.columnDef.type}
                                                    className='select'
                                                    style={{ width: '100%' }}
                                                    value={value as any}
                                                    onChange={event => {
                                                      if (header?.headerGroup?.headers[header.index].column.columnDef.type === 'number') {
                                                        setValue(Number(event.target.value))
                                                        return 
                                                      } 
                                                      if (header?.headerGroup?.headers[header.index].column.columnDef.type === 'date') {
                                                        setValue(event.target.value)
                                                        return 
                                                      }
                                                      setValue(event.target.value)
                                                    }} 
                                                  />
                                                  <Button
                                                    color="primary"
                                                    type={"submit"}
                                                    disableElevation
                                                    style={{
                                                      marginTop: 8,
                                                      width: '100%'
                                                    }}
                                                    variant="contained"
                                                    onClick={() => {
                                                      setGlobalFilters((current: any) => [...current, 
                                                        {
                                                          acessor: header.column.columnDef.accessorKey,
                                                          type: filterInputSelected,
                                                          value: value
                                                        }
                                                      ])
                                                      header.column.setFilterValue(value)
                                                      setOpenFilterOptions(false)
                                                      setOpenFilterDialog('')
                                                      setFilterInputSelected(false)
                                                      setValue(null)
                                                    }}
                                                  >
                                                    Buscar
                                                  </Button>
                                                </div>
                                              )
                                              : null
                                          : null 
                                        }
                                      </div>
                                    </S.ListFilterDialog>
                                  )
                                  : (
                                    <S.ListFilterDialog>
                                      <S.OptionFilterDialog style={{
                                        background: orderSmallest ? 'rgba(0, 0, 0, 0.04)' : ''
                                      }}>
                                        <div className='icon'>
                                          <svg fill="#666" stroke="currentColor" strokeWidth="1.5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="20" height="20"><path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m0 0l6.75-6.75M12 19.5l-6.75-6.75"></path></svg>
                                        </div>
                                        <p onClick={() => {
                                          header.column.toggleSorting()
                                          setOrderSmallest(true)
                                          setOrderLargest(false)
                                        }}>Menor primeiro</p>
                                      </S.OptionFilterDialog>
                                      <S.OptionFilterDialog style={{
                                        background: orderLargest ? 'rgba(0, 0, 0, 0.04)' : ''
                                      }}>
                                        <div className='icon rotate'>
                                          <svg fill="#666" stroke="currentColor" strokeWidth="1.5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="20" height="20"><path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m0 0l6.75-6.75M12 19.5l-6.75-6.75"></path></svg>
                                        </div>
                                        <p onClick={() => {
                                          header.column.toggleSorting()
                                          setOrderLargest(true)
                                          setOrderSmallest(false)
                                        }}>Maior primeiro</p>
                                      </S.OptionFilterDialog>
                                      <S.OptionFilterDialog>
                                        <div className='icon'>
                                          <svg fill="none" stroke="currentColor" strokeWidth="1.5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="16" height="16"><path strokeLinecap="round" strokeLinejoin="round" d="M12 3c2.755 0 5.455.232 8.083.678.533.09.917.556.917 1.096v1.044a2.25 2.25 0 01-.659 1.591l-5.432 5.432a2.25 2.25 0 00-.659 1.591v2.927a2.25 2.25 0 01-1.244 2.013L9.75 21v-6.568a2.25 2.25 0 00-.659-1.591L3.659 7.409A2.25 2.25 0 013 5.818V4.774c0-.54.384-1.006.917-1.096A48.32 48.32 0 0112 3z"></path></svg>
                                        </div>
                                        <p onClick={() => setOpenFilterOptions(true)}>Filtrar por</p>
                                      </S.OptionFilterDialog>
                                    </S.ListFilterDialog>
                                  )
                              }
                            </S.FilterDialog>
                          </>
                        ) : null
                      }
                    </div>
                  </th>
                ))}
              </tr>
            ))}
          </thead>
          <TBody 
            table={table} 
            onClick={onClick} 
            onMouseOver={onMouseOver} 
            onMouseOut={onMouseOut}
          />
        </S.Table>
      </S.Content>
      <Pagination table={table} onChangePage={onChangePage} />
    </S.Container>
  )
}

export default Table