// Copyright 2019 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:convert';
import 'dart:math';

import 'package:github/github.dart';
import 'package:http/http.dart';

import '../service/logging.dart';

class GithubService {
  GithubService(this.github);

  final GitHub github;
  static final Map<String, String> headers = <String, String>{'Accept': 'application/vnd.github.groot-preview+json'};
  static const String kRefsPrefix = 'refs/heads/';

  /// Lists commits of the provided repository [slug] and [branch]. When
  /// [lastCommitTimestampMills] equals 0, it means a new release branch is
  /// found and only the branched commit will be returned for now, though the
  /// rare case that multiple commits exist. For other cases, it returns all
  /// newer commits since [lastCommitTimestampMills].
  Future<List<RepositoryCommit>> listCommits(RepositorySlug slug, String branch, int lastCommitTimestampMills) async {
    ArgumentError.checkNotNull(slug);
    final PaginationHelper paginationHelper = PaginationHelper(github);

    /// The [pages] defines the number of pages of returned http request
    /// results. Return only one page when this is a new branch. Otherwise
    ///  it will return all commits prior to this release branch commit,
    /// leading to heavy workload.
    int? pages;
    if (lastCommitTimestampMills == 0) {
      pages = 1;
    }

    List<Map<String, dynamic>> commits = <Map<String, dynamic>>[];

    /// [lastCommitTimestamp+1] excludes last commit itself.
    /// Github api url: https://developer.github.com/v3/repos/commits/#list-commits
    await for (Response response in paginationHelper.fetchStreamed(
      'GET',
      '/repos/${slug.fullName}/commits',
      params: <String, dynamic>{
        'sha': branch,
        'since': DateTime.fromMillisecondsSinceEpoch(lastCommitTimestampMills + 1).toUtc().toIso8601String(),
      },
      pages: pages,
      headers: headers,
    )) {
      commits.addAll((json.decode(response.body) as List<dynamic>).cast<Map<String, dynamic>>());
    }

    /// When a release branch is first detected only the most recent commit would be needed.
    ///
    /// If for the worst case, a new release branch consists of a useful cherry pick commit
    /// which should be considered as well, here is the todo.
    // TODO(keyonghan): https://github.com/flutter/flutter/issues/59275
    if (lastCommitTimestampMills == 0) {
      commits = commits.take(1).toList();
    }

    return commits.map<RepositoryCommit>((Map<String, dynamic> commit) {
      return RepositoryCommit()
        ..sha = commit['sha'] as String?
        ..author = (User()
          ..login = commit['author']['login'] as String?
          ..avatarUrl = commit['author']['avatar_url'] as String?)
        ..commit = (GitCommit()
          ..message = commit['commit']['message'] as String?
          ..committer = (GitCommitUser(
              commit['commit']['author']['name'] as String?,
              commit['commit']['author']['email'] as String?,
              DateTime.parse(commit['commit']['author']['date'] as String))));
    }).toList();
  }

  /// List pull requests in the repository.
  Future<List<PullRequest>> listPullRequests(RepositorySlug slug, String? branch) {
    ArgumentError.checkNotNull(slug);
    return github.pullRequests
        .list(
          slug,
          base: branch,
          direction: 'desc',
          sort: 'created',
          state: 'open',
        )
        .toList();
  }

  /// Creates a pull request against the `baseRef` in the `slug` repository.
  ///
  /// The `entries` contains the file changes in the created pull request. This
  /// method creates a branch in the current user's forked repository to create
  /// the pull request. The current user must have a forked repository from the
  /// targeted slug, and the targeted slug must not be belong to current user.
  Future<PullRequest> createPullRequest(
    RepositorySlug slug, {
    required String title,
    String? body,
    String? commitMessage,
    required GitReference baseRef,
    List<CreateGitTreeEntry>? entries,
  }) async {
    ArgumentError.checkNotNull(slug);
    ArgumentError.checkNotNull(title);

    final RepositorySlug clientSlug = await _getCurrentUserSlug(slug.name);
    final GitTree tree = await github.git.createTree(clientSlug, CreateGitTree(entries, baseTree: baseRef.object!.sha));
    final CurrentUser currentUser = (await _getCurrentUser())!;
    final GitCommitUser commitUser = GitCommitUser(currentUser.name, currentUser.email, DateTime.now());
    final GitCommit commit = await github.git.createCommit(
      clientSlug,
      CreateGitCommit(
        commitMessage,
        tree.sha,
        parents: <String?>[baseRef.object!.sha],
        author: commitUser,
        committer: commitUser,
      ),
    );
    final GitReference headRef =
        await github.git.createReference(clientSlug, '$kRefsPrefix${_generateNewRef()}', commit.sha);
    return github.pullRequests.create(
      slug,
      CreatePullRequest(title, '${clientSlug.owner}:${headRef.ref}', baseRef.ref, body: body),
    );
  }

  /// Assigns a reviewer to the pull request in the repository.
  ///
  /// The `reviewer` contains the github login of the reviewer.
  Future<void> assignReviewer(
    RepositorySlug slug, {
    int? pullRequestNumber,
    String? reviewer,
  }) async {
    const JsonEncoder encoder = JsonEncoder();
    await github.postJSON<Map<String, dynamic>, PullRequest>(
      '/repos/${slug.fullName}/pulls/$pullRequestNumber/requested_reviewers',
      convert: (Map<String, dynamic> i) => PullRequest.fromJson(i),
      body: encoder.convert(<String, dynamic>{
        'reviewers': <String?>[reviewer],
      }),
    );
  }

  /// Retrieves issues from the repository.
  ///
  /// Uses the `labels` to return the issues that have the labels.
  ///
  /// The `state` can be set `open`, `closed, or `all`. If it is set to `open`,
  /// this method only returns issues that are currently open. If it is set to
  /// `closed`, this method returns issues that are currently closed. The `all`
  /// returns both closed and open issues. Defaults to `open`.
  Future<List<Issue>> listIssues(
    RepositorySlug slug, {
    List<String>? labels,
    String state = 'open',
  }) {
    ArgumentError.checkNotNull(slug);
    return github.issues.listByRepo(slug, labels: labels, state: state).toList();
  }

  /// Get an issue with the issue number
  Future<Issue>? getIssue(
    RepositorySlug slug, {
    required int issueNumber,
  }) {
    ArgumentError.checkNotNull(slug);
    ArgumentError.checkNotNull(issueNumber);
    return github.issues.get(slug, issueNumber);
  }

  /// Assign the issue to the assignee.
  Future<void> assignIssue(
    RepositorySlug slug, {
    required int issueNumber,
    required String assignee,
  }) async {
    ArgumentError.checkNotNull(slug);
    ArgumentError.checkNotNull(issueNumber);
    ArgumentError.checkNotNull(assignee);
    await github.issues.edit(slug, issueNumber, IssueRequest(assignee: assignee));
  }

  Future<Issue> createIssue(
    RepositorySlug slug, {
    String? title,
    String? body,
    List<String>? labels,
    String? assignee,
  }) async {
    ArgumentError.checkNotNull(slug);
    return await github.issues.create(
      slug,
      IssueRequest(title: title, body: body, labels: labels, assignee: assignee),
    );
  }

  Future<IssueComment?> createComment(
    RepositorySlug slug, {
    required int issueNumber,
    required String body,
  }) async {
    ArgumentError.checkNotNull(slug);
    ArgumentError.checkNotNull(issueNumber);
    return await github.issues.createComment(slug, issueNumber, body);
  }

  Future<List<IssueLabel>> replaceLabelsForIssue(
    RepositorySlug slug, {
    required int issueNumber,
    required List<String> labels,
  }) async {
    ArgumentError.checkNotNull(slug);
    ArgumentError.checkNotNull(issueNumber);
    final Response response = await github.request('PUT', '/repos/${slug.fullName}/issues/$issueNumber/labels',
        body: GitHubJson.encode(labels));
    final List<dynamic> body = jsonDecode(response.body) as List<dynamic>;
    return body.map((dynamic it) => IssueLabel.fromJson(it as Map<String, dynamic>)).toList();
  }

  /// Returns changed files for a [PullRequest].
  ///
  /// See more:
  ///   * https://developer.github.com/v3/pulls/#list-pull-requests-files
  Future<List<String>> listFiles(PullRequest pullRequest) async {
    final List<PullRequestFile> files =
        await github.pullRequests.listFiles(pullRequest.base!.repo!.slug(), pullRequest.number!).toList();
    log.fine('List of files: $files');
    return files.map((PullRequestFile file) {
      return file.filename!;
    }).toList();
  }

  /// Gets the file content as UTF8 string of the file specified by the `path`
  /// in the repository.
  Future<String> getFileContent(RepositorySlug slug, String path) async {
    ArgumentError.checkNotNull(slug);
    ArgumentError.checkNotNull(path);
    final RepositoryContents contents = await github.repositories.getContents(slug, path);
    if (!contents.isFile) {
      throw 'The path $path should point to a file, but it is not!';
    }
    final String content = utf8.decode(base64.decode(contents.file!.content!.replaceAll('\n', '')));
    return content;
  }

  /// Gets the reference of a specific branch in the repository.
  Future<GitReference> getReference(RepositorySlug slug, String ref) {
    ArgumentError.checkNotNull(slug);
    ArgumentError.checkNotNull(ref);
    return github.git.getReference(slug, ref);
  }

  /// Returns JSON of the current GitHub API quota usage.
  ///
  /// This does not consume any API usage.
  ///
  /// Reference:
  ///   * https://docs.github.com/en/rest/reference/rate-limit
  Future<RateLimit> getRateLimit() => github.misc.getRateLimit();

  CurrentUser? _currentUser;

  Future<CurrentUser?> _getCurrentUser() async {
    _currentUser ??= await github.users.getCurrentUser();
    return _currentUser;
  }

  Future<RepositorySlug> _getCurrentUserSlug(String repository) async {
    return RepositorySlug((await _getCurrentUser())!.login!, repository);
  }

  String _generateNewRef() {
    const String chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
    final Random rnd = Random();
    return String.fromCharCodes(Iterable<int>.generate(10, (_) => chars.codeUnitAt(rnd.nextInt(chars.length))));
  }
}
