import useActionLogs from '@/analyst/dataHooks/useActionLogs'
import TableComponent from '@/components/Table'
import { SortingOrder, type Column, type Row } from '@/components/Table/typing'
import {
  numberSortingFunction,
  stringSortingFunction,
} from '@/components/Table/utils'
import type {
  EmailDetails,
  Tool,
  ToolDetails,
} from '@inject/graphql/fragment-types'
import { useContext, useMemo } from 'react'
import { getInjectEmailArgument, injectEmailTool } from '../../utilities'
import SelectedContext from '../SelectedContext'

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

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: Column<TableDataElement>[] = useMemo(
    () => [
      {
        id: 'tool',
        name: 'Tool',
        style: { width: '30%' },
        renderValue: (element: TableDataElement) => element.tool.name,
        sortingFunction: (a, b) =>
          stringSortingFunction(a.tool.name, b.tool.name),
      },
      {
        id: 'argument',
        name: 'Argument',
        style: { width: '40%' },
        renderValue: (element: TableDataElement) => element.argument,
        sortingFunction: (a, b) =>
          stringSortingFunction(a.argument, b.argument),
      },
      {
        id: 'timesUsed',
        name: 'Times used',
        style: { width: '30%' },
        valueStyle: () => ({ textAlign: 'right' }),
        renderValue: (element: TableDataElement) =>
          data.find(dataElement => dataElement.argument === element.argument)
            ?.timesUsed || 0,
        sortingFunction: (a, b) => {
          const aValue =
            data.find(dataElement => dataElement.argument === a.argument)
              ?.timesUsed || 0
          const bValue =
            data.find(dataElement => dataElement.argument === b.argument)
              ?.timesUsed || 0
          return numberSortingFunction(aValue, bValue)
        },
        defaultSortingOrder: SortingOrder.DESC,
      },
    ],
    [data]
  )

  const rows: Row<TableDataElement>[] = data.map(element => ({
    id: element.tool.id + element.argument,
    value: element,
  }))

  return (
    <TableComponent
      columns={columns}
      rows={rows}
      defaultSortByColumnId='timesUsed'
    />
  )
}

export default Table
