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

/**
 Those are the cancellable event types tht we know about
 */
const CANCELLABLE_EVENT_TYPES = [
  'push',
  'pull_request',
  'workflow_run',
  'schedule',
  'workflow_dispatch'
]

/**
 * Those are different modes for cancelling
 */
enum CancelMode {
  DUPLICATES = 'duplicates',
  ALL_DUPLICATES = 'allDuplicates',
  SELF = 'self',
  FAILED_JOBS = 'failedJobs',
  NAMED_JOBS = 'namedJobs',
  ALL_DUPLICATED_NAMED_JOBS = 'allDuplicatedNamedJobs'
}

/**
 * Stores information about the owner and repository used, as well as octokit object that is used for
 * authentication.
 */
interface RepositoryInfo {
  octokit: github.GitHub
  owner: string
  repo: string
}

/**
 * Stores information about the workflow info that triggered the current workflow.
 */
interface TriggeringRunInfo {
  workflowId: number
  runId: number
  headRepo: string
  headBranch: string
  headSha: string
  eventName: string
  mergeCommitSha: string | null
  pullRequest: rest.PullsListResponseItem | null
}

/**
 * Converts the source of a run object into a string that can be used as map key in maps where we keep
 * arrays of runs per source group
 * @param triggeringRunInfo the object identifying the triggering workflow
 * @returns the unique string id for the source group
 */
function getSourceGroupId(triggeringRunInfo: TriggeringRunInfo): string {
  return (
    `:${triggeringRunInfo.workflowId}:${triggeringRunInfo.headRepo}` +
    `:${triggeringRunInfo.headBranch}:${triggeringRunInfo.eventName}`
  )
}

/**
 * Creates query parameters selecting all runs that share the same source group as we have. This can
 * be used to select duplicates of my own run.
 *
 * @param repositoryInfo - information about the repository used
 * @param status - status of the run that we are querying for
 * @param triggeringRunInfo - information about the workflow that triggered the run
 * @return query parameters merged with the listWorkflowRuns criteria
 */
function createListRunsQueryRunsSameSource(
  repositoryInfo: RepositoryInfo,
  status: string,
  triggeringRunInfo: TriggeringRunInfo
): rest.RequestOptions {
  const request = {
    owner: repositoryInfo.owner,
    repo: repositoryInfo.repo,
    // eslint-disable-next-line @typescript-eslint/camelcase
    workflow_id: triggeringRunInfo.workflowId,
    status,
    branch: triggeringRunInfo.headBranch,
    event: triggeringRunInfo.eventName
  }
  return repositoryInfo.octokit.actions.listWorkflowRuns.endpoint.merge(request)
}
/**
 * Creates query parameters selecting only specific run Id.
 * @param repositoryInfo - information about the repository used
 * @param status - status of the run that we are querying for
 * @param triggeringRunInfo - information about the workflow that triggered the run
 * @return query parameters merged with the listWorkflowRuns criteria
 */
function createListRunsQuerySpecificRunId(
  repositoryInfo: RepositoryInfo,
  status: string,
  triggeringRunInfo: TriggeringRunInfo
): rest.RequestOptions {
  const request = {
    owner: repositoryInfo.owner,
    repo: repositoryInfo.repo,
    // eslint-disable-next-line @typescript-eslint/camelcase
    workflow_id: triggeringRunInfo.workflowId,
    status,
    // eslint-disable-next-line @typescript-eslint/camelcase
    run_id: triggeringRunInfo.runId.toString()
  }
  return repositoryInfo.octokit.actions.listWorkflowRuns.endpoint.merge(request)
}

/**
 * Creates query parameters selecting all run Ids for specified workflow Id.
 * @param repositoryInfo - information about the repository used
 * @param status - status of the run that we are querying for
 * @param workflowId - Id of the workflow to retrieve
 * @return query parameters merged with the listWorkflowRuns criteria
 */
function createListRunsQueryAllRuns(
  repositoryInfo: RepositoryInfo,
  status: string,
  workflowId: number | string
): rest.RequestOptions {
  const request = {
    owner: repositoryInfo.owner,
    repo: repositoryInfo.repo,
    // eslint-disable-next-line @typescript-eslint/camelcase
    workflow_id: workflowId,
    status
  }
  return repositoryInfo.octokit.actions.listWorkflowRuns.endpoint.merge(request)
}

/**
 * Creates query parameters selecting all jobs for specified run Id.
 * @param repositoryInfo - information about the repository used
 * @param runId - Id of the run to retrieve jobs for
 * @return query parameters merged with the listJobsForWorkflowRun criteria
 */
function createJobsForWorkflowRunQuery(
  repositoryInfo: RepositoryInfo,
  runId: number
): rest.RequestOptions {
  const request = {
    owner: repositoryInfo.owner,
    repo: repositoryInfo.repo,
    // eslint-disable-next-line @typescript-eslint/camelcase
    run_id: runId
  }
  return repositoryInfo.octokit.actions.listJobsForWorkflowRun.endpoint.merge(
    request
  )
}

/**
 * Returns true if the string matches any of the regexps in array of regexps
 * @param stringToMatch string to match
 * @param regexps array of regexp to match the string against
 * @return array of [matched (boolean), [array of matched strings]]
 */
function matchInArray(
  stringToMatch: string,
  regexps: string[]
): [boolean, string[]] {
  let matched = false
  const allMatches: string[] = []
  for (const regexp of regexps) {
    const match = stringToMatch.match(regexp)
    if (match) {
      matched = true
      allMatches.push(match[0])
    }
  }
  return [matched, allMatches]
}

/**
 * Adds workflow run to the array in the map indexed by key.
 * @param key key to use
 * @param runItem run Item to add
 * @param mapOfWorkflowRunCandidates map of workflow runs to add the run item to
 */
function addWorkflowRunToMap(
  key: string,
  runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
  mapOfWorkflowRunCandidates: Map<
    string,
    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
  >
): void {
  let arrayOfRuns = mapOfWorkflowRunCandidates.get(key)
  if (arrayOfRuns === undefined) {
    arrayOfRuns = []
    mapOfWorkflowRunCandidates.set(key, arrayOfRuns)
  }
  arrayOfRuns.push(runItem)
}

/**
 * Returns true if the runId specified has jobs matching the regexp and optionally checks if those
 * jobs are failed.
 * * If checkIfFailed is False, it returns true if any of the job name for the run match any of the regexps
 * * Id checkIfFailed is True, it returns true if any of the matching jobs have status 'failed'
 * @param repositoryInfo - information about the repository used
 * @param runId - Id of the run to retrieve jobs for
 * @param jobNameRegexps - array of job name regexps
 * @param checkIfFailed - whether to check the 'failed' status of matched jobs
 * @return array of [matched (boolean), array of matches]
 */
async function jobsMatchingNames(
  repositoryInfo: RepositoryInfo,
  runId: number,
  jobNameRegexps: string[],
  checkIfFailed: boolean
): Promise<[boolean, string[]]> {
  const listJobs = createJobsForWorkflowRunQuery(repositoryInfo, runId)
  if (checkIfFailed) {
    core.info(
      `\nChecking if runId ${runId} has job names matching any of the ${jobNameRegexps} that failed\n`
    )
  } else {
    core.info(
      `\nChecking if runId ${runId} has job names matching any of the ${jobNameRegexps}\n`
    )
  }
  const allMatches: string[] = []
  let matched = false
  for await (const item of repositoryInfo.octokit.paginate.iterator(listJobs)) {
    for (const job of item.data) {
      core.info(`    The job name: ${job.name}, Conclusion: ${job.conclusion}`)
      const [jobMatched, jobMatches] = matchInArray(job.name, jobNameRegexps)
      if (jobMatched) {
        allMatches.push(...jobMatches)
        matched = true
        if (checkIfFailed) {
          // Only fail the build if one of the matching jobs fail
          if (job.conclusion === 'failure') {
            core.info(
              `    The Job ${job.name} matches one of the ${jobNameRegexps} regexps and it failed.` +
                ` It will be added to the candidates.`
            )
          } else {
            core.info(
              `    The Job ${job.name} matches one of the ${jobNameRegexps} regexps but it did not fail. ` +
                ` So far, so good.`
            )
          }
        } else {
          // Fail the build if any of the job names match
          core.info(
            `    The Job ${job.name} matches one of the ${jobNameRegexps} regexps. ` +
              `It will be added to the candidates.`
          )
        }
      }
    }
  }
  return [matched, allMatches]
}

/**
 * Retrieves workflowId from the workflow URL.
 * @param workflowUrl workflow URL to retrieve the ID from
 * @return numerical workflow id
 */
function retrieveWorkflowIdFromUrl(workflowUrl: string): number {
  const workflowIdString = workflowUrl.split('/').pop() || ''
  if (!(workflowIdString.length > 0)) {
    throw new Error('Could not resolve workflow')
  }
  return parseInt(workflowIdString)
}

/**
 * Returns workflowId of the runId specified
 * @param repositoryInfo - information about the repository used
 * @param runId - Id of the run to retrieve jobs for
 * @return workflow ID for the run id
 */
async function getWorkflowId(
  repositoryInfo: RepositoryInfo,
  runId: number
): Promise<number> {
  const reply = await repositoryInfo.octokit.actions.getWorkflowRun({
    owner: repositoryInfo.owner,
    repo: repositoryInfo.repo,
    // eslint-disable-next-line @typescript-eslint/camelcase
    run_id: runId
  })
  core.info(`The source run ${runId} is in ${reply.data.workflow_url} workflow`)
  return retrieveWorkflowIdFromUrl(reply.data.workflow_url)
}

/**
 * Returns workflow runs matching the callable adding query criteria
 * @param repositoryInfo - information about the repository used
 * @param statusValues - array of string status values for runs that we are interested at
 * @param cancelMode - which cancel mode the query is about
 * @param createListRunQuery - what is the callable criteria selection
 * @return map of workflow run items indexed by the workflow run number
 */
async function getWorkflowRuns(
  repositoryInfo: RepositoryInfo,
  statusValues: string[],
  cancelMode: CancelMode,
  createListRunQuery: CallableFunction
): Promise<Map<number, rest.ActionsListWorkflowRunsResponseWorkflowRunsItem>> {
  const workflowRuns = new Map<
    number,
    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem
  >()
  for (const status of statusValues) {
    const listRuns = await createListRunQuery(status)
    for await (const item of repositoryInfo.octokit.paginate.iterator(
      listRuns
    )) {
      // There is some sort of bug where the pagination URLs point to a
      // different endpoint URL which trips up the resulting representation
      // In that case, fallback to the actual REST 'workflow_runs' property
      const elements =
        item.data.length === undefined ? item.data.workflow_runs : item.data
      for (const element of elements) {
        workflowRuns.set(element.run_number, element)
      }
    }
  }
  core.info(`\nFound runs: ${Array.from(workflowRuns).map(t => t[0])}\n`)
  return workflowRuns
}

/**
 * True if the request is candidate for cancelling in case of duplicate deletion
 * @param runItem item to check
 * @param cancelFutureDuplicates whether future duplicates are being cancelled
 * @param triggeringRunInfo - information about the workflow that triggered the run
 * @param mapOfWorkflowRunCandidates - map of the workflow runs to add candidates to
 * @return true if we determine that the run Id should be cancelled
 */
function checkCandidateForCancellingDuplicate(
  runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
  cancelFutureDuplicates: boolean,
  triggeringRunInfo: TriggeringRunInfo,
  mapOfWorkflowRunCandidates: Map<
    string,
    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
  >
): void {
  const runHeadRepo = runItem.head_repository.full_name
  if (
    triggeringRunInfo.headRepo !== undefined &&
    runHeadRepo !== triggeringRunInfo.headRepo
  ) {
    core.info(
      `\nThe run ${runItem.id} is from a different ` +
        `repo: ${runHeadRepo} (expected ${triggeringRunInfo.headRepo}). Not adding as candidate to cancel.\n`
    )
  }
  if (cancelFutureDuplicates) {
    core.info(
      `\nCancel Future Duplicates: Returning run id that might be duplicate or my own run: ${runItem.id}.\n`
    )
    addWorkflowRunToMap(
      getSourceGroupId(triggeringRunInfo),
      runItem,
      mapOfWorkflowRunCandidates
    )
  } else {
    if (runItem.id === triggeringRunInfo.runId) {
      core.info(`\nThis is my own run ${runItem.id}. Not returning myself!\n`)
    } else if (runItem.id > triggeringRunInfo.runId) {
      core.info(
        `\nThe run ${runItem.id} is started later than my own ` +
          `run ${triggeringRunInfo.runId}. Not returning it\n`
      )
    }
    core.info(`\nFound duplicate of my own run: ${runItem.id}.\n`)
  }
}

/**
 * Should the run be candidate for cancelling in SELF cancelling mode?
 * @param runItem run item
 * @param triggeringRunInfo - information about the workflow that triggered the run
 * @param mapOfWorkflowRunCandidates - map of the workflow runs to add candidates to
 */
function checkCandidateForCancellingSelf(
  runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
  triggeringRunInfo: TriggeringRunInfo,
  mapOfWorkflowRunCandidates: Map<
    string,
    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
  >
): void {
  if (runItem.id === triggeringRunInfo.runId) {
    core.info(`\nAdding the "source" run: ${runItem.id} to candidates.\n`)
    addWorkflowRunToMap(
      getSourceGroupId(triggeringRunInfo),
      runItem,
      mapOfWorkflowRunCandidates
    )
  }
}

/**
 * Should the run be candidate for cancelling of all duplicates
 * @param runItem run item
 * @param triggeringRunInfo - information about the workflow that triggered the run
 * @param mapOfWorkflowRunCandidates - map of the workflow runs to add candidates to
 */
function checkCandidateForAllDuplicates(
  runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
  triggeringRunInfo: TriggeringRunInfo,
  mapOfWorkflowRunCandidates: Map<
    string,
    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
  >
): void {
  core.info(`\nAdding the run: ${runItem.id} to candidates.\n`)
  addWorkflowRunToMap(
    getSourceGroupId(triggeringRunInfo),
    runItem,
    mapOfWorkflowRunCandidates
  )
}

/**
 * Should the run is candidate for cancelling in naming job cancelling mode?
 * @param repositoryInfo - information about the repository used
 * @param runItem run item
 * @param jobNamesRegexps array of regexps to match job names against
 * @param triggeringRunInfo - information about the workflow that triggered the run
 * @param mapOfWorkflowRunCandidates - map of the workflow runs to add candidates to
 * @return true if the run item contains jobs with names matching the pattern
 */
async function checkCandidateForCancellingNamedJobs(
  repositoryInfo: RepositoryInfo,
  runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
  jobNamesRegexps: string[],
  triggeringRunInfo: TriggeringRunInfo,
  mapOfWorkflowRunCandidates: Map<
    string,
    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
  >
): Promise<void> {
  // Cancel all jobs that have failed jobs (no matter when started)
  const [matched, allMatches] = await jobsMatchingNames(
    repositoryInfo,
    runItem.id,
    jobNamesRegexps,
    false
  )
  if (matched) {
    core.info(
      `\nSome jobs have matching names in ${runItem.id}: ${allMatches}. Adding it candidates.\n`
    )
    addWorkflowRunToMap(
      getSourceGroupId(triggeringRunInfo),
      runItem,
      mapOfWorkflowRunCandidates
    )
  } else {
    core.info(`\nNone of the jobs match name in ${runItem.id}.\n`)
  }
}

/**
 * Should the run is candidate for cancelling in failed job cancelling mode?
 * @param repositoryInfo - information about the repository used
 * @param runItem run item
 * @param jobNamesRegexps array of regexps to match job names against
 * @param triggeringRunInfo - information about the workflow that triggered the run
 * @param mapOfWorkflowRunCandidates - map of the workflow runs to add candidates to
 * @return true if the run item contains failed jobs with names matching the pattern
 */
async function checkCandidateForCancellingFailedJobs(
  repositoryInfo: RepositoryInfo,
  runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
  jobNamesRegexps: string[],
  triggeringRunInfo: TriggeringRunInfo,
  mapOfWorkflowRunCandidates: Map<
    string,
    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
  >
): Promise<void> {
  // Cancel all jobs that have failed jobs (no matter when started)
  const [matched, allMatches] = await jobsMatchingNames(
    repositoryInfo,
    runItem.id,
    jobNamesRegexps,
    true
  )
  if (matched) {
    core.info(
      `\nSome matching named jobs failed in ${runItem.id}: ${allMatches}. Adding it to candidates.\n`
    )
    addWorkflowRunToMap(
      getSourceGroupId(triggeringRunInfo),
      runItem,
      mapOfWorkflowRunCandidates
    )
  } else {
    core.info(
      `\nNone of the matching jobs failed in ${runItem.id}. Not adding as candidate to cancel.\n`
    )
  }
}

/**
 * Checks if the run is candidate for duplicate cancelling of named jobs. It adds it to the map
 * including the match as a key for duplicate detection.
 * @param repositoryInfo - information about the repository used
 * @param runItem - run item
 * @param jobNamesRegexps - array of regexps to match job names against
 * @param mapOfWorkflowRunCandidates - map of runs to update
 */
async function checkCandidateForDuplicateNamedJobs(
  repositoryInfo: RepositoryInfo,
  runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
  jobNamesRegexps: string[],
  mapOfWorkflowRunCandidates: Map<
    string,
    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
  >
): Promise<void> {
  const [matched, allMatches] = await jobsMatchingNames(
    repositoryInfo,
    runItem.id,
    jobNamesRegexps,
    false
  )
  if (matched) {
    for (const match of allMatches) {
      // This is the only case where we are not using source group to cancelling candidates but
      // the match of job names
      addWorkflowRunToMap(match, runItem, mapOfWorkflowRunCandidates)
    }
  }
}

/**
 * Determines whether the run is candidate to be cancelled depending on the mode used and add it to the map
 * of workflow names if it is.
 * @param repositoryInfo - information about the repository used
 * @param runItem - run item
 * @param triggeringRunInfo - information about the workflow that triggered the run
 * @param cancelMode - cancel mode
 * @param cancelFutureDuplicates - whether to cancel future duplicates
 * @param jobNamesRegexps - what are the regexps for job names
 * @param skipEventTypes - which events should be skipped
 * @param mapOfWorkflowRunCandidates - map of workflow runs to add candidates to
 */
async function checkCandidateForCancelling(
  repositoryInfo: RepositoryInfo,
  runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
  triggeringRunInfo: TriggeringRunInfo,
  cancelMode: CancelMode,
  cancelFutureDuplicates: boolean,
  jobNamesRegexps: string[],
  skipEventTypes: string[],
  mapOfWorkflowRunCandidates: Map<
    string,
    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
  >
): Promise<void> {
  if ('completed' === runItem.status.toString()) {
    core.info(
      `\nThe run ${runItem.id} is completed. Not adding as candidate to cancel.\n`
    )
    return
  }
  if (!CANCELLABLE_EVENT_TYPES.includes(runItem.event.toString())) {
    core.info(
      `\nThe run ${runItem.id} is (${runItem.event} event - not ` +
        `in ${CANCELLABLE_EVENT_TYPES}). Not adding as candidate to cancel.\n`
    )
    return
  }
  if (skipEventTypes.includes(runItem.event.toString())) {
    core.info(
      `\nThe run ${runItem.id} is (${runItem.event} event - ` +
        `it is in skipEventTypes ${skipEventTypes}). Not adding as candidate to cancel.\n`
    )
    return
  }
  if (cancelMode === CancelMode.FAILED_JOBS) {
    await checkCandidateForCancellingFailedJobs(
      repositoryInfo,
      runItem,
      jobNamesRegexps,
      triggeringRunInfo,
      mapOfWorkflowRunCandidates
    )
  } else if (cancelMode === CancelMode.NAMED_JOBS) {
    await checkCandidateForCancellingNamedJobs(
      repositoryInfo,
      runItem,
      jobNamesRegexps,
      triggeringRunInfo,
      mapOfWorkflowRunCandidates
    )
  } else if (cancelMode === CancelMode.SELF) {
    checkCandidateForCancellingSelf(
      runItem,
      triggeringRunInfo,
      mapOfWorkflowRunCandidates
    )
  } else if (cancelMode === CancelMode.DUPLICATES) {
    checkCandidateForCancellingDuplicate(
      runItem,
      cancelFutureDuplicates,
      triggeringRunInfo,
      mapOfWorkflowRunCandidates
    )
  } else if (cancelMode === CancelMode.ALL_DUPLICATES) {
    checkCandidateForAllDuplicates(
      runItem,
      triggeringRunInfo,
      mapOfWorkflowRunCandidates
    )
  } else if (cancelMode === CancelMode.ALL_DUPLICATED_NAMED_JOBS) {
    await checkCandidateForDuplicateNamedJobs(
      repositoryInfo,
      runItem,
      jobNamesRegexps,
      mapOfWorkflowRunCandidates
    )
    return
  } else {
    throw Error(`\nWrong cancel mode ${cancelMode}! Please correct it!.\n`)
  }
}

/**
 * Cancels the specified workflow run.
 * @param repositoryInfo - information about the repository used
 * @param runId - run Id to cancel
 */
async function cancelRun(
  repositoryInfo: RepositoryInfo,
  runId: number
): Promise<void> {
  let reply
  try {
    reply = await repositoryInfo.octokit.actions.cancelWorkflowRun({
      owner: repositoryInfo.owner,
      repo: repositoryInfo.repo,
      // eslint-disable-next-line @typescript-eslint/camelcase
      run_id: runId
    })
    core.info(`\nThe run ${runId} cancelled, status = ${reply.status}\n`)
  } catch (error) {
    core.warning(
      `\nCould not cancel run ${runId}: [${error.status}] ${error.message}\n`
    )
  }
}

/**
 * Returns map of workflow run items matching the criteria specified group by workflow run id
 * @param repositoryInfo - information about the repository used
 * @param statusValues - status values we want to check
 * @param cancelMode - cancel mode to use
 * @param triggeringRunInfo - information about the workflow that triggered the run
 * @return map of the run items matching grouped by workflow run id
 */
async function getWorkflowRunsMatchingCriteria(
  repositoryInfo: RepositoryInfo,
  statusValues: string[],
  cancelMode: CancelMode,
  triggeringRunInfo: TriggeringRunInfo
): Promise<Map<number, rest.ActionsListWorkflowRunsResponseWorkflowRunsItem>> {
  return await getWorkflowRuns(
    repositoryInfo,
    statusValues,
    cancelMode,
    function(status: string) {
      if (cancelMode === CancelMode.SELF) {
        core.info(
          `\nFinding runs for my own run: Owner: ${repositoryInfo.owner}, Repo: ${repositoryInfo.repo}, ` +
            `Workflow ID:${triggeringRunInfo.workflowId},` +
            `Source Run id: ${triggeringRunInfo.runId}\n`
        )
        return createListRunsQuerySpecificRunId(
          repositoryInfo,
          status,
          triggeringRunInfo
        )
      } else if (
        cancelMode === CancelMode.FAILED_JOBS ||
        cancelMode === CancelMode.NAMED_JOBS ||
        cancelMode === CancelMode.ALL_DUPLICATES ||
        cancelMode === CancelMode.ALL_DUPLICATED_NAMED_JOBS
      ) {
        core.info(
          `\nFinding runs for all runs: Owner: ${repositoryInfo.owner}, Repo: ${repositoryInfo.repo}, ` +
            `Status: ${status} Workflow ID:${triggeringRunInfo.workflowId}\n`
        )
        return createListRunsQueryAllRuns(
          repositoryInfo,
          status,
          triggeringRunInfo.workflowId
        )
      } else if (cancelMode === CancelMode.DUPLICATES) {
        core.info(
          `\nFinding duplicate runs: Owner: ${repositoryInfo.owner}, Repo: ${repositoryInfo.repo}, ` +
            `Status: ${status} Workflow ID:${triggeringRunInfo.workflowId}, ` +
            `Head Branch: ${triggeringRunInfo.headBranch},` +
            `Event name: ${triggeringRunInfo.eventName}\n`
        )
        return createListRunsQueryRunsSameSource(
          repositoryInfo,
          status,
          triggeringRunInfo
        )
      } else {
        throw Error(`\nWrong cancel mode ${cancelMode}! Please correct it.\n`)
      }
    }
  )
}

/**
 * Finds pull request matching its headRepo, headBranch and headSha
 * @param repositoryInfo - information about the repository used
 * @param headRepo - head repository from which Pull Request comes
 * @param headBranch - head branch from which Pull Request comes
 * @param headSha - sha for the head of the incoming Pull request
 */
async function findPullRequest(
  repositoryInfo: RepositoryInfo,
  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: ${repositoryInfo.owner}, Repo:${repositoryInfo.repo},` +
      ` Head:${headRepo}:${headBranch}.\n`
  )
  const pullRequests = await repositoryInfo.octokit.pulls.list({
    owner: repositoryInfo.owner,
    repo: repositoryInfo.repo,
    head: `${headRepo}:${headBranch}`
  })
  for (const pullRequest of pullRequests.data) {
    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
}

/**
 * Finds pull request id for the run item.
 * @param repositoryInfo - information about the repository used
 * @param runItem - run Item that the pull request should be found for
 * @return pull request number to notify (or undefined if not found)
 */
async function findPullRequestForRunItem(
  repositoryInfo: RepositoryInfo,
  runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem
): Promise<number | undefined> {
  const pullRequest = await findPullRequest(
    repositoryInfo,
    runItem.head_repository.owner.login,
    runItem.head_branch,
    runItem.head_sha
  )
  if (pullRequest) {
    return pullRequest.number
  }
  return undefined
}

/**
 * Maps found workflow runs into groups - filters out the workflows that are not eligible for cancelling
 * (depends on cancel Mode) and assigns each workflow to groups - where workflow runs from the
 * same group are put together in one array - in a map indexed by the source group id.
 *
 * @param repositoryInfo - information about the repository used
 * @param triggeringRunInfo - information about the workflow that triggered the run
 * @param cancelMode - cancel mode to use
 * @param cancelFutureDuplicates - whether to cancel future duplicates
 * @param jobNameRegexps - regexps for job names
 * @param skipEventTypes - array of event names to skip
 * @param selfPreservation - whether the run will cancel itself if requested
 * @param selfRunId - my own run id
 * @param workflowRuns - map of workflow runs found
 * @parm maps with string key and array of run items as value. The key might be
 *       * source group id (allDuplicates mode)
 *       * matching job name (allDuplicatedMatchingJobNames mode)
 */
async function filterAndMapWorkflowRunsToGroups(
  repositoryInfo: RepositoryInfo,
  triggeringRunInfo: TriggeringRunInfo,
  cancelMode: CancelMode,
  cancelFutureDuplicates: boolean,
  jobNameRegexps: string[],
  skipEventTypes: string[],
  selfRunId: number,
  selfPreservation: boolean,
  workflowRuns: Map<
    number,
    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem
  >
): Promise<
  Map<string, rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]>
> {
  const mapOfWorkflowRunCandidates = new Map()
  for (const [key, runItem] of workflowRuns) {
    core.info(
      `\nChecking run number: ${key} RunId: ${runItem.id} Url: ${runItem.url} Status ${runItem.status}` +
        ` Created at ${runItem.created_at}\n`
    )
    if (runItem.id === selfRunId && selfPreservation) {
      core.info(
        `\nI have self-preservation built in. I refuse to cancel myself :)\n`
      )
      continue
    }
    await checkCandidateForCancelling(
      repositoryInfo,
      runItem,
      triggeringRunInfo,
      cancelMode,
      cancelFutureDuplicates,
      jobNameRegexps,
      skipEventTypes,
      mapOfWorkflowRunCandidates
    )
  }
  return mapOfWorkflowRunCandidates
}

/**
 * Add specified comment to Pull Request
 * @param repositoryInfo - information about the repository used
 * @param pullRequestNumber - number of pull request
 * @param comment - comment to add
 */
async function addCommentToPullRequest(
  repositoryInfo: RepositoryInfo,
  pullRequestNumber: number,
  comment: string
): Promise<void> {
  core.info(`\nNotifying PR: ${pullRequestNumber} with '${comment}'.\n`)
  await repositoryInfo.octokit.issues.createComment({
    owner: repositoryInfo.owner,
    repo: repositoryInfo.repo,
    // eslint-disable-next-line @typescript-eslint/camelcase
    issue_number: pullRequestNumber,
    body: comment
  })
}

/**
 * Notifies PR about cancelling
 * @param repositoryInfo - information about the repository used
 * @param selfRunId - my own run id
 * @param pullRequestNumber - number of pull request
 * @param reason reason for cancelling
 */
async function notifyPR(
  repositoryInfo: RepositoryInfo,
  selfRunId: number,
  pullRequestNumber: number,
  reason: string
): Promise<void> {
  const selfWorkflowRunUrl =
    `https://github.com/${repositoryInfo.owner}/${repositoryInfo.repo}` +
    `/actions/runs/${selfRunId}`
  await addCommentToPullRequest(
    repositoryInfo,
    pullRequestNumber,
    `[The Workflow run](${selfWorkflowRunUrl}) is cancelling this PR. ${reason}`
  )
}

/**
 * Cancels all runs in the specified group of runs.
 * @param repositoryInfo - information about the repository used
 * @param sortedRunItems - items sorted in descending order (descending order by created_at)
 * @param notifyPRCancel - whether to notify the PR when cancelling
 * @param selfRunId - what is the self run id
 * @param sourceGroupId - what is the source group id
 * @param reason - reason for cancelling
 */
async function cancelAllRunsInTheGroup(
  repositoryInfo: RepositoryInfo,
  sortedRunItems: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[],
  notifyPRCancel: boolean,
  selfRunId: number,
  sourceGroupId: string,
  reason: string
): Promise<number[]> {
  core.info(
    `\n###### Cancelling runs for ${sourceGroupId} starting from the most recent  ##########\n` +
      `\n     Number of runs to cancel: ${sortedRunItems.length}\n`
  )
  const cancelledRuns: number[] = []
  for (const runItem of sortedRunItems) {
    if (notifyPRCancel && runItem.event === 'pull_request') {
      const pullRequestNumber = await findPullRequestForRunItem(
        repositoryInfo,
        runItem
      )
      if (pullRequestNumber !== undefined) {
        core.info(
          `\nNotifying PR: ${pullRequestNumber} (runItem: ${runItem}) with: ${reason}\n`
        )
        await notifyPR(repositoryInfo, selfRunId, pullRequestNumber, reason)
      }
    }
    core.info(`\nCancelling run: ${runItem.id}.\n`)
    await cancelRun(repositoryInfo, runItem.id)
    cancelledRuns.push(runItem.id)
  }
  core.info(
    `\n######  Finished cancelling runs for ${sourceGroupId} ##########\n`
  )
  return cancelledRuns
}

/**
 * Cancels found runs per group. It takes all the found groups, sorts them
 * descending according to create date in each of the groups and cancels them in that order -
 * optionally skipping the first found run in each source group in case of duplicate cancelling.
 *
 * @param repositoryInfo - information about the repository used
 * @param mapOfWorkflowRunCandidatesCandidatesToCancel map of all workflow run candidates
 * @param cancelMode - cancel mode
 * @param cancelFutureDuplicates - whether to cancel future duplicates
 * @param notifyPRCancel - whether to notify PRs with comments
 * @param selfRunId - self run Id
 * @param reason - reason for cancelling
 */
async function cancelTheRunsPerGroup(
  repositoryInfo: RepositoryInfo,
  mapOfWorkflowRunCandidatesCandidatesToCancel: Map<
    string,
    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
  >,
  cancelMode: CancelMode,
  cancelFutureDuplicates: boolean,
  notifyPRCancel: boolean,
  selfRunId: number,
  reason: string
): Promise<number[]> {
  const cancelledRuns: number[] = []
  for (const [
    groupId,
    candidatesArray
  ] of mapOfWorkflowRunCandidatesCandidatesToCancel) {
    // Sort from most recent date - this way we always kill current one at the end (if we kill it at all)
    const sortedRunItems = candidatesArray.sort((runItem1, runItem2) =>
      runItem2.created_at.localeCompare(runItem1.created_at)
    )
    if (sortedRunItems.length > 0) {
      if (
        (cancelMode === CancelMode.DUPLICATES && cancelFutureDuplicates) ||
        cancelMode === CancelMode.ALL_DUPLICATES ||
        cancelMode === CancelMode.ALL_DUPLICATED_NAMED_JOBS
      ) {
        core.info(
          `\nSkipping the first run (${sortedRunItems[0].id}) of all the matching ` +
            `duplicates for '${groupId}'. This one we are going to leave in peace!\n`
        )
        sortedRunItems.shift()
      }
      if (sortedRunItems.length === 0) {
        core.info(`\nNo duplicates to cancel for ${groupId}!\n`)
        continue
      }
      cancelledRuns.push(
        ...(await cancelAllRunsInTheGroup(
          repositoryInfo,
          sortedRunItems,
          notifyPRCancel,
          selfRunId,
          groupId,
          reason
        ))
      )
    } else {
      core.info(
        `\n######  There are no runs to cancel for ${groupId} ##########\n`
      )
    }
  }
  return cancelledRuns
}

/**
 * Find and cancels runs based on the criteria chosen.
 * @param repositoryInfo - information about the repository used
 * @param selfRunId - number of own run id
 * @param triggeringRunInfo - information about the workflow that triggered the run
 * @param cancelMode - cancel mode used
 * @param cancelFutureDuplicates - whether to cancel future duplicates for duplicate cancelling
 * @param notifyPRCancel - whether to notify in PRs about cancelling
 * @param notifyPRMessageStart - whether to notify PRs when the action starts
 * @param jobNameRegexps - array of regular expressions to match hob names in case of named modes
 * @param skipEventTypes - array of event names that should be skipped
 * @param reason - reason for cancelling
 * @param selfPreservation - whether the run will cancel itself if requested
 * @return array of canceled workflow run ids
 */
async function findAndCancelRuns(
  repositoryInfo: RepositoryInfo,
  selfRunId: number,
  triggeringRunInfo: TriggeringRunInfo,
  cancelMode: CancelMode,
  cancelFutureDuplicates: boolean,
  notifyPRCancel: boolean,
  notifyPRMessageStart: string,
  jobNameRegexps: string[],
  skipEventTypes: string[],
  reason: string,
  selfPreservation: boolean
): Promise<number[]> {
  const statusValues = ['queued', 'in_progress']
  const workflowRuns = await getWorkflowRunsMatchingCriteria(
    repositoryInfo,
    statusValues,
    cancelMode,
    triggeringRunInfo
  )
  const mapOfWorkflowRunCandidatesCandidatesToCancel = await filterAndMapWorkflowRunsToGroups(
    repositoryInfo,
    triggeringRunInfo,
    cancelMode,
    cancelFutureDuplicates,
    jobNameRegexps,
    skipEventTypes,
    selfRunId,
    selfPreservation,
    workflowRuns
  )
  return await cancelTheRunsPerGroup(
    repositoryInfo,
    mapOfWorkflowRunCandidatesCandidatesToCancel,
    cancelMode,
    cancelFutureDuplicates,
    notifyPRCancel,
    selfRunId,
    reason
  )
}

/**
 * Returns environment variable that is required - throws error if it is not defined.
 * @param key key for the env variable
 * @return value of the env variable
 */
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
}

/**
 * Gets source run using  of the runId - if this is a workflow run, it returns the information about the source run
 * @param repositoryInfo - information about the repository used
 * @param runId - run id of the run to check
 * @return information about the triggering run
 */
async function getTriggeringRunInfo(
  repositoryInfo: RepositoryInfo,
  runId: number
): Promise<TriggeringRunInfo> {
  const reply = await repositoryInfo.octokit.actions.getWorkflowRun({
    owner: repositoryInfo.owner,
    repo: repositoryInfo.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') {
    pullRequest = await findPullRequest(
      repositoryInfo,
      sourceRun.head_repository.owner.login,
      sourceRun.head_branch,
      sourceRun.head_sha
    )
  }

  return {
    workflowId: retrieveWorkflowIdFromUrl(reply.data.workflow_url),
    runId,
    headRepo: reply.data.head_repository.full_name,
    headBranch: reply.data.head_branch,
    headSha: reply.data.head_sha,
    mergeCommitSha: pullRequest ? pullRequest.merge_commit_sha : null,
    pullRequest: pullRequest ? pullRequest : null,
    eventName: reply.data.event
  }
}

/**
 * Performs the actual cancelling.
 *
 * @param repositoryInfo - information about the repository used
 * @param selfRunId - number of own run id
 * @param triggeringRunInfo - information about the workflow that triggered the run
 * @param cancelMode - cancel mode used
 * @param notifyPRCancel - whether to notify in PRs about cancelling
 * @param notifyPRCancelMessage - message to send when cancelling the PR (overrides default message
 *        generated automatically)
 * @param notifyPRMessageStart - whether to notify PRs when the action starts
 * @param jobNameRegexps - array of regular expressions to match hob names in case of named modes
 * @param skipEventTypes - array of event names that should be skipped
 * @param cancelFutureDuplicates - whether to cancel future duplicates for duplicate cancelling
 * @param selfPreservation - whether the run will cancel itself if requested
 */
async function performCancelJob(
  repositoryInfo: RepositoryInfo,
  selfRunId: number,
  triggeringRunInfo: TriggeringRunInfo,
  cancelMode: CancelMode,
  notifyPRCancel: boolean,
  notifyPRCancelMessage: string,
  notifyPRMessageStart: string,
  jobNameRegexps: string[],
  skipEventTypes: string[],
  cancelFutureDuplicates: boolean,
  selfPreservation: boolean
): Promise<number[]> {
  core.info(
    '\n###################################################################################\n'
  )
  core.info(
    `All parameters: owner: ${repositoryInfo.owner}, repo: ${repositoryInfo.repo}, ` +
      `run id: ${triggeringRunInfo.runId}, ` +
      `head repo ${triggeringRunInfo.headRepo}, headBranch: ${triggeringRunInfo.headBranch}, ` +
      `sourceEventName: ${triggeringRunInfo.eventName}, ` +
      `cancelMode: ${cancelMode}, jobNames: ${jobNameRegexps}`
  )
  core.info(
    '\n###################################################################################\n'
  )
  let reason = ''
  if (cancelMode === CancelMode.SELF) {
    core.info(
      `# Cancelling source run: ${triggeringRunInfo.runId} ` +
        `for workflow ${triggeringRunInfo.workflowId}.`
    )
    reason = notifyPRCancelMessage
      ? notifyPRCancelMessage
      : `The job has been cancelled by another workflow.`
  } else if (cancelMode === CancelMode.FAILED_JOBS) {
    core.info(
      `# Cancel all runs for workflow ${triggeringRunInfo.workflowId} ` +
        `where job names matching ${jobNameRegexps} failed.`
    )
    reason = `It has some failed jobs matching ${jobNameRegexps}.`
  } else if (cancelMode === CancelMode.NAMED_JOBS) {
    core.info(
      `# Cancel all runs for workflow ${triggeringRunInfo.workflowId} ` +
        `have job names matching ${jobNameRegexps}.`
    )
    reason = `It has jobs matching ${jobNameRegexps}.`
  } else if (cancelMode === CancelMode.DUPLICATES) {
    core.info(
      `# Cancel duplicate runs for workflow ${triggeringRunInfo.workflowId} ` +
        `for same triggering branch as own run Id.`
    )
    reason = `It is an earlier duplicate of ${triggeringRunInfo.workflowId} run.`
  } else if (cancelMode === CancelMode.ALL_DUPLICATES) {
    core.info(
      `# Cancel all duplicates runs started for workflow ${triggeringRunInfo.workflowId}.`
    )
    reason = `It is an earlier duplicate of ${triggeringRunInfo.workflowId} run.`
  } else if (cancelMode === CancelMode.ALL_DUPLICATED_NAMED_JOBS) {
    core.info(
      `# Cancel all duplicate named jobs matching the patterns ${jobNameRegexps}.`
    )
    reason = `It is an earlier duplicate of ${triggeringRunInfo.workflowId} run.`
  } else {
    throw Error(`Wrong cancel mode ${cancelMode}! Please correct it.`)
  }
  core.info(
    '\n###################################################################################\n'
  )

  return await findAndCancelRuns(
    repositoryInfo,
    selfRunId,
    triggeringRunInfo,
    cancelMode,
    cancelFutureDuplicates,
    notifyPRCancel,
    notifyPRMessageStart,
    jobNameRegexps,
    skipEventTypes,
    reason,
    selfPreservation
  )
}

/**
 * Retrieves information about source workflow Id. Either from the current event or from the workflow
 * nme specified. If the file name is not specified, the workflow to act on is either set to self event
 * or in case of workflow_run event - to the workflow id that triggered the 'workflow_run' event.
 *
 * @param repositoryInfo - information about the repository used
 * @param workflowFileName - optional workflow file name
 * @param runId - run id of the workflow
 * @param selfRunId - self run id
 * @return workflow id that is associate with the workflow we are going to act on.
 */
async function retrieveWorkflowId(
  repositoryInfo: RepositoryInfo,
  workflowFileName: string | null,
  runId: number,
  selfRunId: number
): Promise<string | number> {
  let workflowId
  if (workflowFileName) {
    workflowId = workflowFileName
    core.info(
      `\nFinding runs for another workflow found by ${workflowFileName} name: ${workflowId}\n`
    )
  } else {
    workflowId = await getWorkflowId(repositoryInfo, runId)
    if (runId === selfRunId) {
      core.info(`\nFinding runs for my own workflow ${workflowId}\n`)
    } else {
      core.info(`\nFinding runs for source workflow ${workflowId}\n`)
    }
  }
  return workflowId
}
/**
 * Sets output but also prints the output value in the logs.
 *
 * @param name name of the output
 * @param value value of the output
 */
function verboseOutput(name: string, value: string): void {
  core.info(`Setting output: ${name}: ${value}`)
  core.setOutput(name, value)
}

/**
 * Performs sanity check of the parameters passed. Some of the parameter combinations do not work so they
 * are verified and in case od unexpected combination found, appropriate error is raised.
 *
 * @param eventName - name of the event to act on
 * @param runId - run id of the triggering event
 * @param selfRunId - our own run id
 * @param cancelMode - cancel mode used
 * @param cancelFutureDuplicates - whether future duplicate cancelling is enabled
 * @param jobNameRegexps - array of regular expression of job names
 */
function performSanityChecks(
  eventName: string,
  runId: number,
  selfRunId: number,
  cancelMode: CancelMode,
  cancelFutureDuplicates: boolean,
  jobNameRegexps: string[]
): void {
  if (
    eventName === 'workflow_run' &&
    runId === selfRunId &&
    cancelMode === CancelMode.DUPLICATES
  ) {
    throw Error(
      `You cannot run "workflow_run" in ${cancelMode} cancelMode without "sourceId" input.` +
        'It will likely not work as you intended - it will cancel runs which are not duplicates!' +
        'See the docs for details.'
    )
  }

  if (
    jobNameRegexps.length > 0 &&
    [
      CancelMode.DUPLICATES,
      CancelMode.SELF,
      CancelMode.ALL_DUPLICATES
    ].includes(cancelMode)
  ) {
    throw Error(
      `You cannot specify jobNamesRegexps on ${cancelMode} cancelMode.`
    )
  }

  if (
    jobNameRegexps.length === 0 &&
    [
      CancelMode.NAMED_JOBS,
      CancelMode.FAILED_JOBS,
      CancelMode.ALL_DUPLICATED_NAMED_JOBS
    ].includes(cancelMode)
  ) {
    throw Error(`You must specify jobNamesRegexps on ${cancelMode} cancelMode.`)
  }

  if (
    (cancelMode === CancelMode.ALL_DUPLICATES ||
      cancelMode === CancelMode.ALL_DUPLICATED_NAMED_JOBS) &&
    !cancelFutureDuplicates
  ) {
    throw Error(
      `The  ${cancelMode} cancelMode has to have cancelFutureDuplicates set to true.`
    )
  }
}

/**
 * Produces basic outputs for the action. This does not include cancelled workflow run id - those are
 * set after cancelling is done.
 *
 * @param triggeringRunInfo
 */
function produceBasicOutputs(triggeringRunInfo: TriggeringRunInfo): void {
  verboseOutput('sourceHeadRepo', triggeringRunInfo.headRepo)
  verboseOutput('sourceHeadBranch', triggeringRunInfo.headBranch)
  verboseOutput('sourceHeadSha', triggeringRunInfo.headSha)
  verboseOutput('sourceEvent', triggeringRunInfo.eventName)
  verboseOutput(
    'pullRequestNumber',
    triggeringRunInfo.pullRequest
      ? triggeringRunInfo.pullRequest.number.toString()
      : ''
  )
  verboseOutput(
    'mergeCommitSha',
    triggeringRunInfo.mergeCommitSha ? triggeringRunInfo.mergeCommitSha : ''
  )
  verboseOutput(
    'targetCommitSha',
    triggeringRunInfo.mergeCommitSha
      ? triggeringRunInfo.mergeCommitSha
      : triggeringRunInfo.headSha
  )
}

/**
 * Notifies the PR that the action has started.
 *
 * @param repositoryInfo information about the repository
 * @param triggeringRunInfo information about the triggering workflow
 * @param selfRunId self run id
 * @param notifyPRMessageStart whether to notify about the start of the action
 */
async function notifyActionStart(
  repositoryInfo: RepositoryInfo,
  triggeringRunInfo: TriggeringRunInfo,
  selfRunId: number,
  notifyPRMessageStart: string
): Promise<void> {
  if (notifyPRMessageStart && triggeringRunInfo.pullRequest) {
    const selfWorkflowRunUrl =
      `https://github.com/${repositoryInfo.owner}/${repositoryInfo.repo}` +
      `/actions/runs/${selfRunId}`
    await repositoryInfo.octokit.issues.createComment({
      owner: repositoryInfo.owner,
      repo: repositoryInfo.repo,
      // eslint-disable-next-line @typescript-eslint/camelcase
      issue_number: triggeringRunInfo.pullRequest.number,
      body: `${notifyPRMessageStart} [The workflow run](${selfWorkflowRunUrl})`
    })
  }
}

/**
 * Main run method that does everything :)
 */
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 cancelMode =
    (core.getInput('cancelMode') as CancelMode) || CancelMode.DUPLICATES
  const notifyPRCancel =
    (core.getInput('notifyPRCancel') || 'false').toLowerCase() === 'true'
  const notifyPRCancelMessage = core.getInput('notifyPRCancelMessage')
  const notifyPRMessageStart = core.getInput('notifyPRMessageStart')
  const sourceRunId = parseInt(core.getInput('sourceRunId')) || selfRunId
  const jobNameRegexpsString = core.getInput('jobNameRegexps')
  const selfPreservation =
    (core.getInput('selfPreservation') || 'true').toLowerCase() === 'true'
  const cancelFutureDuplicates =
    (core.getInput('cancelFutureDuplicates') || 'true').toLowerCase() === 'true'
  const jobNameRegexps = jobNameRegexpsString
    ? JSON.parse(jobNameRegexpsString)
    : []

  const skipEventTypesString = core.getInput('skipEventTypes')
  const skipEventTypes = skipEventTypesString
    ? JSON.parse(skipEventTypesString)
    : []
  const workflowFileName = core.getInput('workflowFileName')

  const [owner, repo] = repository.split('/')

  const repositoryInfo: RepositoryInfo = {
    octokit,
    owner,
    repo
  }
  core.info(
    `\nGetting workflow id for source run id: ${sourceRunId}, owner: ${owner}, repo: ${repo},` +
      ` skipEventTypes: ${skipEventTypes}\n`
  )
  const sourceWorkflowId = await retrieveWorkflowId(
    repositoryInfo,
    workflowFileName,
    sourceRunId,
    selfRunId
  )

  performSanityChecks(
    eventName,
    sourceRunId,
    selfRunId,
    cancelMode,
    cancelFutureDuplicates,
    jobNameRegexps
  )

  core.info(
    `Repository: ${repository}, Owner: ${owner}, Repo: ${repo}, ` +
      `Event name: ${eventName}, CancelMode: ${cancelMode}, ` +
      `sourceWorkflowId: ${sourceWorkflowId}, sourceRunId: ${sourceRunId}, selfRunId: ${selfRunId}, ` +
      `jobNames: ${jobNameRegexps}`
  )

  const triggeringRunInfo = await getTriggeringRunInfo(
    repositoryInfo,
    sourceRunId
  )
  produceBasicOutputs(triggeringRunInfo)

  await notifyActionStart(
    repositoryInfo,
    triggeringRunInfo,
    selfRunId,
    notifyPRMessageStart
  )

  const cancelledRuns = await performCancelJob(
    repositoryInfo,
    selfRunId,
    triggeringRunInfo,
    cancelMode,
    notifyPRCancel,
    notifyPRCancelMessage,
    notifyPRMessageStart,
    jobNameRegexps,
    skipEventTypes,
    cancelFutureDuplicates,
    selfPreservation
  )

  verboseOutput('cancelledRuns', JSON.stringify(cancelledRuns))
}

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