// Copyright 2020 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:github/github.dart' as github;
import 'package:github/hooks.dart';

import '../foundation/github_checks_util.dart';
import '../model/luci/buildbucket.dart';
import '../model/luci/push_message.dart' as push_message;
import 'config.dart';
import 'github_service.dart';
import 'logging.dart';
import 'luci_build_service.dart';
import 'scheduler.dart';

const String kGithubSummary = '''
**[Understanding a LUCI build failure](https://github.com/flutter/flutter/wiki/Understanding-a-LUCI-build-failure)**

''';

/// Controls triggering builds and updating their status in the Github UI.
class GithubChecksService {
  GithubChecksService(this.config, {GithubChecksUtil? githubChecksUtil})
      : githubChecksUtil = githubChecksUtil ?? const GithubChecksUtil();

  Config config;
  GithubChecksUtil githubChecksUtil;

  static Set<github.CheckRunConclusion> failedStatesSet = <github.CheckRunConclusion>{
    github.CheckRunConclusion.cancelled,
    github.CheckRunConclusion.failure,
  };

  /// Takes a [CheckSuiteEvent] and trigger all the relevant builds if this is a
  /// new commit or only failed builds if the event was generated by a click on
  /// the re-run all button in the Github UI.
  /// Relevant API docs:
  ///   https://docs.github.com/en/rest/reference/checks#create-a-check-suite
  ///   https://docs.github.com/en/rest/reference/checks#rerequest-a-check-suite
  Future<void> handleCheckSuite(
    github.PullRequest pullRequest,
    CheckSuiteEvent checkSuiteEvent,
    Scheduler scheduler,
  ) async {
    switch (checkSuiteEvent.action) {
      case 'requested':
        // Trigger all try builders.
        log.info('Check suite request for pull request ${pullRequest.number}, ${pullRequest.title}');
        await scheduler.triggerPresubmitTargets(
          pullRequest: pullRequest,
        );
        break;
      case 'rerequested':
        log.info('Check suite re-request for pull request ${pullRequest.number}, ${pullRequest.title}');
        pullRequest.head = github.PullRequestHead(sha: checkSuiteEvent.checkSuite?.headSha);
        return await scheduler.retryPresubmitTargets(
          pullRequest: pullRequest,
          checkSuiteEvent: checkSuiteEvent,
        );
    }
  }

  /// Updates the Github build status using a [BuildPushMessage] sent by LUCI in
  /// a pub/sub notification.
  /// Relevant APIs:
  ///   https://docs.github.com/en/rest/reference/checks#update-a-check-run
  Future<bool> updateCheckStatus(
    push_message.BuildPushMessage buildPushMessage,
    LuciBuildService luciBuildService,
    github.RepositorySlug slug,
  ) async {
    final push_message.Build? build = buildPushMessage.build;
    if (buildPushMessage.userData.isEmpty) {
      return false;
    }

    if (!buildPushMessage.userData.containsKey('check_run_id') ||
        !buildPushMessage.userData.containsKey('repo_owner') ||
        !buildPushMessage.userData.containsKey('repo_name')) {
      log.severe(
        'UserData did not contain check_run_id,'
        'repo_owner, or repo_name: ${buildPushMessage.userData}',
      );
      return false;
    }
    final github.CheckRun checkRun = await githubChecksUtil.getCheckRun(
      config,
      slug,
      buildPushMessage.userData['check_run_id'] as int?,
    );
    final github.CheckRunStatus status = statusForResult(build!.status);
    final github.CheckRunConclusion? conclusion =
        (buildPushMessage.build!.result != null) ? conclusionForResult(buildPushMessage.build!.result) : null;
    // Do not override url for completed status.
    final String? url = status == github.CheckRunStatus.completed ? checkRun.detailsUrl : buildPushMessage.build!.url;
    github.CheckRunOutput? output;
    // If status has completed with failure then provide more details.
    if (status == github.CheckRunStatus.completed && failedStatesSet.contains(conclusion)) {
      final Build build =
          await luciBuildService.getBuildById(buildPushMessage.build!.id, fields: 'id,builder,summaryMarkdown');
      output = github.CheckRunOutput(title: checkRun.name!, summary: getGithubSummary(build.summaryMarkdown));
    }
    log.fine('Updating check run with output: [$output]');
    await githubChecksUtil.updateCheckRun(
      config,
      slug,
      checkRun,
      status: status,
      conclusion: conclusion,
      detailsUrl: url,
      output: output,
    );
    return true;
  }

  /// Appends triage wiki page to `summaryMarkdown` from LUCI build so that people can easily
  /// reference from github check run page.
  String getGithubSummary(String? summary) {
    if (summary == null) {
      return '${kGithubSummary}Empty summaryMarkdown';
    }
    // This is an imposed GitHub limit
    const int checkSummaryLimit = 65535;
    // This is to give buffer room incase GitHub lowers the amount.
    const int checkSummaryBufferLimit = checkSummaryLimit - 10000 - kGithubSummary.length;
    // Return the last [checkSummaryBufferLimit] characters as they are likely the most relevant.
    if (summary.length > checkSummaryBufferLimit) {
      final String truncatedSummary = summary.substring(summary.length - checkSummaryBufferLimit);
      summary = '[TRUNCATED...] $truncatedSummary';
    }
    return '$kGithubSummary$summary';
  }

  /// Transforms a [push_message.Result] to a [github.CheckRunConclusion].
  /// Relevant APIs:
  ///   https://developer.github.com/v3/checks/runs/#check-runs
  github.CheckRunConclusion conclusionForResult(push_message.Result? result) {
    switch (result) {
      case push_message.Result.canceled:
        // Set conclusion cancelled as a failure to ensure developers can retry
        // tasks when builds timeout.
        return github.CheckRunConclusion.failure;
      case push_message.Result.failure:
      case push_message.Result.infraFailure:
        return github.CheckRunConclusion.failure;
      case push_message.Result.success:
        return github.CheckRunConclusion.success;
      case null:
        throw StateError('unreachable');
    }
  }

  /// Transforms a [push_message.Status] to a [github.CheckRunStatus].
  /// Relevant APIs:
  ///   https://developer.github.com/v3/checks/runs/#check-runs
  github.CheckRunStatus statusForResult(push_message.Status? status) {
    switch (status) {
      case push_message.Status.completed:
        return github.CheckRunStatus.completed;
      case push_message.Status.scheduled:
        return github.CheckRunStatus.queued;
      case push_message.Status.started:
        return github.CheckRunStatus.inProgress;
      case null:
        throw StateError('unreachable');
    }
  }

  /// Given a [headSha] and [checkSuiteId], finds the [PullRequest] that matches.
  Future<github.PullRequest?> findMatchingPullRequest(
    github.RepositorySlug slug,
    String headSha,
    int checkSuiteId,
  ) async {
    final GithubService githubService = await config.createDefaultGitHubService();

    // There could be multiple PRs that have the same [headSha] commit.
    final List<github.Issue> prIssues = await githubService.searchIssuesAndPRs(slug, '$headSha type:pr');

    for (final prIssue in prIssues) {
      final int prNumber = prIssue.number;

      // Each PR can have multiple check suites.
      final List<github.CheckSuite> checkSuites = await githubChecksUtil.listCheckSuitesForRef(
        githubService.github,
        slug,
        ref: 'refs/pull/$prNumber/head',
      );

      // Use check suite ID equality to verify that we have iterated to the correct PR.
      final bool doesPrIncludeMatchingCheckSuite = checkSuites.any((checkSuite) => checkSuite.id! == checkSuiteId);
      if (doesPrIncludeMatchingCheckSuite) {
        return githubService.getPullRequest(slug, prNumber);
      }
    }

    return null;
  }
}
