module.exports = authenticationRequestError

const { RequestError } = require('@octokit/request-error')

function authenticationRequestError (state, error, options) {
  if (!error.headers) throw error

  const otpRequired = /required/.test(error.headers['x-github-otp'] || '')
  // handle "2FA required" error only
  if (error.status !== 401 || !otpRequired) {
    throw error
  }

  if (error.status === 401 && otpRequired && error.request && error.request.headers['x-github-otp']) {
    if (state.otp) {
      delete state.otp // no longer valid, request again
    } else {
      throw new RequestError('Invalid one-time password for two-factor authentication', 401, {
        headers: error.headers,
        request: options
      })
    }
  }

  if (typeof state.auth.on2fa !== 'function') {
    throw new RequestError('2FA required, but options.on2fa is not a function. See https://github.com/octokit/rest.js#authentication', 401, {
      headers: error.headers,
      request: options
    })
  }

  return Promise.resolve()
    .then(() => {
      return state.auth.on2fa()
    })
    .then((oneTimePassword) => {
      const newOptions = Object.assign(options, {
        headers: Object.assign(options.headers, { 'x-github-otp': oneTimePassword })
      })
      return state.octokit.request(newOptions)
        .then(response => {
          // If OTP still valid, then persist it for following requests
          state.otp = oneTimePassword
          return response
        })
    })
}
