// Copyright (c) 2019, 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.

// Add fields with data about the test run and the commit tested, and
// with the result on the last build tested, to the test results file.

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

import 'package:test_runner/bot_results.dart';

const skipped = 'skipped';

main(List<String> args) async {
  final resultsPath = args[0];
  final priorResultsPath = args[1];
  final flakyPath = args[2];
  final priorFlakyPath = args[3];
  final builderName = args[4];
  final buildNumber = args[5];
  final commitTime = int.parse(args[6]);
  final commitHash = args[7];
  final newResultsPath = args[8];
  // Load the input and the flakiness data if specified.
  final results = await loadResultsMap(resultsPath);
  final priorResults = await loadResultsMap(priorResultsPath);
  final flakes = await loadResultsMap(flakyPath);
  final priorFlakes = await loadResultsMap(priorFlakyPath);
  final firstPriorResult =
      priorResults.isEmpty ? null : priorResults.values.first;

  priorResults.forEach((key, priorResult) {
    if (priorResult['result'] != skipped) {
      results.putIfAbsent(key, () => constructNotRunResult(priorResult));
    }
  });
  for (final String key in results.keys) {
    final Map<String, dynamic> result = results[key]!;
    final Map<String, dynamic>? priorResult = priorResults[key];
    final Map<String, dynamic>? flaky = flakes[key];
    final Map<String, dynamic>? priorFlaky = priorFlakes[key];
    result['commit_hash'] = commitHash;
    result['commit_time'] = commitTime;
    result['build_number'] = buildNumber;
    result['builder_name'] = builderName;
    result['flaky'] = flaky != null && (flaky['active'] ?? true) == true;
    result['previous_flaky'] =
        priorFlaky != null && (priorFlaky['active'] ?? true) == true;
    if (firstPriorResult != null) {
      result['previous_commit_hash'] = firstPriorResult['commit_hash'];
      result['previous_commit_time'] = firstPriorResult['commit_time'];
      result['previous_build_number'] = firstPriorResult['build_number'];
    }
    if (priorResult != null) {
      result['previous_result'] = priorResult['result'];
      result['changed'] = !(result['result'] == result['previous_result'] &&
          result['flaky'] == result['previous_flaky'] &&
          result['expected'] == priorResult['expected']);
    } else {
      result['changed'] = true;
    }
  }
  final sink = File(newResultsPath).openWrite();
  final sorted = results.keys.toList()..sort();
  for (final key in sorted) {
    sink.writeln(jsonEncode(results[key]));
  }
  sink.close();
}

Map<String, dynamic> constructNotRunResult(Map<String, dynamic> previous) => {
      for (final key in [
        'name',
        'configuration',
        'suite',
        'test_name',
        'expected'
      ])
        key: previous[key],
      'time_ms': 0,
      'result': skipped,
      'matches': true,
      'bot_name': '',
    };
