#!/usr/bin/env dart
// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// Find the newest commit that has a full set of results on the builders.

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math';

import 'package:args/args.dart';
import 'package:glob/glob.dart';

void main(List<String> args) async {
  final parser = ArgParser();
  parser.addMultiOption('builder',
      abbr: 'b',
      help: 'Select the builders matching the glob [option is repeatable]',
      splitCommas: false);
  parser.addOption('branch',
      abbr: 'B',
      help: 'Select the builders building this branch',
      defaultsTo: 'main');
  parser.addOption('count',
      abbr: 'c', help: 'List this many commits', defaultsTo: '1');
  parser.addFlag('help', help: 'Show the program usage.', negatable: false);

  final options = parser.parse(args);
  if (options['help']) {
    print('''
Usage: find_base_commit.dart [OPTION]...
Find the newest commit that has a full set of results on the builders.

The options are as follows:

${parser.usage}''');
    return;
  }

  int count = int.parse(options['count']);
  final globs = List<Glob>.from(
      options['builder'].map((String pattern) => Glob(pattern)));

  // Download the most recent builds from buildbucket.
  const maxBuilds = 1000;
  final url = Uri.parse('https://cr-buildbucket.appspot.com'
      '/prpc/buildbucket.v2.Builds/SearchBuilds');
  const maxRetries = 3;
  const timeout = Duration(seconds: 30);
  final query = jsonEncode({
    'predicate': {
      'builder': {'project': 'dart', 'bucket': 'ci.sandbox'},
      'status': 'ENDED_MASK'
    },
    'pageSize': maxBuilds,
    'fields': 'builds.*.builder.builder,builds.*.input'
  });
  late Map<String, dynamic> searchResult;
  for (int i = 1; i <= maxRetries; i++) {
    try {
      final client = HttpClient();
      final request = await client.postUrl(url).timeout(timeout)
        ..headers.contentType = ContentType.json
        ..headers.add(HttpHeaders.acceptHeader, ContentType.json)
        ..write(query);
      final response = await request.close().timeout(timeout);
      if (response.statusCode != 200) {
        print('Failed to search for builds: '
            '${response.statusCode}:${response.reasonPhrase}');
        exit(1);
      }
      const prefix = ")]}'";
      searchResult = await (response
          .cast<List<int>>()
          .transform(Utf8Decoder())
          .map((event) =>
              event.startsWith(prefix) ? event.substring(prefix.length) : event)
          .transform(JsonDecoder())
          .cast<Map<String, dynamic>>()
          .first
          .timeout(timeout));
      client.close();
      break;
    } on TimeoutException catch (e) {
      final inSeconds = e.duration?.inSeconds;
      stderr.writeln(
          'Attempt $i of $maxRetries timed out after $inSeconds seconds');
      if (i == maxRetries) {
        stderr.writeln('error: Failed to download $url');
        exit(1);
      }
    }
  }

  // Locate the builds we're interested in and map them to each commit. The
  // builds returned by the API are sorted with the newest first. Since builders
  // don't build back in time and always build the latest commit whenever they
  // can, the first time we see a commit, we know it's newer than all commits
  // we haven't seen yet. The insertion order into the buildersForCommits map
  // will then sorted with the newest commit first.
  final builds = searchResult['builds'];
  if (builds == null) {
    print('No builds found');
    exit(1);
  }
  final buildersForCommits = <String, Set<String>>{};
  for (final build in builds) {
    final builder = build['builder']?['builder'];
    if (builder is! String ||
        builder.endsWith('-beta') ||
        builder.endsWith('-dev') ||
        builder.endsWith('-stable')) {
      // Ignore the release builders. The -try builders aren't in the
      // bucket we're reading.
      continue;
    }
    if (globs.isNotEmpty && !globs.any((glob) => glob.matches(builder))) {
      // Filter way builders we're not interested in.
      continue;
    }
    final input = build['input']?['gitilesCommit'];
    if (input == null) {
      // Ignore builds not triggered by a commit, e.g. fuzz-linux.
      continue;
    }
    final ref = input['ref'];
    if (ref != "refs/heads/${options['branch']}") {
      // Ignore builds on the wrong branch.
      continue;
    }
    final commit = input['id'] as String;
    final buildersForCommit =
        buildersForCommits.putIfAbsent(commit, () => <String>{});
    buildersForCommit.add(builder);
  }

  if (buildersForCommits.isEmpty) {
    print('Failed to locate any commits having run on the builders');
    exitCode = 1;
    return;
  }

  int maxBots = 0;
  for (final builders in buildersForCommits.values) {
    maxBots = max(maxBots, builders.length);
  }

  // List commits run on the most builders.
  for (final commit in buildersForCommits.keys
      .where((commit) => buildersForCommits[commit]!.length == maxBots)
      .take(count)) {
    print(commit);
  }
}
