// Copyright 2014 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:io' as io;

import 'package:process/process.dart';

import 'git.dart';
import 'globals.dart';
import 'repository.dart';
import 'stdio.dart';

/// A service for rolling the SDK's pub packages to latest and open a PR upstream.
class PackageAutoroller {
  PackageAutoroller({
    required this.githubClient,
    required this.token,
    required this.framework,
    required this.orgName,
    required this.processManager,
    this.githubUsername = 'fluttergithubbot',
    Stdio? stdio,
  }) {
    this.stdio = stdio ?? VerboseStdio.local();
    if (token.trim().isEmpty) {
      throw Exception('empty token!');
    }
    if (githubClient.trim().isEmpty) {
      throw Exception('Must provide path to GitHub client!');
    }
    if (orgName.trim().isEmpty) {
      throw Exception('Must provide an orgName!');
    }
  }

  late final Stdio stdio;

  final FrameworkRepository framework;
  final ProcessManager processManager;

  /// Path to GitHub CLI client.
  final String githubClient;

  final String githubUsername;

  /// GitHub API access token.
  final String token;

  static const String hostname = 'github.com';

  static const String prBody = '''
This PR was generated by `flutter update-packages --force-upgrade`.
''';

  /// Name of the feature branch to be opened on against the mirror repo.
  ///
  /// We never re-use a previous branch, so the branch name ends in an index
  /// number, which gets incremented for each roll.
  late final Future<String> featureBranchName = (() async {
    final List<String> remoteBranches = await framework.listRemoteBranches(framework.mirrorRemote!.name);

    int x = 1;
    String name(int index) => 'packages-autoroller-branch-$index';

    while (remoteBranches.contains(name(x))) {
      x += 1;
    }

    return name(x);
  })();

  void log(String message) {
    stdio.printStatus(_redactToken(message));
  }

  /// Name of the GitHub organization to push the feature branch to.
  final String orgName;

  Future<void> roll() async {
    try {
      await authLogin();
      final bool openPrAlready = await hasOpenPrs();
      if (openPrAlready) {
        // Don't open multiple roll PRs.
        return;
      }
      final bool didUpdate = await updatePackages();
      if (!didUpdate) {
        log('Packages are already at latest.');
        return;
      }
      await pushBranch();
      await createPr(repository: await framework.checkoutDirectory);
      await authLogout();
    } on Exception catch (exception) {
      final String message = _redactToken(exception.toString());
      throw Exception('${exception.runtimeType}: $message');
    }
  }

  // Ensure we don't leak the GitHub token in exception messages
  String _redactToken(String message) => message.replaceAll(token, '[GitHub TOKEN]');

  /// Attempt to update all pub packages.
  ///
  /// Will return whether or not any changes were made.
  Future<bool> updatePackages({
    bool verbose = true,
  }) async {
    final String author = '$githubUsername <$githubUsername@gmail.com>';

    await framework.newBranch(await featureBranchName);
    final io.Process flutterProcess = await framework.streamFlutter(<String>[
      if (verbose) '--verbose',
      'update-packages',
      '--force-upgrade',
    ]);
    final int exitCode = await flutterProcess.exitCode;
    if (exitCode != 0) {
      throw ConductorException('Failed to update packages with exit code $exitCode');
    }
    // If the git checkout is clean, then pub packages are already at latest that cleanly resolve.
    if (await framework.gitCheckoutClean()) {
      return false;
    }
    await framework.commit(
      'roll packages',
      addFirst: true,
      author: author,
    );
    return true;
  }

  Future<void> pushBranch() async {
    final String projectName = framework.mirrorRemote!.url.split(r'/').last;
    // Encode the token into the remote URL for authentication to work
    final String remote = 'https://$token@$hostname/$orgName/$projectName';
    await framework.pushRef(
      fromRef: await featureBranchName,
      toRef: await featureBranchName,
      remote: remote,
    );
  }

  Future<void> authLogout() {
    return cli(
      <String>['auth', 'logout', '--hostname', hostname],
      allowFailure: true,
    );
  }

  Future<void> authLogin() {
    return cli(
      <String>[
        'auth',
        'login',
        '--hostname',
        hostname,
        '--git-protocol',
        'https',
        '--with-token',
      ],
      stdin: '$token\n',
    );
  }

  /// Create a pull request on GitHub.
  ///
  /// Depends on the gh cli tool.
  Future<void> createPr({
    required io.Directory repository,
    String title = 'Roll pub packages',
    String body = 'This PR was generated by `flutter update-packages --force-upgrade`.',
    String base = FrameworkRepository.defaultBranch,
    bool draft = false,
  }) async {
    const List<String> labels = <String>['tool', 'autosubmit'];

    // We will wrap title and body in double quotes before delegating to gh
    // binary
    await cli(
      <String>[
        'pr',
        'create',
        '--title',
        title.trim(),
        '--body',
        body.trim(),
        '--head',
        '$orgName:${await featureBranchName}',
        '--base',
        base,
        for (final String label in labels) ...<String>['--label', label],
        if (draft)
          '--draft',
      ],
      workingDirectory: repository.path,
    );
  }

  Future<void> help([List<String>? args]) {
    return cli(<String>[
      'help',
      ...?args,
    ]);
  }

  /// Run a sub-process with the GitHub CLI client.
  ///
  /// Will return STDOUT of the sub-process.
  Future<String> cli(
    List<String> args, {
    bool allowFailure = false,
    String? stdin,
    String? workingDirectory,
  }) async {
    log('Executing "$githubClient ${args.join(' ')}" in $workingDirectory');
    final io.Process process = await processManager.start(
      <String>[githubClient, ...args],
      workingDirectory: workingDirectory,
      environment: <String, String>{},
    );
    final List<String> stderrStrings = <String>[];
    final List<String> stdoutStrings = <String>[];
    final Future<void> stdoutFuture = process.stdout
        .transform(utf8.decoder)
        .forEach(stdoutStrings.add);
    final Future<void> stderrFuture = process.stderr
        .transform(utf8.decoder)
        .forEach(stderrStrings.add);
    if (stdin != null) {
      process.stdin.write(stdin);
      await process.stdin.flush();
      await process.stdin.close();
    }
    final int exitCode = await process.exitCode;
    await Future.wait(<Future<Object?>>[
      stdoutFuture,
      stderrFuture,
    ]);
    final String stderr = stderrStrings.join();
    final String stdout = stdoutStrings.join();
    if (!allowFailure && exitCode != 0) {
      throw GitException(
        '$stderr\n$stdout',
        args,
      );
    }
    log(stdout);
    return stdout;
  }

  Future<bool> hasOpenPrs() async {
    // gh pr list --author christopherfujino --repo flutter/flutter --state open --json number
    final String openPrString = await cli(<String>[
      'pr',
      'list',
      '--author',
      githubUsername,
      '--repo',
      'flutter/flutter',
      '--state',
      'open',
      // We are only interested in pub rolls, not devicelab flaky PRs
      '--label',
      'tool',
      // Return structured JSON with the PR numbers of open PRs
      '--json',
      'number',
    ]);

    // This will be an array of objects, one for each open PR.
    final List<Object?> openPrs = json.decode(openPrString) as List<Object?>;

    if (openPrs.isNotEmpty) {
      log('$githubUsername already has open tool PRs:\n$openPrs');
      return true;
    }
    return false;
  }
}
