import type { FC, PropsWithChildren, Reducer as ReducerType } from 'react'
import { useCallback, useMemo, useReducer, useState } from 'react'
import { SubscriptionProvider } from './SubscriptionContext'

interface SubscriptionEngineProps extends PropsWithChildren {}

interface State {
  actionLogTeamIds: string[]
}

interface Action {
  type: 'push' | 'remove'
  payload: string
  group: 'actionLog'
}

const reducerFn: ReducerType<State, Action> = (state, reducer) => {
  switch (reducer.group) {
    case 'actionLog':
      switch (reducer.type) {
        case 'push':
          if (state.actionLogTeamIds.includes(reducer.payload)) return state
          return {
            ...state,
            actionLogTeamIds: [...state.actionLogTeamIds, reducer.payload],
          }
        case 'remove':
          return {
            ...state,
            actionLogTeamIds: state.actionLogTeamIds.filter(
              id => id !== reducer.payload
            ),
          }
        default:
          return state
      }
    default:
      return state
  }
}

const SubscriptionEngine: FC<SubscriptionEngineProps> = ({ children }) => {
  const [state, dispatch] = useReducer(reducerFn, {
    actionLogTeamIds: [],
  })
  const [instructorContext, setInstructorContext] = useState(false)
  const subscribeTeam = useCallback(
    (teamIds: Array<string>) => {
      teamIds.forEach(id => {
        dispatch({
          type: 'push',
          payload: id,
          group: 'actionLog',
        })
      })
      return () => {
        teamIds.forEach(id => {
          dispatch({
            type: 'remove',
            payload: id,
            group: 'actionLog',
          })
        })
      }
    },
    [dispatch]
  )
  const enableInstructorContext = useCallback(() => {
    setInstructorContext(true)
  }, [setInstructorContext])
  const disableInstructorContext = useCallback(() => {
    setInstructorContext(false)
  }, [setInstructorContext])
  const value = useMemo(
    () => ({
      subscribeTeam,
      teamIds: state.actionLogTeamIds,
      instructorContext,
      enableInstructorContext,
      disableInstructorContext,
    }),
    [
      subscribeTeam,
      state,
      instructorContext,
      enableInstructorContext,
      disableInstructorContext,
    ]
  )
  return <SubscriptionProvider value={value}>{children}</SubscriptionProvider>
}

export default SubscriptionEngine
