const fp = require('fastify-plugin')
const fetch = require('node-fetch')
const {extraceDataFromRequest} = require('../utils')
const {version} = require('../../package.json')

module.exports = fp(initPlugin)

// TODO: get routes for creation tunnel and stop tunnel from the server, so we can change routes in the future
async function initPlugin(fastify, opts) {
  const {
    env: {egTunnelManagerUrl},
  } = opts

  function createTunnel({apiKey, eyesServerUrl, environment}) {
    return _retry(
      async () => {
        const request = fetch(`${egTunnelManagerUrl}/request-tunnel-proxy`, {
          method: 'POST',
          headers: {
            Accept: 'application/json',
            'Content-Type': 'application/json',
            'x-eyes-api-key': apiKey,
            'x-eyes-server-url': eyesServerUrl,
            'x-execution-cloud-tunnel-version': version,
          },
          body: JSON.stringify({environment}),
        })
        return await extraceDataFromRequest(request)
      },
      {
        retries: 3,
        shouldRetry: ({statusCode, error}) =>
          statusCode >= 500 &&
          !(error && error.message && error.message.includes('NO_AVAILABLE_TUNNEL_PROXY')),
      },
    )
  }

  function deleteTunnel({apiKey, tunnelId, eyesServerUrl, reason = 'UNKNOWN'}) {
    return _retry(
      async () => {
        const request = fetch(
          `${egTunnelManagerUrl}/release-tunnel-proxy/${tunnelId}?${new URLSearchParams({
            reason,
          }).toString()}`,
          {
            method: 'DELETE',
            headers: {
              Accept: 'application/json',
              'x-eyes-api-key': apiKey,
              'x-eyes-server-url': eyesServerUrl,
              'x-execution-cloud-tunnel-version': version,
            },
          },
        )

        return await extraceDataFromRequest(request)
      },
      {retries: 3, shouldRetry: (error) => error.statusCode >= 500},
    )
  }

  // How to limit the access to this route?
  function sendHeartBeat(tunnelIds) {
    return fetch(`${egTunnelManagerUrl}/tunnel-hb`, {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        'x-execution-cloud-tunnel-version': version,
      },
      body: JSON.stringify({tunnelIds}),
    })
  }

  fastify.decorate('egTunnelManager', {createTunnel, deleteTunnel, sendHeartBeat})
}

async function _retry(fn, {retries = 3, shouldRetry = (error) => !!error}) {
  let error

  for (let i = 0; i < retries; i++) {
    try {
      return await fn()
    } catch (e) {
      error = e
      if (!shouldRetry(e)) throw error
    }
  }

  throw error
}
