/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const github = require("@actions/github");
const commentStrings = require("./shared/commentStrings");
const { processCommand } = require("./shared/userCommand");
const {
  addPrComment,
  getGitHubClient,
  nextActionAuthor,
  nextActionReviewers,
  getPullAuthorFromPayload,
  getPullNumberFromPayload,
} = require("./shared/githubUtils");
const { processPull } = require("./processNewPrs");
const { PersistentState } = require("./shared/persistentState");
const { ReviewerConfig } = require("./shared/reviewerConfig");
const {
  BOT_NAME,
  PATH_TO_CONFIG_FILE,
  REPO_OWNER,
  REPO,
  SLOW_REVIEW_LABEL,
  REVIEWERS_ACTION,
  AUTHOR_ACTION,
} = require("./shared/constants");

// Removes the slow label if the pr has been reviewed and returns an updated payload.
async function removeSlowReviewLabel(payload: any) {
  let labels = payload.issue?.labels || payload.pull_request?.labels;
  if (labels.some((label) => label.name.toLowerCase() == SLOW_REVIEW_LABEL)) {
    const pullNumber = payload.issue?.number || payload.pull_request?.number;
    labels = (
      await getGitHubClient().rest.issues.removeLabel({
        owner: REPO_OWNER,
        repo: REPO,
        issue_number: pullNumber,
        name: "slow-review",
      })
    ).data;
    if (payload.issues) {
      payload.issues.labels = labels;
    }
    if (payload.pull_request) {
      payload.pull_request.labels = labels;
    }
  }
}

async function areReviewersAssigned(
  pull: any,
  stateClient: typeof PersistentState
): Promise<boolean> {
  const prState = await stateClient.getPrState(pull.number);
  if (Object.values(prState.reviewersAssignedForLabels).length > 0) {
    return true;
  }
  if (pull.requested_reviewers && pull.requested_reviewers.length > 0) {
    return true;
  }
  return false;
}

async function processPrComment(
  payload: any,
  pull: any,
  stateClient: typeof PersistentState,
  reviewerConfig: typeof ReviewerConfig
) {
  const commentContents = payload.comment.body;
  const commentAuthor = payload.sender.login;
  const pullAuthor = getPullAuthorFromPayload(payload);
  console.log(commentContents);
  const processedCommand = await processCommand(
    payload,
    commentAuthor,
    commentContents,
    stateClient,
    reviewerConfig
  );

  // Check to see if notifications have been stopped before processing further.
  // Notifications can be stopped by an "R: reviewer" comment,
  // and then restarted by adding "assign set of reviewers" comment.
  if (
    (await stateClient.getPrState(getPullNumberFromPayload(payload)))
      .stopReviewerNotifications
  ) {
    console.log("Notifications have been paused for this pull - skipping");
    return;
  }

  // If there's been a comment by a non-author, we can remove the slow review label
  if (commentAuthor !== pullAuthor && commentAuthor !== BOT_NAME) {
    await removeSlowReviewLabel(payload);
  }
  if (processedCommand) {
    // If we've processed a command, don't worry about trying to change the attention set.
    // This is not a meaningful push or comment from the author.
    console.log("Processed command");
    return;
  }

  // If comment was from the author, we should shift attention back to the reviewers.
  console.log(
    "No command to be processed, checking if we should shift attention to reviewers"
  );
  if (pullAuthor === commentAuthor) {
    await setNextActionReviewers(payload, pull, stateClient);
  } else {
    console.log(
      `Comment was from ${commentAuthor}, not author: ${pullAuthor}. No action to take.`
    );
  }
}

/*
 * On pr push, ready_for_review, or author comment, we should put the attention set back on the reviewers
 */
async function setNextActionReviewers(
  payload: any,
  pull: any,
  stateClient: typeof PersistentState
) {
  if (pull.draft) {
    console.log("PR is a draft, not shifting attention to reviewers");
    return;
  }
  if (!(await areReviewersAssigned(pull, stateClient))) {
    console.log("No reviewers assigned, dont need to manipulate attention set");
    return;
  }
  const existingLabels =
    pull.labels || payload.issue?.labels || payload.pull_request?.labels;
  await nextActionReviewers(pull.number, existingLabels);
  let prState = await stateClient.getPrState(pull.number);
  prState.nextAction = REVIEWERS_ACTION;
  await stateClient.writePrState(pull.number, prState);
}

/*
 * When a PR is marked as draft, set the next action state to Author
 */
async function setNextActionAuthor(
  payload: any,
  pull: any,
  stateClient: typeof PersistentState
) {
  const existingLabels =
    pull.labels || payload.issue?.labels || payload.pull_request?.labels;
  await nextActionAuthor(pull.number, existingLabels);
  let prState = await stateClient.getPrState(pull.number);
  prState.nextAction = AUTHOR_ACTION;
  await stateClient.writePrState(pull.number, prState);
}

async function processPrUpdate() {
  const reviewerConfig = new ReviewerConfig(PATH_TO_CONFIG_FILE);
  const context = github.context;
  console.log("Event context:");
  console.log(context);
  const payload = context.payload;

  if (!payload.issue?.pull_request && !payload.pull_request) {
    console.log("Issue, not pull request - returning");
    return;
  }
  const pullNumber = getPullNumberFromPayload(payload);

  const stateClient = new PersistentState();

  switch (github.context.eventName) {
    case "issue_comment": {
      console.log("Processing comment event");
      if (payload.action !== "created") {
        console.log("Comment wasnt just created, skipping");
        return;
      }
      const pull = (
        await getGitHubClient().rest.pulls.get({
          owner: REPO_OWNER,
          repo: REPO,
          pull_number: pullNumber,
        })
      ).data;
      await processPrComment(payload, pull, stateClient, reviewerConfig);
      break;
    }
    case "pull_request_target": {
      if (
        (await stateClient.getPrState(pullNumber)).stopReviewerNotifications
      ) {
        console.log("Notifications have been paused for this pull - skipping");
        return;
      }
      const pull = (
        await getGitHubClient().rest.pulls.get({
          owner: REPO_OWNER,
          repo: REPO,
          pull_number: pullNumber,
        })
      ).data;
      if (payload.action === "synchronize") {
        console.log("Processing synchronize action");
        await setNextActionReviewers(payload, pull, stateClient);
      } else if (payload.action === "review_requested") {
        console.log("Processing review_requested action");
        await setNextActionReviewers(payload, pull, stateClient);
      } else if (payload.action === "converted_to_draft") {
        console.log("Processing converted_to_draft action");
        await setNextActionAuthor(payload, pull, stateClient);
      } else if (payload.action === "ready_for_review") {
        console.log("Processing ready_for_review action");
        // If reviewers are already assigned, shift attention back to them.
        // Otherwise, try to assign initial reviewers immediately (e.g. when a draft
        // PR with passing checks is marked ready for review) instead of waiting for cron.
        if (await areReviewersAssigned(pull, stateClient)) {
          await setNextActionReviewers(payload, pull, stateClient);
        } else {
          await processPull(pull, reviewerConfig, stateClient);
        }
      }
      // TODO(damccorm) - it would be good to eventually handle the following events here, even though they're not part of the normal workflow
      // review requested, assigned, label added, label removed
      break;
    }
    default:
      console.log("Not a PR comment or push, doing nothing");
  }
}

processPrUpdate();

export {};
