import { useEffect, useMemo } from 'react'
import type { ResultOf, VariablesOf } from '../../graphql'
import { useTypedQuery } from '../../graphql'
import {
  setIsUnreadChannel,
  setIsUnreadEmailThread,
} from '../../mutations.client'
import {
  GetEmailThreads,
  GetTeamActionLogsLookup,
  GetTeamTools,
} from '../../queries'
import { teamAction } from '../../subscriptions'
import { useClient } from '../../urql/client'
import type { ActionLogPayload } from '../../urql/events'
import isOverlay from '../isOverlay'
import useExerciseLoopStatusSubscription from '../useExerciseLoopStatusSubscription'
import { isInCurrentContext, useGenericActionLogEvent } from './utils'

const useActionLogSubscriptionTrainee = ({
  teamId,
  exerciseId,
}: {
  teamId: string
  exerciseId: string
}) => {
  const client = useClient()
  useExerciseLoopStatusSubscription(exerciseId)

  useTypedQuery({
    query: GetEmailThreads,
    variables: {
      teamId,
    },
    requestPolicy: 'cache-and-network',
    context: useMemo(
      () => ({
        suspense: true,
      }),
      []
    ),
  })

  // mark unread channels when entering the exercise
  const [{ data, fetching }] = useTypedQuery({
    query: GetTeamActionLogsLookup,
    variables: {
      teamId,
    },
    context: useMemo(
      () => ({
        suspense: true,
      }),
      []
    ),
  })
  useEffect(() => {
    if (fetching || !data) {
      return
    }

    const setChannelIds = new Set<string>()
    const setThreadIds = new Set<string>()
    data.actionLogs.forEach(actionLog => {
      if (
        !actionLog.readReceipt &&
        !isInCurrentContext(actionLog) &&
        !isOverlay(actionLog) &&
        !(
          actionLog.details.__typename === 'EmailType' &&
          actionLog.details.readReceipt
        )
      ) {
        setChannelIds.add(actionLog.channel.id)
        if (actionLog.details.__typename === 'EmailType') {
          setThreadIds.add(actionLog.details.thread.id)
        }
      }
    })
    setChannelIds.forEach(channelId =>
      client
        .mutation(setIsUnreadChannel, {
          channelId,
          teamId,
          isUnread: true,
        })
        .toPromise()
    )
    setThreadIds.forEach(threadId =>
      client
        .mutation(setIsUnreadEmailThread, {
          threadId,
          teamId,
          isUnread: true,
        })
        .toPromise()
    )
  }, [fetching, data, client, teamId])

  useEffect(() => {
    client.query<
      ResultOf<typeof GetTeamTools>,
      VariablesOf<typeof GetTeamTools>
    >(GetTeamTools, {
      teamId,
    })
    const { unsubscribe: unsubLog } = client
      .subscription<ResultOf<typeof teamAction>>(teamAction, {
        teamId,
      })
      .subscribe(({ data }) => {
        if (data?.actionLogs?.actionLog) {
          window.dispatchEvent(
            new CustomEvent<ActionLogPayload>('actionLogEvent', {
              detail: {
                actionLog: data.actionLogs.actionLog,
                eventType: data.actionLogs.eventType,
              },
            })
          )
        }
      })

    return () => {
      unsubLog()
    }
  }, [client, exerciseId, teamId])

  useGenericActionLogEvent()
}

export default useActionLogSubscriptionTrainee
