import useActionLogs from '@/analyst/dataHooks/useActionLogs'
import useFormatTimestamp from '@/analyst/useFormatTimestamp'
import TableComponent from '@/components/Table'
import type { Column, Row } from '@/components/Table/typing'
import {
  stringSortingFunction,
  timestampSortingFunction,
} from '@/components/Table/utils'
import { textFromRenderedContent } from '@/utils'
import type {
  ActionLog,
  EmailDetails,
  ToolDetails,
} from '@inject/graphql/fragment-types'
import { useCallback, useContext, useMemo } from 'react'
import {
  getInjectEmailArgument,
  getInjectEmailResponse,
  injectEmailTool,
} from '../../utilities'
import SelectedContext from '../SelectedContext'

const Table = () => {
  const actionLogs = useActionLogs()
  const { selectedReducer } = useContext(SelectedContext)
  const [selectedState] = selectedReducer
  const formatTimestamp = useFormatTimestamp()

  const columns: Column<ActionLog>[] = useMemo(
    () => [
      {
        id: 'team',
        name: 'Team',
        style: { width: '20%' },
        renderValue: (actionLog: ActionLog) => actionLog.team.name,
        sortingFunction: (a, b) =>
          stringSortingFunction(a.team.name, b.team.name),
      },
      {
        id: 'tool',
        name: 'Tool',
        style: { width: '20%' },
        renderValue: (actionLog: ActionLog) => {
          switch (actionLog.type) {
            case 'TOOL':
              return (actionLog.details as ToolDetails).tool.name
            case 'EMAIL':
              return injectEmailTool.name
            default:
              throw new Error('unsupported actionLog type')
          }
        },
        sortingFunction: (a, b) =>
          stringSortingFunction(
            a.type === 'TOOL'
              ? (a.details as ToolDetails).tool.name
              : injectEmailTool.name,
            b.type === 'TOOL'
              ? (b.details as ToolDetails).tool.name
              : injectEmailTool.name
          ),
      },
      {
        id: 'argument',
        name: 'Argument',
        style: { width: '20%' },
        renderValue: (actionLog: ActionLog) => {
          switch (actionLog.type) {
            case 'TOOL':
              return (actionLog.details as ToolDetails).argument
            case 'EMAIL':
              return getInjectEmailArgument(actionLog.details as EmailDetails)
            default:
              throw new Error('unsupported actionLog type')
          }
        },
        sortingFunction: (a, b) =>
          stringSortingFunction(
            a.type === 'TOOL'
              ? (a.details as ToolDetails).argument
              : getInjectEmailArgument(a.details as EmailDetails),
            b.type === 'TOOL'
              ? (b.details as ToolDetails).argument
              : getInjectEmailArgument(b.details as EmailDetails)
          ),
      },
      {
        id: 'response',
        name: 'Response',
        style: { width: '20%' },
        renderValue: (actionLog: ActionLog) => {
          switch (actionLog.type) {
            case 'TOOL':
              return textFromRenderedContent(
                (actionLog.details as ToolDetails).content.rendered
              )
            case 'EMAIL':
              return getInjectEmailResponse()
            default:
              throw new Error('unsupported actionLog type')
          }
        },
        sortingFunction: (a, b) =>
          stringSortingFunction(
            a.type === 'TOOL'
              ? textFromRenderedContent(
                  (a.details as ToolDetails).content.rendered
                )
              : getInjectEmailResponse(),
            b.type === 'TOOL'
              ? textFromRenderedContent(
                  (b.details as ToolDetails).content.rendered
                )
              : getInjectEmailResponse()
          ),
      },
      {
        id: 'timestamp',
        name: 'Timestamp',
        style: { width: '20%' },
        renderValue: (actionLog: ActionLog) =>
          formatTimestamp(actionLog.timestamp),
        sortingFunction: (a, b) =>
          timestampSortingFunction(a.timestamp, b.timestamp),
      },
    ],
    [formatTimestamp]
  )

  const actionLogFilter = useCallback(
    (actionLog: ActionLog) => {
      if (actionLog.type !== 'TOOL' && actionLog.type !== 'EMAIL') {
        return false
      }
      if (selectedState.team && actionLog.team.id !== selectedState.team.id) {
        return false
      }
      if (
        actionLog.type === 'EMAIL' &&
        actionLog.team.id !==
          (actionLog.details as EmailDetails).sender.team?.id
      ) {
        return
      }

      if (!selectedState.tool) {
        return true
      }
      if (
        actionLog.type === 'TOOL' &&
        (actionLog.details as ToolDetails).tool.id === selectedState.tool.id
      ) {
        return true
      }
      if (
        actionLog.type === 'EMAIL' &&
        injectEmailTool.id === selectedState.tool.id
      ) {
        return true
      }

      return false
    },
    [selectedState.team, selectedState.tool]
  )

  const rows: Row<ActionLog>[] = useMemo(
    () =>
      actionLogs.filter(actionLogFilter).map(actionLog => ({
        id: actionLog.id,
        value: actionLog,
      })),
    [actionLogFilter, actionLogs]
  )

  return (
    <div style={{ overflow: 'auto', height: '100%' }}>
      <TableComponent<ActionLog>
        columns={columns}
        rows={rows}
        defaultSortByColumnId='timestamp'
      />
    </div>
  )
}

export default Table
