text: 'use strict'
  
  const Joi = require('@hapi/joi')
  const { latest } = require('../version')
  const { NotFound } = require('..')
  const { errorMessagesFor } = require('./github-helpers')
  
  const releaseInfoSchema = Joi.object({
    tag_name: Joi.string().required(),
    prerelease: Joi.boolean().required(),
  }).required()
  
  // Fetch the 'latest' release as defined by the GitHub API
  async function fetchLatestGitHubRelease(serviceInstance, { user, repo }) {
    const commonAttrs = {
      errorMessages: errorMessagesFor('no releases or repo not found'),
    }
    const releaseInfo = await serviceInstance._requestJson({
      schema: releaseInfoSchema,
      url: `/repos/${user}/${repo}/releases/latest`,
      ...commonAttrs,
    })
    return releaseInfo
  }
  
  const releaseInfoArraySchema = Joi.alternatives().try(
    Joi.array().items(releaseInfoSchema),
    Joi.array().length(0)
  )
  
  async function fetchReleases(serviceInstance, { user, repo }) {
    const commonAttrs = {
      errorMessages: errorMessagesFor('repo not found'),
    }
    const releases = await serviceInstance._requestJson({
      url: `/repos/${user}/${repo}/releases`,
      schema: releaseInfoArraySchema,
      ...commonAttrs,
    })
    return releases
  }
  
  function getLatestRelease({ releases, sort, includePrereleases }) {
    if (sort === 'semver') {
      const latestRelease = latest(
        releases.map(release => release.tag_name),
        {
          pre: includePrereleases,
        }
      )
      const kvpairs = Object.assign(
        ...releases.map(release => ({ [release.tag_name]: release.prerelease }))
      )
      return { tag_name: latestRelease, prerelease: kvpairs[latestRelease] }
    }
  
    if (!includePrereleases) {
      const stableReleases = releases.filter(release => !release.prerelease)
      if (stableReleases.length > 0) {
        return stableReleases[0]
      }
    }
  
    return releases[0]
  }
  
  const queryParamSchema = Joi.object({
    include_prereleases: Joi.equal(''),
    sort: Joi.string()
      .valid('date', 'semver')
      .default('date'),
  }).required()
  
  // Fetch the latest release as defined by query params
  async function fetchLatestRelease(
    serviceInstance,
    { user, repo },
    queryParams
  ) {
    const sort = queryParams.sort
    const includePrereleases = queryParams.include_prereleases !== undefined
  
    if (!includePrereleases && sort === 'date') {
      const releaseInfo = await fetchLatestGitHubRelease(serviceInstance, {
        user,
        repo,
      })
      return releaseInfo
    }
  
    const releases = await fetchReleases(serviceInstance, { user, repo })
    if (releases.length === 0) {
      throw new NotFound({ prettyMessage: 'no releases' })
    }
    const latestRelease = getLatestRelease({ releases, sort, includePrereleases })
    return latestRelease
  }
  
  module.exports = {
    fetchLatestRelease,
    queryParamSchema,
    _getLatestRelease: getLatestRelease, // currently only used for tests
  }
  