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

async function getWorkflowId(
  octokit: github.GitHub,
  runId: number,
  owner: string,
  repo: string
): Promise<number> {
  const reply = await octokit.actions.getWorkflowRun({
    owner,
    repo,
    // eslint-disable-next-line @typescript-eslint/camelcase
    run_id: runId
  })
  core.info(`The source run ${runId} is in ${reply.data.workflow_url} workflow`)
  const workflowIdString = reply.data.workflow_url.split('/').pop() || ''
  if (!(workflowIdString.length > 0)) {
    throw new Error('Could not resolve workflow')
  }
  return parseInt(workflowIdString)
}

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
}

async function findPullRequest(
  octokit: github.GitHub,
  owner: string,
  repo: string,
  headRepo: string,
  headBranch: string,
  headSha: string
): Promise<rest.PullsListResponseItem | null> {
  // Finds Pull request for this workflow run
  core.info(
    `\nFinding PR request id for: owner: ${owner}, Repo:${repo}, Head:${headRepo}:${headBranch}.\n`
  )
  const pullRequests = await octokit.paginate(
    await octokit.pulls.list({
      owner,
      repo,
      head: `${headRepo}:${headBranch}`
    })
  )
  for (const pullRequest of pullRequests) {
    core.info(
      `\nComparing: ${pullRequest.number} sha: ${pullRequest.head.sha} with expected: ${headSha}.\n`
    )
    if (pullRequest.head.sha === headSha) {
      core.info(`\nFound PR: ${pullRequest.number}\n`)
      return pullRequest
    }
  }
  core.info(`\nCould not find the PR for this build :(\n`)
  return null
}

async function getOrigin(
  octokit: github.GitHub,
  runId: number,
  owner: string,
  repo: string
): Promise<
  [string, string, string, string, string, rest.PullsListResponseItem | null]
> {
  const reply = await octokit.actions.getWorkflowRun({
    owner,
    repo,
    // eslint-disable-next-line @typescript-eslint/camelcase
    run_id: runId
  })
  const sourceRun = reply.data
  core.info(
    `Source workflow: Head repo: ${sourceRun.head_repository.full_name}, ` +
      `Head branch: ${sourceRun.head_branch} ` +
      `Event: ${sourceRun.event}, Head sha: ${sourceRun.head_sha}, url: ${sourceRun.url}`
  )
  let pullRequest: rest.PullsListResponseItem | null = null
  if (
    sourceRun.event === 'pull_request' ||
    sourceRun.event === 'pull_request_review'
  ) {
    pullRequest = await findPullRequest(
      octokit,
      owner,
      repo,
      sourceRun.head_repository.owner.login,
      sourceRun.head_branch,
      sourceRun.head_sha
    )
  }

  return [
    reply.data.head_repository.full_name,
    reply.data.head_branch,
    reply.data.event,
    reply.data.head_sha,
    pullRequest ? pullRequest.merge_commit_sha : '',
    pullRequest
  ]
}

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

async function run(): Promise<void> {
  const token = core.getInput('token', {required: true})
  const octokit = new github.GitHub(token)
  const selfRunId = parseInt(getRequiredEnv('GITHUB_RUN_ID'))
  const repository = getRequiredEnv('GITHUB_REPOSITORY')
  const eventName = getRequiredEnv('GITHUB_EVENT_NAME')
  const sourceRunId = parseInt(core.getInput('sourceRunId')) || selfRunId
  const [owner, repo] = repository.split('/')

  core.info(
    `\nGetting workflow id for source run id: ${sourceRunId}, owner: ${owner}, repo: ${repo}\n`
  )
  const sourceWorkflowId = await getWorkflowId(
    octokit,
    sourceRunId,
    owner,
    repo
  )
  core.info(
    `Repository: ${repository}, Owner: ${owner}, Repo: ${repo}, ` +
      `Event name: ${eventName},` +
      `sourceWorkflowId: ${sourceWorkflowId}, sourceRunId: ${sourceRunId}, selfRunId: ${selfRunId}, `
  )

  const [
    headRepo,
    headBranch,
    sourceEventName,
    headSha,
    mergeCommitSha,
    pullRequest
  ] = await getOrigin(octokit, sourceRunId, owner, repo)

  verboseOutput('sourceHeadRepo', headRepo)
  verboseOutput('sourceHeadBranch', headBranch)
  verboseOutput('sourceHeadSha', headSha)
  verboseOutput('sourceEvent', sourceEventName)
  verboseOutput(
    'pullRequestNumber',
    pullRequest ? pullRequest.number.toString() : ''
  )
  const labelNames = pullRequest ? pullRequest.labels.map(x => x.name) : []
  verboseOutput('pullRequestLabels', JSON.stringify(labelNames))
  verboseOutput('mergeCommitSha', mergeCommitSha)
  verboseOutput('targetCommitSha', pullRequest ? mergeCommitSha : headSha)
}

run()
  .then(() =>
    core.info(
      '\n############### Get Workflow Origin complete ##################\n'
    )
  )
  .catch(e => core.setFailed(e.message))
