// 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 == null || 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 ?? 0) + 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, {String? ref}) async {
    ArgumentError.checkNotNull(slug);
    ArgumentError.checkNotNull(path);
    final RepositoryContents contents = await github.repositories.getContents(slug, path, ref: ref);
    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))));
  }
}
