// Copyright 2022 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 'dart:async';
import 'dart:convert';
import 'package:auto_submit/service/log.dart';
import 'package:github/github.dart';

/// If a pull request was behind the tip of tree by _kBehindToT commits
/// then the bot tries to rebase it
const int _kBehindToT = 10;

/// [GithubService] handles communication with the GitHub API.
class GithubService {
  GithubService(this.github);

  final GitHub github;

  /// Retrieves check runs with the ref.
  Future<List<CheckRun>> getCheckRuns(
    RepositorySlug slug,
    String ref,
  ) async {
    return github.checks.checkRuns.listCheckRunsForRef(slug, ref: ref).toList();
  }

  Future<List<CheckRun>> getCheckRunsFiltered({
    required RepositorySlug slug,
    required String ref,
    String? checkName,
    CheckRunStatus? status,
    CheckRunFilter? filter,
  }) async {
    return github.checks.checkRuns
        .listCheckRunsForRef(
          slug,
          ref: ref,
          checkName: checkName,
          status: status,
          filter: filter,
        )
        .toList();
  }

  /// Fetches the specified commit.
  Future<RepositoryCommit> getCommit(
    RepositorySlug slug,
    String sha,
  ) async {
    return github.repositories.getCommit(slug, sha);
  }

  Future<List<PullRequestFile>> getPullRequestFiles(
    RepositorySlug slug,
    PullRequest pullRequest,
  ) async {
    final int? pullRequestId = pullRequest.number;
    final List<PullRequestFile> listPullRequestFiles = [];

    if (pullRequestId == null) {
      return listPullRequestFiles;
    }

    final Stream<PullRequestFile> pullRequestFiles = github.pullRequests.listFiles(slug, pullRequestId);

    await for (PullRequestFile file in pullRequestFiles) {
      listPullRequestFiles.add(file);
    }

    return listPullRequestFiles;
  }

  /// Create a new issue in github.
  Future<Issue> createIssue({
    required RepositorySlug slug,
    required String title,
    required String body,
    List<String>? labels,
    String? assignee,
    List<String>? assignees,
    String? state,
  }) async {
    final IssueRequest issueRequest = IssueRequest(
      title: title,
      body: body,
      labels: labels,
      assignee: assignee,
      assignees: assignees,
      state: state,
    );
    return github.issues.create(slug, issueRequest);
  }

  Future<Issue> getIssue({
    required RepositorySlug slug,
    required int issueNumber,
  }) async {
    return github.issues.get(slug, issueNumber);
  }

  /// Create a pull request.
  Future<PullRequest> createPullRequest({
    required RepositorySlug slug,
    String? title,
    String? head,
    required String base,
    bool draft = false,
    String? body,
  }) async {
    final CreatePullRequest createPullRequest = CreatePullRequest(
      title,
      head,
      base,
      draft: draft,
      body: body,
    );
    return github.pullRequests.create(slug, createPullRequest);
  }

  /// Fetches the specified pull request.
  Future<PullRequest> getPullRequest(
    RepositorySlug slug,
    int pullRequestNumber,
  ) async {
    return github.pullRequests.get(slug, pullRequestNumber);
  }

  Future<List<PullRequest>> listPullRequests(
    RepositorySlug slug, {
    int? pages,
    String? base,
    String direction = 'desc',
    String? head,
    String sort = 'created',
    String state = 'open',
  }) async {
    final List<PullRequest> pullRequestsFound = [];
    final Stream<PullRequest> pullRequestStream = github.pullRequests.list(
      slug,
      pages: pages,
      direction: direction,
      head: head,
      sort: sort,
      state: state,
    );
    await for (PullRequest pullRequest in pullRequestStream) {
      pullRequestsFound.add(pullRequest);
    }
    return pullRequestsFound;
  }

  Future<bool> addReviewersToPullRequest(
    RepositorySlug slug,
    int pullRequestNumber,
    List<String> reviewerLogins,
  ) async {
    final response = await github.request(
      'POST',
      '/repos/${slug.fullName}/pulls/$pullRequestNumber/requested_reviewers',
      body: GitHubJson.encode({'reviewers': reviewerLogins}),
    );
    return response.statusCode == StatusCodes.CREATED;
  }

  /// Get the reviews for Pull Request with number pullRequestNumber.
  Future<List<PullRequestReview>> getPullRequestReviews(
    RepositorySlug slug,
    int pullRequestNumber,
  ) async {
    return github.pullRequests.listReviews(slug, pullRequestNumber).toList();
  }

  /// Compares two commits to fetch diff.
  ///
  /// The response will include details on the files that were changed between the two commits.
  /// Relevant APIs: https://docs.github.com/en/rest/reference/commits#compare-two-commits
  Future<GitHubComparison> compareTwoCommits(
    RepositorySlug slug,
    String refBase,
    String refHead,
  ) async {
    return github.repositories.compareCommits(slug, refBase, refHead);
  }

  /// Removes a label from a pull request.
  Future<bool> removeLabel(
    RepositorySlug slug,
    int issueNumber,
    String label,
  ) async {
    return github.issues.removeLabelForIssue(slug, issueNumber, label);
  }

  /// Add labels to a pull request.
  Future<List<IssueLabel>> addLabels(
    RepositorySlug slug,
    int issueNumber,
    List<String> labels,
  ) async {
    return github.issues.addLabelsToIssue(slug, issueNumber, labels);
  }

  /// Relevant API: https://docs.github.com/en/rest/issues/assignees?apiVersion=2022-11-28#add-assignees-to-an-issue
  Future<bool> addAssignee(
    RepositorySlug slug,
    int number,
    List<String> assignees,
  ) async {
    final response = await github.request(
      'POST',
      '/repos/${slug.fullName}/issues/$number/assignees',
      body: GitHubJson.encode({'assignees': assignees}),
    );
    return response.statusCode == StatusCodes.CREATED;
  }

  /// Create a comment for a pull request.
  Future<IssueComment> createComment(
    RepositorySlug slug,
    int issueNumber,
    String body,
  ) async {
    return github.issues.createComment(slug, issueNumber, body);
  }

  Future<List<IssueComment>> getIssueComments(
    RepositorySlug slug,
    int issueNumber,
  ) async {
    return github.issues.listCommentsByIssue(slug, issueNumber).toList();
  }

  /// Update a pull request branch
  Future<bool> updateBranch(
    RepositorySlug slug,
    int number,
    String headSha,
  ) async {
    final response = await github.request(
      'PUT',
      '/repos/${slug.fullName}/pulls/$number/update-branch',
      body: GitHubJson.encode({'expected_head_sha': headSha}),
    );
    return response.statusCode == StatusCodes.ACCEPTED;
  }

  Future<Branch> getBranch(
    RepositorySlug slug,
    String branchName,
  ) async {
    return github.repositories.getBranch(slug, branchName);
  }

  Future<bool> deleteBranch(
    RepositorySlug slug,
    String branchName,
  ) async {
    final String ref = 'heads/$branchName';
    return github.git.deleteReference(slug, ref);
  }

  /// Merges a pull request according to the MergeMethod type. Current supported
  /// merge method types are merge, rebase and squash.
  Future<PullRequestMerge> mergePullRequest(
    RepositorySlug slug,
    int number, {
    String? commitMessage,
    MergeMethod mergeMethod = MergeMethod.merge,
    String? requestSha,
  }) async {
    return github.pullRequests.merge(
      slug,
      number,
      message: commitMessage,
      mergeMethod: mergeMethod,
      requestSha: requestSha,
    );
  }

  /// Automerges a given pull request with HEAD to ensure the commit is not in conflicting state.
  Future<void> autoMergeBranch(PullRequest pullRequest) async {
    final RepositorySlug slug = pullRequest.base!.repo!.slug();
    final int prNumber = pullRequest.number!;
    final RepositoryCommit totCommit = await getCommit(slug, 'HEAD');
    final GitHubComparison comparison = await compareTwoCommits(slug, totCommit.sha!, pullRequest.base!.sha!);
    if (comparison.behindBy! >= _kBehindToT) {
      log.info('The current branch is behind by ${comparison.behindBy} commits.');
      final String headSha = pullRequest.head!.sha!;
      await updateBranch(slug, prNumber, headSha);
    }
  }

  /// Get contents from a repository at the supplied path.
  Future<String> getFileContents(RepositorySlug slug, String path, {String? ref}) async {
    final RepositoryContents repositoryContents = await github.repositories.getContents(slug, path, ref: ref);
    if (!repositoryContents.isFile) {
      throw 'Contents do not point to a file.';
    }
    final String content = utf8.decode(base64.decode(repositoryContents.file!.content!.replaceAll('\n', '')));
    return content;
  }

  /// Check to see if user is a member of team in org.
  ///
  /// Note that we catch here as the api returns a 404 if the user has no
  /// membership in general or is not a member of the team.
  Future<bool> isTeamMember(String team, String user, String org) async {
    try {
      final TeamMembershipState teamMembershipState =
          await github.organizations.getTeamMembershipByName(org, team, user);
      return teamMembershipState.isActive;
    } on GitHubError {
      return false;
    }
  }

  /// Get the definition of a single repository
  Future<Repository> getRepository(RepositorySlug slug) async {
    return github.repositories.getRepository(slug);
  }

  Future<String> getDefaultBranch(RepositorySlug slug) async {
    final Repository repository = await getRepository(slug);
    return repository.defaultBranch;
  }
}
