import {
  CLOUDFLARE_TOO_MANY_REQUESTS_STATUS,
  CLOUDFLARE_SERVICE_UNAVAILABLE_STATUS,
  MAX_NUMBER_OF_RETRIES,
  MILLISECONDS_TO_NEXT_RETRY,
  MULTIPLE_RETRIES_ERROR_MESSAGE,
} from './constants'
import {
  getNumberOfRetries,
  getLastRetryDate,
  setNumberOfRetries,
  setLastRetryDate,
} from './store/retries'
import { pageReload } from './utils/page-reload'
import { reportToSentry } from './utils/report-sentry'

const SEC_30 = 30 * 1000

const getNowDate = () => {
  return new Date()
}

const cloudflareFetchHander = (response: Response) => {
  try {
    if (
      response.status !== CLOUDFLARE_TOO_MANY_REQUESTS_STATUS &&
      response.status !== CLOUDFLARE_SERVICE_UNAVAILABLE_STATUS
    ) {
      return response
    }

    const numberOfRetries = getNumberOfRetries()
    const lastRetryDate = getLastRetryDate()

    const exceedNumberOfRetries = numberOfRetries >= MAX_NUMBER_OF_RETRIES
    const passedEnoughTimeAfterLastRetry =
      lastRetryDate.getTime() + MILLISECONDS_TO_NEXT_RETRY <
      getNowDate().getTime()
    const passedLessThan30SecAfterLastRetry =
      lastRetryDate.getTime() + SEC_30 > getNowDate().getTime()

    if (numberOfRetries >= 1 && passedLessThan30SecAfterLastRetry) {
      reportToSentry(MULTIPLE_RETRIES_ERROR_MESSAGE)
    }

    if (!exceedNumberOfRetries) {
      setLastRetryDate(getNowDate())
      setNumberOfRetries(numberOfRetries + 1)
      pageReload()
    } else if (passedEnoughTimeAfterLastRetry) {
      setLastRetryDate(getNowDate())
      setNumberOfRetries(0)
      pageReload()
    }

    return response
  } catch (e) {
    console.error('cloudflareFetchHander error:', e)

    return response
  }
}

export default cloudflareFetchHander
