import type { ActionLog } from '@inject/graphql/fragments/ActionLog.generated'
import type { DefinitionInject } from '@inject/graphql/fragments/DefinitionInject.generated'
import type { MilestoneState } from '@inject/graphql/fragments/MilestoneState.generated'
import milestoneStatesEqual from '@inject/graphql/utils/milestoneStatesEqual'

export interface selectedReducerStateProps {
  selectedDataType?: 'ACTIONS' | 'MILESTONES' | 'EMAILS' | 'AUTO_INJECTS'
  actionLog?: ActionLog
  milestoneState?: MilestoneState
  injectGroup?: DefinitionInject[]
}

export interface selectedReducerActionProps {
  type:
    | 'selectActions'
    | 'selectMilestones'
    | 'selectEmails'
    | 'selectCategories'
    | 'resetSelection'
  actionLog?: ActionLog
  milestoneState?: MilestoneState
  injectGroup?: DefinitionInject[]
}

const injectGroupsEqual = (a: DefinitionInject[], b: DefinitionInject[]) =>
  a.every((category, i) => b[i].id === category.id)

const selectedReducer = (
  state: selectedReducerStateProps,
  action: selectedReducerActionProps
): selectedReducerStateProps => {
  switch (action.type) {
    case 'selectActions':
      if (
        state.selectedDataType === 'ACTIONS' &&
        state.actionLog?.id === action.actionLog?.id
      ) {
        return selectedReducer(state, { type: 'resetSelection' })
      }

      return {
        selectedDataType: 'ACTIONS',
        actionLog: action.actionLog,
      }
    case 'selectMilestones':
      if (state.selectedDataType === 'MILESTONES') {
        if (!state.milestoneState || !action.milestoneState) {
          throw new Error('milestoneState null when MILESTONES selected')
        }

        if (milestoneStatesEqual(state.milestoneState, action.milestoneState)) {
          return selectedReducer(state, { type: 'resetSelection' })
        }
      }

      return {
        selectedDataType: 'MILESTONES',
        milestoneState: action.milestoneState,
      }
    case 'selectEmails':
      if (
        state.selectedDataType === 'EMAILS' &&
        state.actionLog?.id === action.actionLog?.id
      ) {
        return selectedReducer(state, { type: 'resetSelection' })
      }

      return {
        selectedDataType: 'EMAILS',
        actionLog: action.actionLog,
      }
    case 'selectCategories':
      if (state.selectedDataType === 'AUTO_INJECTS') {
        if (!state.injectGroup || !action.injectGroup) {
          throw new Error('categories null when AUTO_INJECTS selected')
        }

        if (injectGroupsEqual(state.injectGroup, action.injectGroup)) {
          return selectedReducer(state, { type: 'resetSelection' })
        }
      }

      return {
        selectedDataType: 'AUTO_INJECTS',
        injectGroup: action.injectGroup,
      }
    case 'resetSelection':
      return {}
    default:
      throw new Error('unknown action')
  }
}

export default selectedReducer
