// 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:async';
import 'dart:convert' show Encoding, json;
import 'dart:io';

import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:http/http.dart';
import 'package:logging/logging.dart';
import 'package:meta/meta.dart';

import 'task_result.dart';
import 'utils.dart';

typedef ProcessRunSync = ProcessResult Function(
  String,
  List<String>, {
  Map<String, String>? environment,
  bool includeParentEnvironment,
  bool runInShell,
  Encoding? stderrEncoding,
  Encoding? stdoutEncoding,
  String? workingDirectory,
});

/// Class for test runner to interact with Flutter's infrastructure service, Cocoon.
///
/// Cocoon assigns bots to run these devicelab tasks on real devices.
/// To retrieve these results, the test runner needs to send results back so the database can be updated.
class Cocoon {
  Cocoon({
    String? serviceAccountTokenPath,
    @visibleForTesting Client? httpClient,
    @visibleForTesting this.fs = const LocalFileSystem(),
    @visibleForTesting this.processRunSync = Process.runSync,
    @visibleForTesting this.requestRetryLimit = 5,
    @visibleForTesting this.requestTimeoutLimit = 30,
  }) : _httpClient = AuthenticatedCocoonClient(serviceAccountTokenPath, httpClient: httpClient, filesystem: fs);

  /// Client to make http requests to Cocoon.
  final AuthenticatedCocoonClient _httpClient;

  final ProcessRunSync processRunSync;

  /// Url used to send results to.
  static const String baseCocoonApiUrl = 'https://flutter-dashboard.appspot.com/api';

  /// Threshold to auto retry a failed test.
  static const int retryNumber = 2;

  /// Underlying [FileSystem] to use.
  final FileSystem fs;

  static final Logger logger = Logger('CocoonClient');

  @visibleForTesting
  final int requestRetryLimit;

  @visibleForTesting
  final int requestTimeoutLimit;

  String get commitSha => _commitSha ?? _readCommitSha();
  String? _commitSha;

  /// Parse the local repo for the current running commit.
  String _readCommitSha() {
    final ProcessResult result = processRunSync('git', <String>['rev-parse', 'HEAD']);
    if (result.exitCode != 0) {
      throw CocoonException(result.stderr as String);
    }

    return _commitSha = result.stdout as String;
  }

  /// Update test status to Cocoon.
  ///
  /// Flutter infrastructure's workflow is:
  /// 1. Run DeviceLab test
  /// 2. Request service account token from luci auth (valid for at least 3 minutes)
  /// 3. Update test status from (1) to Cocoon
  ///
  /// The `resultsPath` is not available for all tests. When it doesn't show up, we
  /// need to append `CommitBranch`, `CommitSha`, and `BuilderName`.
  Future<void> sendTaskStatus({
    String? resultsPath,
    bool? isTestFlaky,
    String? gitBranch,
    String? builderName,
    String? testStatus,
    String? builderBucket,
  }) async {
    Map<String, dynamic> resultsJson = <String, dynamic>{};
    if (resultsPath != null) {
      final File resultFile = fs.file(resultsPath);
      resultsJson = json.decode(await resultFile.readAsString()) as Map<String, dynamic>;
    } else {
      resultsJson['CommitBranch'] = gitBranch;
      resultsJson['CommitSha'] = commitSha;
      resultsJson['BuilderName'] = builderName;
      resultsJson['NewStatus'] = testStatus;
    }
    resultsJson['TestFlaky'] = isTestFlaky ?? false;
    if (_shouldUpdateCocoon(resultsJson, builderBucket ?? 'prod')) {
      await retry(
        () async => _sendUpdateTaskRequest(resultsJson).timeout(Duration(seconds: requestTimeoutLimit)),
        retryIf: (Exception e) => e is SocketException || e is TimeoutException || e is ClientException,
        maxAttempts: requestRetryLimit,
      );
    }
  }

  /// Only post-submit tests on `master` are allowed to update in cocoon.
  bool _shouldUpdateCocoon(Map<String, dynamic> resultJson, String builderBucket) {
    const List<String> supportedBranches = <String>['master'];
    return supportedBranches.contains(resultJson['CommitBranch']) && builderBucket == 'prod';
  }

  /// Write the given parameters into an update task request and store the JSON in [resultsPath].
  Future<void> writeTaskResultToFile({
    String? builderName,
    String? gitBranch,
    required TaskResult result,
    required String resultsPath,
  }) async {
    final Map<String, dynamic> updateRequest = _constructUpdateRequest(
      gitBranch: gitBranch,
      builderName: builderName,
      result: result,
    );
    final File resultFile = fs.file(resultsPath);
    if (resultFile.existsSync()) {
      resultFile.deleteSync();
    }
    logger.fine('Writing results: ${json.encode(updateRequest)}');
    resultFile.createSync();
    resultFile.writeAsStringSync(json.encode(updateRequest));
  }

  Map<String, dynamic> _constructUpdateRequest({
    String? builderName,
    required TaskResult result,
    String? gitBranch,
  }) {
    final Map<String, dynamic> updateRequest = <String, dynamic>{
      'CommitBranch': gitBranch,
      'CommitSha': commitSha,
      'BuilderName': builderName,
      'NewStatus': result.succeeded ? 'Succeeded' : 'Failed',
    };
    logger.fine('Update request: $updateRequest');

    // Make a copy of result data because we may alter it for validation below.
    updateRequest['ResultData'] = result.data;

    final List<String> validScoreKeys = <String>[];
    if (result.benchmarkScoreKeys != null) {
      for (final String scoreKey in result.benchmarkScoreKeys!) {
        final Object score = result.data![scoreKey] as Object;
        if (score is num) {
          // Convert all metrics to double, which provide plenty of precision
          // without having to add support for multiple numeric types in Cocoon.
          result.data![scoreKey] = score.toDouble();
          validScoreKeys.add(scoreKey);
        }
      }
    }
    updateRequest['BenchmarkScoreKeys'] = validScoreKeys;

    return updateRequest;
  }

  Future<void> _sendUpdateTaskRequest(Map<String, dynamic> postBody) async {
    logger.info('Attempting to send update task request to Cocoon.');
    final Map<String, dynamic> response = await _sendCocoonRequest('update-task-status', postBody);
    if (response['Name'] != null) {
      logger.info('Updated Cocoon with results from this task');
    } else {
      logger.info(response);
      logger.severe('Failed to updated Cocoon with results from this task');
    }
  }

  /// Make an API request to Cocoon.
  Future<Map<String, dynamic>> _sendCocoonRequest(String apiPath, [dynamic jsonData]) async {
    final Uri url = Uri.parse('$baseCocoonApiUrl/$apiPath');

    /// Retry requests to Cocoon as sometimes there are issues with the servers, such
    /// as version changes to the backend, datastore issues, or latency issues.
    final Response response = await retry(
      () => _httpClient.post(url, body: json.encode(jsonData)),
      retryIf: (Exception e) => e is SocketException || e is TimeoutException || e is ClientException,
      maxAttempts: requestRetryLimit,
    );
    return json.decode(response.body) as Map<String, dynamic>;
  }
}

/// [HttpClient] for sending authenticated requests to Cocoon.
class AuthenticatedCocoonClient extends BaseClient {
  AuthenticatedCocoonClient(
    this._serviceAccountTokenPath, {
    @visibleForTesting Client? httpClient,
    @visibleForTesting FileSystem? filesystem,
  })  : _delegate = httpClient ?? Client(),
        _fs = filesystem ?? const LocalFileSystem();

  /// Authentication token to have the ability to upload and record test results.
  ///
  /// This is intended to only be passed on automated runs on LUCI post-submit.
  final String? _serviceAccountTokenPath;

  /// Underlying [HttpClient] to send requests to.
  final Client _delegate;

  /// Underlying [FileSystem] to use.
  final FileSystem _fs;

  /// Value contained in the service account token file that can be used in http requests.
  String get serviceAccountToken => _serviceAccountToken ?? _readServiceAccountTokenFile();
  String? _serviceAccountToken;

  /// Get [serviceAccountToken] from the given service account file.
  String _readServiceAccountTokenFile() {
    return _serviceAccountToken = _fs.file(_serviceAccountTokenPath).readAsStringSync().trim();
  }

  @override
  Future<StreamedResponse> send(BaseRequest request) async {
    request.headers['Service-Account-Token'] = serviceAccountToken;
    final StreamedResponse response = await _delegate.send(request);

    if (response.statusCode != 200) {
      throw ClientException(
          'AuthenticatedClientError:\n'
          '  URI: ${request.url}\n'
          '  HTTP Status: ${response.statusCode}\n'
          '  Response body:\n'
          '${(await Response.fromStream(response)).body}',
          request.url);
    }
    return response;
  }
}

class CocoonException implements Exception {
  CocoonException(this.message) : assert(message != null);

  /// The message to show to the issuer to explain the error.
  final String message;

  @override
  String toString() => 'CocoonException: $message';
}
