import useActionLogs from '@/analyst/dataHooks/useActionLogs'
import SortableTable from '@/components/SortableTable'
import type { Column, Row, ValueType } from '@/components/SortableTable/typing'
import { SortingFunction } from '@/components/SortableTable/typing'
import type { EmailDetails } from '@inject/graphql/fragments/EmailDetails.generated'
import type { Tool } from '@inject/graphql/fragments/Tool.generated'
import type { ToolDetails } from '@inject/graphql/fragments/ToolDetails.generated'
import { useContext, useMemo } from 'react'
import { getInjectEmailArgument, injectEmailTool } from '../../utilities'
import SelectedContext from '../SelectedContext'

interface TableDataElement {
  tool: Tool
  argument: string
  timesUsed: number
}

interface TableColumn extends Column {
  getValue: (element: TableDataElement) => ValueType
}

const Table = () => {
  const actionLogs = useActionLogs()
  const { selectedReducer } = useContext(SelectedContext)

  const [selectedState] = selectedReducer

  const data: TableDataElement[] = useMemo(
    () =>
      actionLogs
        .filter(
          actionLog => actionLog.type === 'TOOL' || actionLog.type === 'EMAIL'
        )
        .filter(
          actionLog =>
            !selectedState.team || actionLog.team.id === selectedState.team.id
        )
        .filter(
          actionLog =>
            actionLog.type !== 'EMAIL' ||
            actionLog.team.id ===
              (actionLog.details as EmailDetails).sender.team?.id
        )
        .map(actionLog => {
          const tool =
            actionLog.type === 'TOOL'
              ? (actionLog.details as ToolDetails).tool
              : injectEmailTool
          const argument =
            actionLog.type === 'TOOL'
              ? (actionLog.details as ToolDetails).argument
              : getInjectEmailArgument(actionLog.details as EmailDetails)
          return { tool, argument }
        })
        .filter(
          element =>
            !selectedState.tool || element.tool.id === selectedState.tool.id
        )
        .reduce<TableDataElement[]>((acc, element) => {
          const index = acc.findIndex(
            accElement =>
              accElement.tool.id === element.tool.id &&
              accElement.argument === element.argument
          )
          if (index === -1) {
            acc.push({ ...element, timesUsed: 1 })
          } else {
            acc[index].timesUsed++
          }
          return acc
        }, []),
    [actionLogs, selectedState.team, selectedState.tool]
  )

  const columns: TableColumn[] = useMemo(
    () => [
      {
        id: 'tool',
        name: 'Tool',
        style: { width: '30%' },
        getValue: (element: TableDataElement) => element.tool.name,
      },
      {
        id: 'argument',
        name: 'Argument',
        style: { width: '40%' },
        getValue: (element: TableDataElement) => element.argument,
      },
      {
        id: 'timesUsed',
        name: 'Times used',
        style: { width: '30%' },
        valueStyle: { textAlign: 'right' },
        getValue: (element: TableDataElement) =>
          data.find(dataElement => dataElement.argument === element.argument)
            ?.timesUsed || 0,
      },
    ],
    [data]
  )

  const rows: Row[] = data.map(element => ({
    id: element.tool.id + element.argument,
    columns,
    values: columns.map(column => column.getValue(element)),
  }))

  return (
    <SortableTable
      columns={columns}
      rows={rows}
      sortByColumn={2}
      defaultSortingFunction={SortingFunction.DESC}
    />
  )
}

export default Table
