import * as github from '@actions/github'
import * as core from '@actions/core'
import * as rest from '@octokit/rest'

function getRequiredEnv(key: string): string {
  const value = process.env[key]
  if (value === undefined) {
    const message = `${key} was not defined.`
    throw new Error(message)
  }
  return value
}

function verboseOutput(name: string, value: string): void {
  core.info(`Setting output: ${name}: ${value}`)
  core.setOutput(name, value)
}

async function getPullRequest(
  octokit: github.GitHub,
  owner: string,
  repo: string,
  pullRequestNumber: number
): Promise<rest.PullsGetResponse> {
  core.info(`Fetching pull request with number: ${pullRequestNumber}`)
  const pullRequest = await octokit.pulls.get({
    owner,
    repo,
    // eslint-disable-next-line @typescript-eslint/camelcase
    pull_number: pullRequestNumber
  })
  return pullRequest.data
}

function getPullRequestLabels(pullRequest: rest.PullsGetResponse): string[] {
  const labelNames = pullRequest
    ? pullRequest.labels.map(label => label.name)
    : []
  return labelNames
}

async function getReviews(
  octokit: github.GitHub,
  owner: string,
  repo: string,
  number: number,
  getComitters: boolean
): Promise<[rest.PullsListReviewsResponseItem[], string[], string[]]> {
  let reviews: rest.PullsListReviewsResponseItem[] = []
  const options = octokit.pulls.listReviews.endpoint.merge({
    owner,
    repo,
    // eslint-disable-next-line @typescript-eslint/camelcase
    pull_number: number
  })
  await octokit.paginate(options).then(r => {
    reviews = r
  })

  const reviewers = reviews ? reviews.map(review => review.user.login) : []
  const reviewersAlreadyChecked: string[] = []
  const committers: string[] = []
  if (getComitters) {
    core.info('Checking reviewers permissions:')
    for (const reviewer of reviewers) {
      if (!reviewersAlreadyChecked.includes(reviewer)) {
        const p = await octokit.repos.getCollaboratorPermissionLevel({
          owner,
          repo,
          username: reviewer
        })
        const permission = p.data.permission
        if (permission === 'admin' || permission === 'write') {
          committers.push(reviewer)
        }
        core.info(`\t${reviewer}: ${permission}`)
        reviewersAlreadyChecked.push(reviewer)
      }
    }
  }
  return [reviews, reviewers, committers]
}

function processReviews(
  reviews: rest.PullsListReviewsResponseItem[],
  reviewers: string[],
  committers: string[],
  requireCommittersApproval: boolean
): boolean {
  let isApproved = false
  const reviewStates: {[user: string]: string} = {}

  for (const review of reviews) {
    if (review.state === 'APPROVED' || review.state === 'CHANGES_REQUESTED') {
      if (requireCommittersApproval && committers.includes(review.user.login)) {
        reviewStates[review.user.login] = review.state
      } else if (!requireCommittersApproval) {
        reviewStates[review.user.login] = review.state
      }
    }
  }

  core.info(`Reviews:`)
  for (const user in reviewStates) {
    core.info(`\t${user}: ${reviewStates[user].toLowerCase()}`)
  }

  for (const user in reviewStates) {
    if (reviewStates[user] === 'APPROVED') {
      isApproved = true
      break
    }
  }
  for (const user in reviewStates) {
    if (reviewStates[user] === 'CHANGES_REQUESTED') {
      isApproved = false
      break
    }
  }

  return isApproved
}

async function setLabel(
  octokit: github.GitHub,
  owner: string,
  repo: string,
  pullRequestNumber: number,
  label: string
): Promise<void> {
  core.info(`Setting label: ${label}`)
  await octokit.issues.addLabels({
    // eslint-disable-next-line @typescript-eslint/camelcase
    issue_number: pullRequestNumber,
    labels: [label],
    owner,
    repo
  })
}

async function removeLabel(
  octokit: github.GitHub,
  owner: string,
  repo: string,
  pullRequestNumber: number,
  label: string
): Promise<void> {
  core.info(`Removing label: ${label}`)
  await octokit.issues.removeLabel({
    // eslint-disable-next-line @typescript-eslint/camelcase
    issue_number: pullRequestNumber,
    name: label,
    owner,
    repo
  })
}

async function addComment(
  octokit: github.GitHub,
  owner: string,
  repo: string,
  pullRequestNumber: number,
  comment: string
): Promise<void> {
  core.info(`Adding comment: ${comment}`)
  await octokit.issues.createComment({
    owner,
    repo,
    // eslint-disable-next-line @typescript-eslint/camelcase
    issue_number: pullRequestNumber,
    body: comment
  })
}

async function printDebug(
  item: object | string | boolean | number,
  description: string = ''
): Promise<void> {
  const itemJson = JSON.stringify(item)
  core.debug(`\n ######### ${description} ######### \n: ${itemJson}\n\n`)
}

async function run(): Promise<void> {
  const token = core.getInput('token', {required: true})
  const userLabel = core.getInput('label') || 'not set'
  const requireCommittersApproval =
    core.getInput('require_committers_approval') === 'true'
  const comment = core.getInput('comment') || ''
  const pullRequestNumberInput = core.getInput('pullRequestNumber') || 'not set'
  const octokit = new github.GitHub(token)
  const context = github.context
  const repository = getRequiredEnv('GITHUB_REPOSITORY')
  const eventName = getRequiredEnv('GITHUB_EVENT_NAME')
  const [owner, repo] = repository.split('/')
  let pullRequestNumber: number | undefined

  core.info(
    `\n############### Set Label When Approved start ##################\n` +
      `label: "${userLabel}"\n` +
      `requireCommittersApproval: ${requireCommittersApproval}\n` +
      `comment: ${comment}\n` +
      `pullRequestNumber: ${pullRequestNumberInput}`
  )

  if (eventName === 'pull_request_review') {
    pullRequestNumber = context.payload.pull_request
      ? context.payload.pull_request.number
      : undefined
    if (pullRequestNumber === undefined) {
      throw Error(`Could not find PR number in context payload.`)
    }
  } else if (eventName === 'workflow_run') {
    if (pullRequestNumberInput === 'not set') {
      core.warning(
        `If action is triggered by "workflow_run" then input "pullRequestNumber" is required.\n` +
          `It might be missing because the pull request might have been already merged or a fixup pushed to` +
          `the PR branch. None of the outputs will be set as we cannot find the right PR.`
      )
      return
    } else {
      pullRequestNumber = parseInt(pullRequestNumberInput)
    }
  } else {
    throw Error(
      `This action is only useful in "pull_request_review" or "workflow_run" triggered runs and you used it in "${eventName}"`
    )
  }

  // PULL REQUEST
  const pullRequest = await getPullRequest(
    octokit,
    owner,
    repo,
    pullRequestNumber
  )

  // LABELS
  const labelNames = getPullRequestLabels(pullRequest)

  // REVIEWS
  const [reviews, reviewers, committers] = await getReviews(
    octokit,
    owner,
    repo,
    pullRequest.number,
    requireCommittersApproval
  )
  const isApproved = processReviews(
    reviews,
    reviewers,
    committers,
    requireCommittersApproval
  )

  // HANDLE LABEL
  let isLabelShouldBeSet = false
  let isLabelShouldBeRemoved = false

  if (userLabel !== 'not set') {
    isLabelShouldBeSet = isApproved && !labelNames.includes(userLabel)
    isLabelShouldBeRemoved = !isApproved && labelNames.includes(userLabel)

    if (isLabelShouldBeSet) {
      await setLabel(octokit, owner, repo, pullRequest.number, userLabel)
      if (comment !== '') {
        await addComment(octokit, owner, repo, pullRequest.number, comment)
      }
    } else if (isLabelShouldBeRemoved) {
      await removeLabel(octokit, owner, repo, pullRequest.number, userLabel)
    }
  }

  // OUTPUT
  verboseOutput('isApproved', String(isApproved))
  verboseOutput('labelSet', String(isLabelShouldBeSet))
  verboseOutput('labelRemoved', String(isLabelShouldBeRemoved))
}

run()
  .then(() =>
    core.info(
      '\n############### Set Label When Approved complete ##################\n'
    )
  )
  .catch(e => core.setFailed(e.message))
