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

interface TableColumn extends Column {
  getValue: (actionLog: ActionLog) => ValueType
}

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

  const columns: TableColumn[] = useMemo(
    () => [
      {
        id: 'team',
        name: 'Team',
        style: { width: '20%' },
        getValue: (actionLog: ActionLog) => actionLog.team.name,
      },
      {
        id: 'tool',
        name: 'Tool',
        style: { width: '20%' },
        getValue: (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')
          }
        },
      },
      {
        id: 'argument',
        name: 'Argument',
        style: { width: '20%' },
        getValue: (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')
          }
        },
      },
      {
        id: 'response',
        name: 'Response',
        style: { width: '20%' },
        getValue: (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')
          }
        },
      },
      {
        id: 'timestamp',
        name: 'Timestamp',
        style: { width: '20%' },
        getValue: (actionLog: ActionLog) =>
          formatTimestamp(actionLog.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[] = useMemo(
    () =>
      actionLogs.filter(actionLogFilter).map(actionLog => ({
        id: actionLog.id,
        columns,
        values: columns.map(column => column.getValue(actionLog)),
      })),
    [actionLogFilter, actionLogs, columns]
  )

  return (
    <div style={{ overflow: 'auto', height: '100%' }}>
      <SortableTable columns={columns} rows={rows} sortByColumn={4} />
    </div>
  )
}

export default Table
