#!/usr/bin/env dart
// Copyright (c) 2023, 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.

// A script to find all try jobs for a set of tests.
//
// Usage:
//
// ```
// $ tools/find_builders.dart ffi/regress_51504_test ffi/regress_52298_test
// Cq-Include-Trybots: dart/try:vm-kernel-linux-debug-x64,...
// ```

import 'dart:convert';
import 'dart:io';

// TODO(dacoharkes): Be able to use test full paths instead of test names.
// TODO(dacoharkes): Be able to use different filters.
Future<void> main(List<String> args) async {
  if (args.contains('--help')) {
    return printHelp();
  }
  final testNames = args;

  final configurations = _filterConfigurations({
    for (final testName in testNames) ...await _testGetConfigurations(testName),
  });
  final configurationBuilders = await _configurationBuilders();
  final builders =
      _filterBuilders({
          for (final config in configurations) configurationBuilders[config]!,
        }).toList()
        ..sort();

  final gerritTryList = builders.map((b) => '$b-try').join(',');
  print('Cq-Include-Trybots: dart/try:$gerritTryList');
}

Future<List<String>> _testGetConfigurations(String testName) async {
  final requestUrl = Uri(
    scheme: 'https',
    host: 'current-results-qvyo5rktwa-uc.a.run.app',
    path: 'v1/results',
    queryParameters: {'filter': testName},
  );
  final response = await _get(requestUrl);
  final object = jsonDecode(response) as Map<String, dynamic>;
  return [
    for (final result in ((object['results'] as List)).cast<Map>())
      result['configuration'],
  ];
}

Future<String> _get(Uri requestUrl) async {
  final client = HttpClient();
  final request = await client.getUrl(requestUrl);
  final response = await request.close();
  final responseString = await response.transform(const Utf8Decoder()).join();
  client.close();
  return responseString;
}

Iterable<String> _filterConfigurations(Set<String> configs) {
  final result = <String>[];
  for (final config in configs) {
    if (config.contains('debug')) {
      result.add(config);
    } else if (config.contains('release') &&
        !configs.contains(config.replaceFirst('release', 'debug'))) {
      result.add(config);
    } else if (config.contains('profile') &&
        !configs.contains(config.replaceFirst('profile', 'debug')) &&
        !configs.contains(config.replaceFirst('profile', 'release'))) {
      result.add(config);
    }
  }
  return result..sort();
}

Iterable<String> _filterBuilders(Iterable<String> builders) {
  return builders.where(
    (b) => !_ciOnlyBuilders.contains(b) && !_denyListedBuilders.contains(b),
  );
}

const _ciOnlyBuilders = {
  'vm-aot-linux-release-arm64',
  'vm-linux-release-arm64',
};

const _denyListedBuilders = <String>{};

Stream<Map<String, dynamic>> _configurationDocuments() async* {
  String? nextPageToken;
  do {
    final requestUrl = Uri(
      scheme: 'https',
      host: 'firestore.googleapis.com',
      path: 'v1/projects/dart-ci/databases/(default)/documents/configurations',
      queryParameters: {
        'pageSize': '300',
        if (nextPageToken != null) 'pageToken': nextPageToken,
      },
    );
    final response = await _get(requestUrl);
    final object = jsonDecode(response) as Map<String, dynamic>;
    yield* Stream.fromIterable(
      (object['documents'] as List).cast<Map<String, dynamic>>(),
    );

    nextPageToken = object['nextPageToken'];
  } while (nextPageToken != null);
}

Future<Map<String, String>> _configurationBuilders() async {
  return {
    await for (final document in _configurationDocuments())
      if (document case {
        'name': String fullName,
        'fields': {'builder': {'stringValue': String builder}},
      })
        fullName.split('/').last: builder,
  };
}

void printHelp() {
  print(r'''
A script to find all try jobs for a set of tests.

  Usage: tools/find_builders.dart [selector] [selector2] [...]

Sample output: Cq-Include-Trybots: dart/try:vm-kernel-linux-debug-x64,...
''');
}
