/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 */

'use strict';

const {danger, fail, message, warn} = require('danger');
const includes = require('lodash.includes');

const isFromPhabricator =
  danger.github.pr.body &&
  danger.github.pr.body.toLowerCase().includes('differential revision:');

// Provides advice if a summary section is missing, or body is too short
const includesSummary =
  danger.github.pr.body &&
  danger.github.pr.body.toLowerCase().includes('## summary');
if (!danger.github.pr.body || danger.github.pr.body.length < 50) {
  fail(':grey_question: This pull request needs a description.');
} else if (!includesSummary && !isFromPhabricator) {
  // PRs from Phabricator always includes the Summary by default.
  const title = ':clipboard: Missing Summary';
  const idea =
    'Can you add a Summary? ' +
    'To do so, add a "## Summary" section to your PR description. ' +
    'This is a good place to explain the motivation for making this change.';
  message(`${title} - <i>${idea}</i>`);
}

// Warns if there are changes to package.json, and tags the team.
const packageChanged = includes(danger.git.modified_files, 'package.json');
if (packageChanged) {
  const title = ':lock: package.json';
  const idea =
    'Changes were made to package.json. ' +
    'This will require a manual import by a Facebook employee.';
  warn(`${title} - <i>${idea}</i>`);
}

// Provides advice if a test plan is missing.
const includesTestPlan =
  danger.github.pr.body &&
  danger.github.pr.body.toLowerCase().includes('## test plan');
if (!includesTestPlan && !isFromPhabricator) {
  // PRs from Phabricator never exports the Test Plan so let's disable this check.
  const title = ':clipboard: Missing Test Plan';
  const idea =
    'Can you add a Test Plan? ' +
    'To do so, add a "## Test Plan" section to your PR description. ' +
    'A Test Plan lets us know how these changes were tested.';
  message(`${title} - <i>${idea}</i>`);
}

// Regex looks for given categories, types, a file/framework/component, and a message - broken into 4 capture groups
const changelogRegex =
  /\[\s?(ANDROID|GENERAL|IOS|JS|JAVASCRIPT|INTERNAL)\s?\]\s?\[\s?(ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY)\s?\]\s*?-?\s*?(.*)/gi;
const internalChangelogRegex = /\[\s?(INTERNAL)\s?\].*/gi;
const includesChangelog =
  danger.github.pr.body &&
  (danger.github.pr.body.toLowerCase().includes('## changelog') ||
    danger.github.pr.body.toLowerCase().includes('release notes') ||
    // PR exports from Phabricator have a `Changelog:` entry for the changelog.
    danger.github.pr.body.toLowerCase().includes('changelog:'));
const correctlyFormattedChangelog = changelogRegex.test(danger.github.pr.body);
const containsInternalChangelog = internalChangelogRegex.test(
  danger.github.pr.body,
);

// Provides advice if a changelog is missing
const changelogInstructions =
  'A changelog entry has the following format: `[CATEGORY] [TYPE] - Message`.\n\n<details>CATEGORY may be:\n\n- General\n- iOS\n- Android\n- JavaScript\n- Internal (for changes that do not need to be called out in the release notes)\n\nTYPE may be:\n\n- Added, for new features.\n- Changed, for changes in existing functionality.\n- Deprecated, for soon-to-be removed features.\n- Removed, for now removed features.\n- Fixed, for any bug fixes.\n- Security, in case of vulnerabilities.\n\nMESSAGE may answer "what and why" on a feature level.   Use this to briefly tell React Native users about notable changes.</details>';
if (!includesChangelog) {
  const title = ':clipboard: Missing Changelog';
  const idea =
    'Can you add a Changelog? ' +
    'To do so, add a "## Changelog" section to your PR description. ' +
    changelogInstructions;
  message(`${title} - <i>${idea}</i>`);
} else if (!correctlyFormattedChangelog && !containsInternalChangelog) {
  const title = ':clipboard: Verify Changelog Format';
  const idea = changelogInstructions;
  message(`${title} - <i>${idea}</i>`);
}

// Warns if the PR is opened against stable, as commits need to be cherry picked and tagged by a release maintainer.
// Fails if the PR is opened against anything other than `main` or `-stable`.
const isMergeRefMaster = danger.github.pr.base.ref === 'main';
const isMergeRefStable = danger.github.pr.base.ref.indexOf('-stable') !== -1;
if (!isMergeRefMaster && !isMergeRefStable) {
  const title = ':exclamation: Base Branch';
  const idea =
    'The base branch for this PR is something other than `main` or a `-stable` branch. [Are you sure you want to target something other than the `main` branch?](https://reactnative.dev/docs/contributing#pull-requests)';
  fail(`${title} - <i>${idea}</i>`);
}

@@ -4330,20 +4330,18 @@
 rgeRefMa
-ster
+in
  = dange
@@ -4472,12 +4472,10 @@
 efMa
-ster
+in
  && 
@@ -4775,16 +4775,16 @@
 ests)';%0A
-
   fail(%60
@@ -4794,28 +4794,378 @@
 itle%7D - %3Ci%3E$%7Bidea%7D%3C/i%3E%60);%0A%7D%0A
+%0A// If the PR is opened against stable should add %60Pick Request%60 label%0Aif (isMergeRefStable) %7B%0A  const %7Bowner, repo, number: issueNumber%7D = danger.github.thisPR;%0A%0A  danger.github.api.request(%0A    'POST /repos/%7Bowner%7D/%7Brepo%7D/issues/%7BissueNumber%7D/labels',%0A    %7B%0A      owner,%0A      repo,%0A      issueNumber,%0A      labels: %5B'Pick Request'%5D,%0A    %7D,%0A  );%0A%7D%0A

Auto-label pull requests opened against release branches (#32917)