import type { ActionLog, MilestoneState } from '@inject/graphql/fragment-types'
import setsEqual from '@inject/shared/utils/setsEqual'
import type { AutoInject } from './AutoInject/utils'

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

export interface selectedReducerActionProps {
  type:
    | 'selectActions'
    | 'selectMilestones'
    | 'selectEmails'
    | 'selectAutoInjects'
    | 'resetSelection'
  actionLog?: ActionLog
  milestoneState?: MilestoneState
  autoInjects?: AutoInject[]
}

const autoInjectGroupsEqual = (a: AutoInject[], b: AutoInject[]) =>
  a.every(
    (inject, i) =>
      b[i].__typename === inject.__typename && b[i].id === inject.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')
        }

        // milestoneStatesEqual
        if (
          state.milestoneState !== null &&
          action.milestoneState !== null &&
          state.milestoneState.milestone.id ===
            action.milestoneState.milestone.id &&
          setsEqual(
            new Set(state.milestoneState.teamIds),
            new Set(action.milestoneState.teamIds)
          )
        ) {
          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 'selectAutoInjects':
      if (state.selectedDataType === 'AUTO_INJECTS') {
        if (!state.autoInjects || !action.autoInjects) {
          throw new Error('autoInjects null when AUTO_INJECTS selected')
        }

        if (autoInjectGroupsEqual(state.autoInjects, action.autoInjects)) {
          return selectedReducer(state, { type: 'resetSelection' })
        }
      }

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

export default selectedReducer
