import type { SpinnerProps } from '@blueprintjs/core'
import { Spinner, SpinnerSize } from '@blueprintjs/core'
import { useApolloNetworkStatus } from '@inject/graphql/client'
import useApolloClient from '@inject/graphql/client/useApolloClient'
import { GetExerciseDocument } from '@inject/graphql/queries/GetExercise.generated'
import { GetExerciseLoopStatusDocument } from '@inject/graphql/queries/GetExerciseLoopStatus.generated'
import { useGetExerciseTimeLeft } from '@inject/graphql/queries/GetExerciseTimeLeft.generated'
import { useEffect, useState } from 'react'
import { HEALTH_CHECK_INTERVAL } from '../utilities'

const HealthCheck = () => {
  const [wasError, setWasError] = useState(false)
  const { loading, error } = useGetExerciseTimeLeft({
    pollInterval: HEALTH_CHECK_INTERVAL,
  })
  const { numPendingQueries, numPendingMutations } = useApolloNetworkStatus()
  const client = useApolloClient()

  /**
   * During a backend server outage, the exercise loop of a running exercise
   * will be stopped, but the exercise will still be marked as running
   *
   * This  inconsistency is resolved in
   * /frontend/graphql/utils/useExerciseSubscriptionStatus.ts by restarting
   * the exercise and refetching the exercise loop status
   *
   * To be able to detect this inconsistency, the relevant queries need to be
   * refetched after the backend server outage
   */
  useEffect(() => {
    if (error) {
      setWasError(true)
    } else {
      if (wasError) {
        setWasError(false)
        client.refetchQueries({
          include: [GetExerciseLoopStatusDocument, GetExerciseDocument],
        })
      }
    }
  }, [client, error, wasError])

  let spinnerProps: SpinnerProps
  if (loading) {
    spinnerProps = {
      value: undefined,
      intent: 'danger',
      title: 'loading',
    }
  } else if (error) {
    spinnerProps = {
      value: 1,
      intent: 'danger',
      title: 'error',
    }
  } else if (numPendingQueries > 0) {
    spinnerProps = {
      value: undefined,
      intent: 'warning',
      title: 'querying',
    }
  } else if (numPendingMutations > 0) {
    spinnerProps = {
      value: undefined,
      intent: 'warning',
      title: 'updating',
    }
  } else {
    spinnerProps = {
      value: 1,
      intent: 'success',
      title: 'running',
    }
  }

  return (
    <Spinner
      size={SpinnerSize.SMALL}
      value={spinnerProps.value}
      intent={spinnerProps.intent}
      title={`backend status: ${spinnerProps.title}`}
    />
  )
}

export default HealthCheck
