const {
  Team,
  User,
  services,
  Fragment,
  Collection,
  authsome: authsomeHelper,
} = require('pubsweet-component-helper-service')

module.exports = models => async (req, res) => {
  const { collectionId, fragmentId } = req.params
  let collection, fragment

  try {
    collection = await models.Collection.find(collectionId)
    if (!collection.fragments.includes(fragmentId))
      return res.status(400).json({
        error: `Collection and fragment do not match.`,
      })
    fragment = await models.Fragment.find(fragmentId)

    const authsome = authsomeHelper.getAuthsome(models)
    const target = {
      fragment,
      path: req.route.path,
    }
    const canPatch = await authsome.can(req.user, 'PATCH', target)
    if (!canPatch)
      return res.status(403).json({
        error: 'Unauthorized.',
      })

    const collectionHelper = new Collection({ collection })
    const fragmentHelper = new Fragment({ fragment })
    const teamHelper = new Team({
      TeamModel: models.Team,
      collectionId,
      fragmentId,
    })

    fragment.authors = fragment.authors || []
    teamHelper.createOrUpdateTeamForNewVersion({
      role: 'author',
      iterable: fragment.authors,
    })

    const authorsTeam = await teamHelper.getTeam({
      role: 'author',
      objectType: 'fragment',
    })

    const userHelper = new User({ UserModel: models.User })
    if (authorsTeam) {
      fragment.authors.forEach(author => {
        userHelper.updateUserTeams({
          userId: author.id,
          teamId: authorsTeam.id,
        })
      })
    }

    fragment.invitations = fragment.invitations || []
    teamHelper.createOrUpdateTeamForNewVersion({
      role: 'reviewer',
      iterable: fragment.invitations,
    })

    const reviewersTeam = await teamHelper.getTeam({
      role: 'reviewer',
      objectType: 'fragment',
    })

    if (reviewersTeam) {
      fragment.invitations.forEach(inv => {
        userHelper.updateUserTeams({
          userId: inv.userId,
          teamId: reviewersTeam.id,
        })
      })
    }

    const fragLength = collection.fragments.length
    if (fragLength < 2) {
      return res.status(400).json({
        error: 'No previous version has been found.',
      })
    }

    const previousFragment = await models.Fragment.find(
      collection.fragments[fragLength - 2],
    )
    fragmentHelper.fragment = previousFragment

    const heRecommendation = fragmentHelper.getHeRequestToRevision()
    if (!heRecommendation) {
      return res.status(400).json({
        error: 'No Handling Editor recommendation has been found.',
      })
    }

    collectionHelper.updateStatusByRecommendation({
      recommendation: heRecommendation.recommendation,
    })

    return res.status(200).json(fragment)
  } catch (e) {
    const notFoundError = await services.handleNotFoundError(e, 'Item')
    return res.status(notFoundError.status).json({
      error: notFoundError.message,
    })
  }
}