/*
 * 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.
 */

import { Label } from "./githubUtils";
const { NO_MATCHING_LABEL } = require("./constants");

export interface AssignReviewerOptions {
  labels?: (string | Label)[];
  notices?: string[];
}

// Custom notices for specific labels
const LABEL_NOTICES: Record<string, string> = {
  core: 'This pull request likely touches a core component ("core" label). Please review with scrutiny.',
};

function formatNotices(
  labelToReviewerMapping: any,
  options?: AssignReviewerOptions
): string {
  const notices = [...(options?.notices || [])];
  const labels = [
    ...(options?.labels || []),
    ...Object.keys(labelToReviewerMapping),
  ];
  for (const label of labels) {
    const name = (typeof label === "string" ? label : label.name).toLowerCase();
    if (LABEL_NOTICES[name] && !notices.includes(LABEL_NOTICES[name])) {
      notices.push(LABEL_NOTICES[name]);
    }
  }
  return notices.length ? `\n${notices.join("\n\n")}\n` : "";
}

export function allChecksPassed(reviewersToNotify: string[]): string {
  return `All checks have passed: @${reviewersToNotify.join(" ")}`;
}

export function assignCommitter(committer: string): string {
  return `R: @${committer} for final approval`;
}

export function assignReviewer(
  labelToReviewerMapping: any,
  options?: AssignReviewerOptions
): string {
  let commentString = "Assigning reviewers:\n\n";

  for (let label in labelToReviewerMapping) {
    let reviewer = labelToReviewerMapping[label];
    if (label === NO_MATCHING_LABEL) {
      commentString += `R: @${reviewer} added as fallback since no labels match configuration\n`;
    } else {
      commentString += `R: @${reviewer} for label ${label}.\n`;
    }
  }

  commentString += formatNotices(labelToReviewerMapping, options);

  commentString += `

Note: If you would like to opt out of this review, comment \`assign to next reviewer\`.

Available commands:
- \`stop reviewer notifications\` - opt out of the automated review tooling
- \`remind me after tests pass\` - tag the comment author after tests pass
- \`waiting on author\` - shift the attention set back to the author (any comment or push by the author will return the attention set to the reviewers)

The PR bot will only process comments in the main thread (not review comments).`;
  return commentString;
}

export function failingChecksCantAssign(): string {
  return "Checks are failing. Will not request review until checks are succeeding. If you'd like to override that behavior, comment `assign set of reviewers`";
}

export function someChecksFailing(reviewersToNotify: string[]): string {
  return `Some checks have failed: @${reviewersToNotify.join(" ")}`;
}

export function stopNotifications(reason: string): string {
  return `Stopping reviewer notifications for this pull request: ${reason}. If you'd like to restart, comment \`assign set of reviewers\``;
}

export function remindReviewerAfterTestsPass(requester: string): string {
  return `Ok - I'll remind @${requester} after tests pass`;
}

export function reviewersAlreadyAssigned(reviewers: string[]): string {
  return `Reviewers are already assigned to this PR: ${reviewers
    .map((reviewer) => "@" + reviewer)
    .join(" ")}`;
}

export function noLegalReviewers(): string {
  return "No reviewers could be found from any of the labels on the PR or in the fallback reviewers list. Check the config file to make sure reviewers are configured";
}

export function updateReviewerConfig(
  reviewersAddedForLabels: { [reviewer: string]: string[] },
  reviewersRemovedForLabels: { [reviewer: string]: string[] }
) {
  let commentString = `Adds and/or removes reviewers based on activity in the repo.
If you have been added and would prefer not to be, you can avoid getting repeatedly suggested by adding yourself to that label's exclusionList.
`;

  if (Object.keys(reviewersAddedForLabels).length > 0) {
    commentString += `
The following users have been added as reviewers to the configuration.
If you choose to accept being added, you will be added to the rotation of users who are automatically added to pull requests for an initial review.
A committer will still have to approve after your review (if you are not a committer), but you will be the initial touchpoint for PRs to which you are assigned.
`;
    for (const reviewer of Object.keys(reviewersAddedForLabels)) {
      commentString += `${reviewer} added for label(s): ${reviewersAddedForLabels[
        reviewer
      ].join(",")}\n`;
    }
  }

  if (Object.keys(reviewersRemovedForLabels).length > 0) {
    commentString += `
The following users have been removed as reviewers from the configuration.
Users are removed if they haven't reviewed or completed a PR in the last 3 months.
`;
    for (const reviewer of Object.keys(reviewersRemovedForLabels)) {
      commentString += `@${reviewer} removed for label(s): ${reviewersRemovedForLabels[
        reviewer
      ].join(",")}\n`;
    }
  }

  return commentString;
}

export function assignNewReviewer(
  labelToReviewerMapping: {
    [label: string]: string;
  },
  options?: AssignReviewerOptions
): string {
  let commentString =
    "Assigning new set of reviewers because Pr has gone too long without review. If you would like to opt out of this review, comment `assign to next reviewer`:\n\n";

  for (const label in labelToReviewerMapping) {
    const reviewer = labelToReviewerMapping[label];
    if (label === NO_MATCHING_LABEL) {
      commentString += `R: @${reviewer} added as fallback since no labels match configuration\n`;
    } else {
      commentString += `R: @${reviewer} for label ${label}.\n`;
    }
  }

  commentString += formatNotices(labelToReviewerMapping, options);

  commentString += `
Available commands:
- \`stop reviewer notifications\` - opt out of the automated review tooling
- \`remind me after tests pass\` - tag the comment author after tests pass
- \`waiting on author\` - shift the attention set back to the author (any comment or push by the author will return the attention set to the reviewers)`;
  return commentString;
}

export function slowReview(reviewers: string[]): string {
  let commentString = `Reminder, please take a look at this pr: `;
  for (const reviewer of reviewers) {
    commentString += `@${reviewer} `;
  }

  return commentString;
}
