/*
 * 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("./shared/githubUtils");
const commentStrings = require("./shared/commentStrings");
const { ReviewerConfig } = require("./shared/reviewerConfig");
const { PersistentState } = require("./shared/persistentState");
const {
  BOT_NAME,
  REPO_OWNER,
  REPO,
  PATH_TO_CONFIG_FILE,
  SLOW_REVIEW_LABEL,
} = require("./shared/constants");
const ONE_DAY_MS = 24 * 60 * 60 * 1000;

function hasLabel(pull: any, labelName: string): boolean {
  return pull.labels.some(
    (label) => label.name.toLowerCase() === labelName.toLowerCase()
  );
}

function getTwoWeekdaysAgo(): Date {
  const twoWeekDaysAgo = new Date(Date.now() - 2 * ONE_DAY_MS);
  const currentDay = new Date(Date.now()).getDay();
  // If Saturday, sunday, monday, or tuesday, add extra time to account for weekend.
  if (currentDay === 6) {
    twoWeekDaysAgo.setDate(twoWeekDaysAgo.getDate() - 1);
  } else if (currentDay <= 2) {
    twoWeekDaysAgo.setDate(twoWeekDaysAgo.getDate() - 2);
  }

  return twoWeekDaysAgo;
}

async function isSlowReview(pull: any): Promise<boolean> {
  if (!hasLabel(pull, "Next Action: Reviewers")) {
    return false;
  }
  const lastModified = new Date(pull.updated_at);
  const sevenDaysAgo = new Date(Date.now() - 7 * ONE_DAY_MS);
  if (lastModified.getTime() < sevenDaysAgo.getTime()) {
    return true;
  }

  // If it has no comments from a non-bot/author in the last 2 weekdays, return true
  const twoWeekDaysAgo = getTwoWeekdaysAgo();
  if (lastModified.getTime() >= twoWeekDaysAgo.getTime()) {
    return false;
  }
  const pullAuthor = pull.user.login;
  const githubClient = github.getGitHubClient();
  const comments = (
    await githubClient.rest.issues.listComments({
      owner: REPO_OWNER,
      repo: REPO,
      issue_number: pull.number,
    })
  ).data;
  for (const comment of comments) {
    if (comment.user.login !== pullAuthor && comment.user.login !== BOT_NAME) {
      return false;
    }
  }

  const reviewComments = (
    await githubClient.rest.pulls.listReviewComments({
      owner: REPO_OWNER,
      repo: REPO,
      pull_number: pull.number,
    })
  ).data;
  for (const comment of reviewComments) {
    if (comment.user.login !== pullAuthor && comment.user.login !== BOT_NAME) {
      return false;
    }
  }

  return true;
}

async function assignToNewReviewers(
  pull: any,
  reviewerConfig: typeof ReviewerConfig,
  stateClient: typeof PersistentState
) {
  let prState = await stateClient.getPrState(pull.number);
  let reviewerStateToUpdate = {};
  const labelObjects = pull.labels;
  let reviewersToExclude: string[] = Object.values(prState.reviewersAssignedForLabels) as string[];
  if (pull.requested_reviewers) {
    reviewersToExclude = reviewersToExclude.concat(pull.requested_reviewers.map((r: any) => r.login));
  }
  reviewersToExclude.push(pull.user.login);
  const reviewersForLabels: { [key: string]: string[] } =
    reviewerConfig.getReviewersForLabels(labelObjects, reviewersToExclude);
  const fallbackReviewers =
    reviewerConfig.getFallbackReviewers();
  for (const labelObject of labelObjects) {
    const label = labelObject.name;
    let availableReviewers = reviewersForLabels[label];
    if (availableReviewers && availableReviewers.length > 0) {
      let reviewersState = await stateClient.getReviewersForLabelState(label);
      let chosenReviewer = await reviewersState.assignNextCommitter(
        availableReviewers,
        fallbackReviewers
      );
      reviewerStateToUpdate[label] = reviewersState;
      prState.reviewersAssignedForLabels[label] = chosenReviewer;
    }
  }

  console.log(`Assigning new reviewers for pr ${pull.number}`);
  await github.addPrComment(
    pull.number,
    commentStrings.assignNewReviewer(prState.reviewersAssignedForLabels)
  );

  await stateClient.writePrState(pull.number, prState);
  let labelsToUpdate = Object.keys(reviewerStateToUpdate);
  for (const label of labelsToUpdate) {
    await stateClient.writeReviewersForLabelState(
      label,
      reviewerStateToUpdate[label]
    );
  }
}

// Flag any prs that have been awaiting reviewer action at least 7 days,
// or have been awaiting initial review for at least 2 days and ping the reviewers
// If there's still no action after 2 more days, assign a new set of committers.
async function processPull(
  pull: any,
  reviewerConfig: typeof ReviewerConfig,
  stateClient: typeof PersistentState
) {
  const prState = await stateClient.getPrState(pull.number);
  if (prState.stopReviewerNotifications) {
    console.log(`Skipping PR ${pull.number} - notifications silenced`);
    return;
  }
  if (hasLabel(pull, SLOW_REVIEW_LABEL)) {
    const lastModified = new Date(pull.updated_at);
    const twoWeekDaysAgo = getTwoWeekdaysAgo();
    console.log(
      `PR ${pull.number} has the slow review label. Last modified ${lastModified}`
    );
    if (lastModified.getTime() < twoWeekDaysAgo.getTime()) {
      console.log(
        `PR ${pull.number} still awaiting action - assigning new reviewers`
      );
      await assignToNewReviewers(pull, reviewerConfig, stateClient);
      await github.getGitHubClient().rest.issues.removeLabel({
        owner: REPO_OWNER,
        repo: REPO,
        issue_number: pull.number,
        name: SLOW_REVIEW_LABEL,
      });
      await github.getGitHubClient().rest.issues.addLabels({
        owner: REPO_OWNER,
        repo: REPO,
        issue_number: pull.number,
        labels: ["reassigned-reviewers"],
      });
    }

    return;
  }

  if (await isSlowReview(pull)) {
    const client = github.getGitHubClient();
    let reviewersToPing = Object.values(prState.reviewersAssignedForLabels || {});
    if (pull.requested_reviewers) {
      reviewersToPing = reviewersToPing.concat(pull.requested_reviewers.map((r: any) => r.login));
    }
    reviewersToPing = [...new Set(reviewersToPing as string[])];

    if (reviewersToPing.length > 0) {
      console.log(
        `Flagging pr ${pull.number} as slow. Tagging reviewers ${reviewersToPing}`
      );
      await github.addPrComment(
        pull.number,
        commentStrings.slowReview(reviewersToPing)
      );
      await client.rest.issues.addLabels({
        owner: REPO_OWNER,
        repo: REPO,
        issue_number: pull.number,
        labels: [SLOW_REVIEW_LABEL],
      });
    }
  }
}

async function processOldPrs() {
  const githubClient = github.getGitHubClient();
  let reviewerConfig = new ReviewerConfig(PATH_TO_CONFIG_FILE);
  let stateClient = new PersistentState();

  let openPulls = await githubClient.paginate(
    "GET /repos/{owner}/{repo}/pulls",
    {
      owner: REPO_OWNER,
      repo: REPO,
    }
  );

  for (const pull of openPulls) {
    await processPull(pull, reviewerConfig, stateClient);
  }
}

processOldPrs();

export {};
