// Copyright 2023 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:cocoon_server/big_query_pull_request_record.dart';
import 'package:cocoon_server/bigquery.dart';
import 'package:cocoon_server/logging.dart';
import 'package:github/github.dart' as github;
import 'package:retry/retry.dart';

import '../exception/retryable_exception.dart';
import '../model/auto_submit_query_result.dart';
import '../model/pull_request_data_types.dart';
import '../requests/graphql_queries.dart';
import 'config.dart';
import 'graphql_service.dart';

/// Class containing common methods to each of the pull request type validation
/// services.
class ValidationService {
  ValidationService(this.config, {RetryOptions? retryOptions})
    : retryOptions = retryOptions ?? Config.mergeRetryOptions;

  final Config config;
  final RetryOptions retryOptions;

  /// Fetch the most up to date info for the current pull request from github.
  Future<QueryResult> getNewestPullRequestInfo(
    Config config,
    github.PullRequest pullRequest,
  ) async {
    final slug = pullRequest.base!.repo!.slug();
    final prNumber = pullRequest.number;

    final graphQlService = await GraphQlService.forRepo(config, slug);

    final findPullRequestsWithReviewsQuery = FindPullRequestsWithReviewsQuery(
      repositoryOwner: slug.owner,
      repositoryName: slug.name,
      pullRequestNumber: prNumber!,
    );

    final data = await graphQlService.queryGraphQL(
      documentNode: findPullRequestsWithReviewsQuery.documentNode,
      variables: findPullRequestsWithReviewsQuery.variables,
    );

    return QueryResult.fromJson(data);
  }

  Future<github.PullRequest> getFullPullRequest(
    github.RepositorySlug slug,
    int pullRequestNumber,
  ) async {
    final githubService = await config.createGithubService(slug);
    return githubService.getPullRequest(slug, pullRequestNumber);
  }

  /// Merges the commit if the PullRequest passes all the validations.
  Future<MergeResult> submitPullRequest({
    required Config config,
    required github.PullRequest pullRequest,
  }) async {
    final slug = pullRequest.base!.repo!.slug();
    final number = pullRequest.number!;

    // Pass an explicit commit message from the PR title otherwise the GitHub API will use the first commit message.
    const revertPattern = 'Revert "Revert';
    var messagePrefix = '';

    if (pullRequest.title!.contains(revertPattern)) {
      // Cleanup auto-generated revert messages.
      messagePrefix = '''
${pullRequest.title!.replaceFirst('Revert "Revert', 'Reland')}

''';
    }

    final prBody = _sanitizePrBody(pullRequest.body ?? '');
    final commitMessage = '$messagePrefix$prBody';

    if (pullRequest.isMergeQueueEnabled) {
      return _enqueuePullRequest(slug, pullRequest);
    } else {
      return _mergePullRequest(number, commitMessage, slug);
    }
  }

  Future<MergeResult> _enqueuePullRequest(
    github.RepositorySlug slug,
    github.PullRequest restPullRequest,
  ) async {
    final graphQlService = await GraphQlService.forRepo(config, slug);
    final isEmergencyPullRequest =
        restPullRequest.labels
            ?.where((label) => label.name == Config.kEmergencyLabel)
            .isNotEmpty ??
        false;

    try {
      await retryOptions.retry(() async {
        await graphQlService.enqueuePullRequest(
          slug,
          restPullRequest.number!,
          isEmergencyPullRequest,
        );
      }, retryIf: (Exception e) => e is RetryableException);
    } catch (e, s) {
      final message =
          'Failed to enqueue ${slug.fullName}/${restPullRequest.number} with $e';
      log.error(message, e, s);
      return (result: false, message: message, method: SubmitMethod.enqueue);
    }

    return (
      result: true,
      message: restPullRequest.title!,
      method: SubmitMethod.enqueue,
    );
  }

  Future<MergeResult> _mergePullRequest(
    int number,
    String commitMessage,
    github.RepositorySlug slug,
  ) async {
    try {
      github.PullRequestMerge? result;

      await retryOptions.retry(() async {
        result = await _processMergeInternal(
          config: config,
          commitMessage: commitMessage,
          slug: slug,
          number: number,
          mergeMethod: github.MergeMethod.squash,
        );
      }, retryIf: (Exception e) => e is RetryableException);

      final merged = result?.merged ?? false;
      if (result != null && !merged) {
        final message =
            'Failed to merge ${slug.fullName}/$number with ${result?.message}';
        log.error(message);
        return (result: false, message: message, method: SubmitMethod.merge);
      }
    } catch (e, s) {
      // Catch graphql client init exceptions.
      final message = 'Failed to merge ${slug.fullName}/$number with $e';
      log.error(message, e, s);
      return (result: false, message: message, method: SubmitMethod.merge);
    }

    return (result: true, message: commitMessage, method: SubmitMethod.merge);
  }

  /// Insert a merged pull request record into the database.
  Future<void> insertPullRequestRecord({
    required Config config,
    required github.PullRequest pullRequest,
    required PullRequestChangeType pullRequestType,
  }) async {
    final slug = pullRequest.base!.repo!.slug();
    final gitHubService = await config.createGithubService(slug);
    // We need the updated time fields for the merged request from github.
    final currentPullRequest = await gitHubService.getPullRequest(
      slug,
      pullRequest.number!,
    );

    // add a record for the pull request into our metrics tracking
    final pullRequestRecord = PullRequestRecord(
      organization: currentPullRequest.base!.repo!.slug().owner,
      repository: currentPullRequest.base!.repo!.slug().name,
      author: currentPullRequest.user!.login,
      prNumber: pullRequest.number!,
      prCommit: currentPullRequest.head!.sha,
      prRequestType: pullRequestType.name,
      prCreatedTimestamp: currentPullRequest.createdAt!,
      prLandedTimestamp: currentPullRequest.closedAt!,
    );

    try {
      final bigqueryService = await config.createBigQueryService();
      await bigqueryService.insertPullRequestRecord(
        projectId: Config.flutterGcpProjectId,
        pullRequestRecord: pullRequestRecord,
      );
    } on BigQueryException catch (e) {
      log.error(
        'Failed to insert pull request record into BigQuery for pull request '
        '${slug.fullName}/${pullRequest.number} due to',
        e,
      );
    }
  }
}

/// Method used to submit the PR for merging.
enum SubmitMethod {
  /// The PR is enqueued into the merge queue, and the merge queue is responsible
  /// for merging the PR.
  enqueue('enqueued'),

  /// The PR is immediately merged into the target branch.
  ///
  /// This is the old method for merging PRs, used by repos where merge queues
  /// are not (yet?) enabled.
  merge('merged');

  const SubmitMethod(this.pastTenseLabel);

  /// The verb in past tense used to describe what happened to a PR when this
  /// submit method was used, e.g. "merged".
  final String pastTenseLabel;
}

/// Small wrapper class to allow us to capture and create a comment in the PR with
/// the issue that caused the merge failure.
typedef MergeResult = ({bool result, String message, SubmitMethod method});

/// Function signature that will be executed with retries.
typedef RetryHandler = void Function();

/// Internal wrapper for the logic of merging a pull request into github.
Future<github.PullRequestMerge> _processMergeInternal({
  required Config config,
  required github.RepositorySlug slug,
  required int number,
  required github.MergeMethod mergeMethod,
  String? commitMessage,
  String? requestSha,
}) async {
  // This is retryable so to guard against token expiration we get a fresh
  // client each time.
  log.info('Attempting to merge ${slug.fullName}/$number.');
  final gitHubService = await config.createGithubService(slug);
  final pullRequestMerge = await gitHubService.mergePullRequest(
    slug,
    number,
    commitMessage: commitMessage,
    mergeMethod: mergeMethod,
    requestSha: requestSha,
  );

  if (pullRequestMerge.merged != true) {
    throw RetryableException(
      'Pull request ${slug.fullName}/$number could not be merged: ${pullRequestMerge.message}',
    );
  }

  return pullRequestMerge;
}

final RegExp _kCheckboxPattern = RegExp(r'^\s*-[ ]?\[( |x|X)\]');
final RegExp _kCommentPattern = RegExp(r'<!--.*-->');
final RegExp _kMarkdownLinkRefDef = RegExp(r'^\[[\w\/ -]+\]:');
final RegExp _kPreLaunchHeader = RegExp(r'## Pre-launch Checklist');
final RegExp _kDiscordPattern = RegExp(r'#hackers-new');

String _sanitizePrBody(String rawPrBody) {
  final buffer = StringBuffer();
  var lastLineWasEmpty = false;
  for (final line in rawPrBody.split('\n')) {
    if (_kCheckboxPattern.hasMatch(line) ||
        _kCommentPattern.hasMatch(line) ||
        _kMarkdownLinkRefDef.hasMatch(line) ||
        _kPreLaunchHeader.hasMatch(line) ||
        _kDiscordPattern.hasMatch(line)) {
      continue;
    }
    if (line.trim().isEmpty) {
      // we don't need to include multiple empty lines
      if (lastLineWasEmpty) {
        continue;
      }
      lastLineWasEmpty = true;
    } else {
      lastLineWasEmpty = false;
    }
    buffer.writeln(line);
  }
  return buffer.toString().trim();
}

/// Repos that use MQ-based workflow.
///
/// This variable is read-write to allow tests to choose which repos they want
/// to test in which mode.
List<String> mqEnabledRepos = const <String>['flutter/flutter'];

/// Convenience extension so one can just do `pullRequest.isMergeQueueEnabled`.
extension PullRequestExtension on github.PullRequest {
  /// Whether this pull requests must be merged via a merge queue.
  bool get isMergeQueueEnabled {
    final baseRef = base!.ref;
    if (baseRef != 'main' && baseRef != 'master') {
      // MQ is only enabled for main and master branches.
      return false;
    }

    final slug = base!.repo!.slug();
    return mqEnabledRepos.contains(slug.fullName);
  }

  /// Extracts label names from the `IssueLabel` list [labels].
  List<String> get labelNames {
    final labels = this.labels;
    if (labels == null) {
      return const <String>[];
    }

    return labels.map<String>((label) => label.name).toList();
  }
}
