// Copyright 2013 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:crypto/crypto.dart';
import 'package:engine_repo_tools/engine_repo_tools.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'package:process/process.dart';

import 'src/errors.dart';
import 'src/release_version.dart';

export 'src/errors.dart' show SkiaGoldProcessError;

const String _kGoldctlKey = 'GOLDCTL';
const String _kPresubmitEnvName = 'GOLD_TRYJOB';
const String _kLuciEnvName = 'LUCI_CONTEXT';

const String _skiaGoldHost = 'https://flutter-engine-gold.skia.org';
const String _instance = 'flutter-engine';

/// Uploads images and makes baseline requests to Skia Gold.
///
/// For an example of how to use this class, see `tool/e2e_test.dart`.
interface class SkiaGoldClient {
  /// Creates a [SkiaGoldClient] with the given [workDirectory].
  ///
  /// A set of [dimensions] can be provided to add attributes about the
  /// environment used to generate the screenshots, which are treated as keys
  /// for the image:
  ///
  /// ```dart
  /// final SkiaGoldClient skiaGoldClient = SkiaGoldClient(
  ///   someDir,
  ///   dimensions: <String, String>{
  ///     'platform': 'linux',
  ///   },
  /// );
  /// ```
  ///
  /// The [verbose] flag is intended for use in debugging CI issues, and
  /// produces more detailed output that some may find useful, but would be too
  /// spammy for regular use.
  factory SkiaGoldClient(
    io.Directory workDirectory, {
    Map<String, String>? dimensions,
    bool verbose = false,
  }) {
    return SkiaGoldClient.forTesting(
      workDirectory,
      dimensions: dimensions,
      verbose: verbose,
    );
  }

  /// Creates a [SkiaGoldClient] for testing.
  ///
  /// Similar to the default constructor, but allows for dependency injection
  /// for testing purposes:
  ///
  /// - [httpClient] makes requests to Skia Gold to fetch expectations.
  /// - [processManager] launches sub-processes.
  /// - [stderr] is where output is written for diagnostics.
  /// - [environment] is the environment variables for the currently running
  ///   process, and is used to determine if Skia Gold is available, and whether
  ///   the current environment is CI, and if so, if it's pre-submit or
  ///   post-submit.
  /// - [engineRoot] is the root of the engine repository, which is used for
  ///   finding the current commit hash, as well as the location of the
  ///   `.engine-release.version` file.
  @visibleForTesting
  SkiaGoldClient.forTesting(
    this.workDirectory, {
    this.dimensions,
    this.verbose = false,
    io.HttpClient? httpClient,
    ProcessManager? processManager,
    StringSink? stderr,
    Map<String, String>? environment,
    Engine? engineRoot,
  }) : httpClient = httpClient ?? io.HttpClient(),
       process = processManager ?? const LocalProcessManager(),
       _stderr = stderr ?? io.stderr,
       _environment = environment ?? io.Platform.environment,
       _engineRoot = engineRoot ?? Engine.findWithin() {
    // Lookup the release version from the engine repository.
    final io.File releaseVersionFile = io.File(path.join(
      _engineRoot.flutterDir.path,
      '.engine-release.version',
    ));

    // If the file is not found or cannot be read, we are in an invalid state.
    try {
      _releaseVersion = ReleaseVersion.parse(releaseVersionFile.readAsStringSync());
    } on FormatException catch (error) {
      throw StateError('Failed to parse release version file: $error.');
    } on io.FileSystemException catch (error) {
      throw StateError('Failed to read release version file: $error.');
    }
  }

  /// The root of the engine repository.
  final Engine _engineRoot;
  ReleaseVersion? _releaseVersion;

  /// Whether the client is available and can be used in this environment.
  static bool isAvailable({
    Map<String, String>? environment,
  }) {
    final String? result = (environment ?? io.Platform.environment)[_kGoldctlKey];
    return result != null && result.isNotEmpty;
  }

  /// Returns true if the current environment is a LUCI builder.
  static bool isLuciEnv({
    Map<String, String>? environment,
  }) {
    return (environment ?? io.Platform.environment).containsKey(_kLuciEnvName);
  }

  /// Whether the current environment is a presubmit job.
  bool get _isPresubmit {
    return
        isLuciEnv(environment: _environment) &&
        isAvailable(environment: _environment) &&
        _environment.containsKey(_kPresubmitEnvName);
  }

  /// Whether the current environment is a postsubmit job.
  bool get _isPostsubmit {
    return
        isLuciEnv(environment: _environment) &&
        isAvailable(environment: _environment) &&
        !_environment.containsKey(_kPresubmitEnvName);
  }

  /// Whether to print verbose output from goldctl.
  ///
  /// This flag is intended for use in debugging CI issues, and should not
  /// ordinarily be set to true.
  final bool verbose;

  /// Environment variables for the currently running process.
  final Map<String, String> _environment;

  /// Where output is written for diagnostics.
  final StringSink _stderr;

  /// Allows to add attributes about the environment used to generate the screenshots.
  final Map<String, String>? dimensions;

  /// A controller for launching sub-processes.
  final ProcessManager process;

  /// A client for making Http requests to the Flutter Gold dashboard.
  final io.HttpClient httpClient;

  /// The local [Directory] for the current test context. In this directory, the
  /// client will create image and JSON files for the `goldctl` tool to use.
  final io.Directory workDirectory;

  String get _tempPath => path.join(workDirectory.path, 'temp');
  String get _keysPath => path.join(workDirectory.path, 'keys.json');
  String get _failuresPath => path.join(workDirectory.path, 'failures.json');

  Future<void>? _initResult;
  Future<void> _initOnce(Future<void> Function() callback) {
    // If a call has already been made, return the result of that call.
    _initResult ??= callback();
    return _initResult!;
  }

  /// Indicates whether the client has already been authorized to communicate
  /// with the Skia Gold backend.
  bool get _isAuthorized {
    final io.File authFile = io.File(path.join(_tempPath, 'auth_opt.json'));

    if (authFile.existsSync()) {
      final String contents = authFile.readAsStringSync();
      final Map<String, dynamic> decoded = json.decode(contents) as Map<String, dynamic>;
      return !(decoded['GSUtil'] as bool);
    }
    return false;
  }

  /// The path to the local [Directory] where the `goldctl` tool is hosted.
  String get _goldctl {
    assert(
      isAvailable(environment: _environment),
      'Trying to use `goldctl` in an environment where it is not available',
    );
    final String? result = _environment[_kGoldctlKey];
    if (result == null || result.isEmpty) {
      throw StateError('The environment variable $_kGoldctlKey is not set.');
    }
    return result;
  }

  /// Prepares the local work space for golden file testing and calls the
  /// `goldctl auth` command.
  ///
  /// This ensures that the `goldctl` tool is authorized and ready for testing.
  Future<void> auth() async {
    if (_isAuthorized) {
      return;
    }
    final List<String> authCommand = <String>[
      _goldctl,
      'auth',
      if (verbose) '--verbose',
      '--work-dir', _tempPath,
      '--luci',
    ];

    final io.ProcessResult result = await _runCommand(authCommand);

    if (result.exitCode != 0) {
      final StringBuffer buf = StringBuffer()
        ..writeln('Skia Gold authorization failed.')
        ..writeln('Luci environments authenticate using the file provided '
          'by LUCI_CONTEXT. There may be an error with this file or Gold '
          'authentication.');
      throw SkiaGoldProcessError(
        command: authCommand,
        stdout: result.stdout.toString(),
        stderr: result.stderr.toString(),
        message: buf.toString(),
      );
    } else if (verbose) {
      _stderr.writeln('stdout:\n${result.stdout}');
      _stderr.writeln('stderr:\n${result.stderr}');
    }
  }

  Future<io.ProcessResult> _runCommand(List<String> command) {
    return process.run(command);
  }

  /// Executes the `imgtest init` command in the `goldctl` tool.
  ///
  /// The `imgtest` command collects and uploads test results to the Skia Gold
  /// backend, the `init` argument initializes the current test.
  Future<void> _imgtestInit() async {
    final io.File keys = io.File(_keysPath);
    final io.File failures = io.File(_failuresPath);

    await keys.writeAsString(_getKeysJSON());
    await failures.create();
    final String commitHash = await _getCurrentCommit();

    final List<String> imgtestInitCommand = <String>[
      _goldctl,
      'imgtest', 'init',
      if (verbose) '--verbose',
      '--instance', _instance,
      '--work-dir', _tempPath,
      '--commit', commitHash,
      '--keys-file', keys.path,
      '--failure-file', failures.path,
      '--passfail',
    ];

    final io.ProcessResult result = await _runCommand(imgtestInitCommand);

    if (result.exitCode != 0) {
      final StringBuffer buf = StringBuffer()
        ..writeln('Skia Gold imgtest init failed.')
        ..writeln('An error occurred when initializing golden file test with ')
        ..writeln('goldctl.');
      throw SkiaGoldProcessError(
        command: imgtestInitCommand,
        stdout: result.stdout.toString(),
        stderr: result.stderr.toString(),
        message: buf.toString(),
      );
    } else if (verbose) {
      _stderr.writeln('stdout:\n${result.stdout}');
      _stderr.writeln('stderr:\n${result.stderr}');
    }

  }

  /// Executes the `imgtest add` command in the `goldctl` tool.
  ///
  /// The `imgtest` command collects and uploads test results to the Skia Gold
  /// backend, the `add` argument uploads the current image test.
  ///
  /// Throws an exception for try jobs that failed to pass the pixel comparison.
  ///
  /// The [testName] and [goldenFile] parameters reference the current
  /// comparison being evaluated.
  ///
  /// [pixelColorDelta] defines maximum acceptable difference in RGB channels of
  /// each pixel, such that:
  ///
  /// ```dart
  /// bool isSame(Color image, Color golden, int pixelDeltaThreshold) {
  ///   return abs(image.r - golden.r)
  ///     + abs(image.g - golden.g)
  ///     + abs(image.b - golden.b) <= pixelDeltaThreshold;
  /// }
  /// ```
  ///
  /// [differentPixelsRate] is the fraction of pixels that can differ, as
  /// determined by the [pixelColorDelta] parameter. It's in the range [0.0,
  /// 1.0] and defaults to 0.01. A value of 0.01 means that 1% of the pixels are
  /// allowed to be different.
  ///
  /// ## Release Testing
  ///
  /// In release branches, we add a unique test suffix to the test name. For
  /// example "testName" -> "testName_Release_3_21", based on the version in the
  /// `.engine-release.version` file at the root of the engine repository.
  ///
  /// See <../README.md#release-testing> for more information.
  Future<void> addImg(
    String testName,
    io.File goldenFile, {
    double differentPixelsRate = 0.01,
    int pixelColorDelta = 0,
    required int screenshotSize,
  }) async {
    assert(_isPresubmit || _isPostsubmit);

    // Clean the test name to remove the file extension.
    testName = path.basenameWithoutExtension(testName);

    // In release branches, we add a unique test suffix to the test name.
    // For example "testName" -> "testName_Release_3_21".
    // See ../README.md#release-testing for more information.
    if (_releaseVersion case final ReleaseVersion v) {
      testName = '${testName}_Release_${v.major}_${v.minor}';
    }

    if (_isPresubmit) {
      await _tryjobAdd(testName, goldenFile, screenshotSize, pixelColorDelta, differentPixelsRate);
    }
    if (_isPostsubmit) {
      await _imgtestAdd(testName, goldenFile, screenshotSize, pixelColorDelta, differentPixelsRate);
    }
  }

  /// Executes the `imgtest add` command in the `goldctl` tool.
  ///
  /// The `imgtest` command collects and uploads test results to the Skia Gold
  /// backend, the `add` argument uploads the current image test. A response is
  /// returned from the invocation of this command that indicates a pass or fail
  /// result.
  ///
  /// The [testName] and [goldenFile] parameters reference the current
  /// comparison being evaluated.
  Future<void> _imgtestAdd(
    String testName,
    io.File goldenFile,
    int screenshotSize,
    int pixelDeltaThreshold,
    double maxDifferentPixelsRate,
  ) async {
    await _initOnce(_imgtestInit);

    final List<String> imgtestCommand = <String>[
      _goldctl,
      'imgtest',
      'add',
      if (verbose)
      '--verbose',
      '--work-dir',
      _tempPath,
      '--test-name',
      testName,
      '--png-file',
      goldenFile.path,
      // Otherwise post submit will not fail.
      '--passfail',
      ..._getMatchingArguments(testName, screenshotSize, pixelDeltaThreshold, maxDifferentPixelsRate),
    ];

    final io.ProcessResult result = await _runCommand(imgtestCommand);

    if (result.exitCode != 0) {
      final StringBuffer buf = StringBuffer()
        ..writeln('Skia Gold received an unapproved image in post-submit ')
        ..writeln('testing. Golden file images in flutter/engine are triaged ')
        ..writeln('in pre-submit during code review for the given PR.')
        ..writeln()
        ..writeln('Visit https://flutter-engine-gold.skia.org/ to view and approve ')
        ..writeln('the image(s), or revert the associated change. For more ')
        ..writeln('information, visit the wiki: ')
        ..writeln('https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package:flutter');
      throw SkiaGoldProcessError(
        command: imgtestCommand,
        stdout: result.stdout.toString(),
        stderr: result.stderr.toString(),
        message: buf.toString(),
      );
    } else if (verbose) {
      _stderr.writeln('stdout:\n${result.stdout}');
      _stderr.writeln('stderr:\n${result.stderr}');
    }
  }

  /// Executes the `imgtest init` command in the `goldctl` tool for tryjobs.
  ///
  /// The `imgtest` command collects and uploads test results to the Skia Gold
  /// backend, the `init` argument initializes the current tryjob.
  Future<void> _tryjobInit() async {
    final io.File keys = io.File(_keysPath);
    final io.File failures = io.File(_failuresPath);

    await keys.writeAsString(_getKeysJSON());
    await failures.create();
    final String commitHash = await _getCurrentCommit();

    final List<String> tryjobInitCommand = <String>[
      _goldctl,
      'imgtest', 'init',
      if (verbose) '--verbose',
      '--instance', _instance,
      '--work-dir', _tempPath,
      '--commit', commitHash,
      '--keys-file', keys.path,
      '--failure-file', failures.path,
      '--passfail',
      '--crs', 'github',
      '--patchset_id', commitHash,
      ..._getCIArguments(),
    ];

    final io.ProcessResult result = await _runCommand(tryjobInitCommand);

    if (result.exitCode != 0) {
      final StringBuffer buf = StringBuffer()
        ..writeln('Skia Gold tryjobInit failure.')
        ..writeln('An error occurred when initializing golden file tryjob with ')
        ..writeln('goldctl.');
      throw SkiaGoldProcessError(
        command: tryjobInitCommand,
        stdout: result.stdout.toString(),
        stderr: result.stderr.toString(),
        message: buf.toString(),
      );
    } else if (verbose) {
      _stderr.writeln('stdout:\n${result.stdout}');
      _stderr.writeln('stderr:\n${result.stderr}');
    }
  }

  /// Executes the `imgtest add` command in the `goldctl` tool for tryjobs.
  ///
  /// The `imgtest` command collects and uploads test results to the Skia Gold
  /// backend, the `add` argument uploads the current image test. A response is
  /// returned from the invocation of this command that indicates a pass or fail
  /// result for the tryjob.
  ///
  /// The [testName] and [goldenFile] parameters reference the current
  /// comparison being evaluated.
  Future<void> _tryjobAdd(
    String testName,
    io.File goldenFile,
    int screenshotSize,
    int pixelDeltaThreshold,
    double differentPixelsRate,
  ) async {
    await _initOnce(_tryjobInit);

    final List<String> tryjobCommand = <String>[
      _goldctl,
      'imgtest',
      'add',
      if (verbose) '--verbose',
      '--work-dir',
      _tempPath,
      '--test-name',
      testName,
      '--png-file',
      goldenFile.path,
      ..._getMatchingArguments(testName, screenshotSize, pixelDeltaThreshold, differentPixelsRate),
    ];

    final io.ProcessResult result = await _runCommand(tryjobCommand);
    final String resultStdout = result.stdout.toString();
    if (result.exitCode == 0) {
      // In "verbose" (debugging) mode, print the output of the tryjob anyway.
      if (verbose) {
        _stderr.writeln('stdout:\n${result.stdout}');
        _stderr.writeln('stderr:\n${result.stderr}');
      }
    } else {
      // Neither of these conditions are considered failures during tryjobs.
      final bool isUntriaged = resultStdout.contains('Untriaged');
      final bool isNegative = resultStdout.contains('negative image');
      if (!isUntriaged && !isNegative) {
        final StringBuffer buf = StringBuffer()
          ..writeln('Unexpected Gold tryjobAdd failure.')
          ..writeln('Tryjob execution for golden file test $testName failed for')
          ..writeln('a reason unrelated to pixel comparison.');
        throw SkiaGoldProcessError(
          command: tryjobCommand,
          stdout: resultStdout,
          stderr: result.stderr.toString(),
          message: buf.toString(),
        );
      }
      // ... but we want to know about them anyway.
      // See https://github.com/flutter/flutter/issues/145219.
      // TODO(matanlurey): Update the documentation to reflect the new behavior.
      if (isUntriaged) {
        _stderr
          ..writeln('NOTE: Untriaged image detected in tryjob.')
          ..writeln('Triage should be required by the "Flutter Gold" check')
          ..writeln('stdout:\n$resultStdout');
      }
    }
  }

  List<String> _getMatchingArguments(
    String testName,
    int screenshotSize,
    int pixelDeltaThreshold,
    double differentPixelsRate,
  ) {
    // The algorithm to be used when matching images. The available options are:
    // - "fuzzy": Allows for customizing the thresholds of pixel differences.
    // - "sobel": Same as "fuzzy" but performs edge detection before performing
    //            a fuzzy match.
    const String algorithm = 'fuzzy';

    // The number of pixels in this image that are allowed to differ from the
    // baseline. It's okay for this to be a slightly high number like 10% of the
    // image size because those wrong pixels are constrained by
    // `pixelDeltaThreshold` below.
    final int maxDifferentPixels = (screenshotSize * differentPixelsRate).toInt();
    return <String>[
      '--add-test-optional-key', 'image_matching_algorithm:$algorithm',
      '--add-test-optional-key', 'fuzzy_max_different_pixels:$maxDifferentPixels',
      '--add-test-optional-key', 'fuzzy_pixel_delta_threshold:$pixelDeltaThreshold',
    ];
  }

  /// Returns the latest positive digest for the given test known to Skia Gold
  /// at head.
  Future<String?> getExpectationForTest(String testName) async {
    late String? expectation;
    final String traceID = getTraceID(testName);
    final Uri requestForExpectations = Uri.parse(
      '$_skiaGoldHost/json/v2/latestpositivedigest/$traceID'
    );
    late String rawResponse;
    try {
      final io.HttpClientRequest request = await httpClient.getUrl(requestForExpectations);
      final io.HttpClientResponse response = await request.close();
      rawResponse = await utf8.decodeStream(response);
      final dynamic jsonResponse = json.decode(rawResponse);
      if (jsonResponse is! Map<String, dynamic>) {
        throw const FormatException('Skia gold expectations do not match expected format.');
      }
      expectation = jsonResponse['digest'] as String?;
    } on FormatException catch (error) {
      _stderr.writeln(
        'Formatting error detected requesting expectations from Flutter Gold.\n'
        'error: $error\n'
        'url: $requestForExpectations\n'
        'response: $rawResponse'
      );
      rethrow;
    }
    return expectation;
  }

  /// Returns the current commit hash of the engine repository.
  Future<String> _getCurrentCommit() async {
    final String engineCheckout = _engineRoot.flutterDir.path;
    final io.ProcessResult revParse = await process.run(
      <String>['git', 'rev-parse', 'HEAD'],
      workingDirectory: engineCheckout,
    );
    if (revParse.exitCode != 0) {
      throw StateError('Current commit of the engine can not be found from path $engineCheckout.');
    }
    return (revParse.stdout as String).trim();
  }

  /// Returns a Map of key value pairs used to uniquely identify the
  /// configuration that generated the given golden file.
  ///
  /// Currently, the only key value pairs being tracked are the platform and
  /// browser the image was rendered on.
  Map<String, dynamic> _getKeys() {
    final Map<String, dynamic> initialKeys = <String, dynamic>{
      'CI': 'luci',
      'Platform': io.Platform.operatingSystem,
    };
    if (dimensions != null) {
      initialKeys.addAll(dimensions!);
    }
    return initialKeys;
  }

  /// Same as [_getKeys] but encodes it in a JSON string.
  String _getKeysJSON() {
    return json.encode(_getKeys());
  }

  /// Returns a list of arguments for initializing a tryjob based on the testing
  /// environment.
  List<String> _getCIArguments() {
    final String jobId = _environment['LOGDOG_STREAM_PREFIX']!.split('/').last;
    final List<String> refs = _environment['GOLD_TRYJOB']!.split('/');
    final String pullRequest = refs[refs.length - 2];

    return <String>[
      '--changelist', pullRequest,
      '--cis', 'buildbucket',
      '--jobid', jobId,
    ];
  }

  /// Returns a trace id based on the current testing environment to lookup
  /// the latest positive digest on Skia Gold with a hex-encoded md5 hash of
  /// the image keys.
  @visibleForTesting
  String getTraceID(String testName) {
    final Map<String, dynamic> keys = <String, dynamic>{
      ..._getKeys(),
      'name': testName,
      'source_type': _instance,
    };
    final String jsonTrace = json.encode(keys);
    final String md5Sum = md5.convert(utf8.encode(jsonTrace)).toString();
    return md5Sum;
  }
}
