// 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.

// We use `print` for logging here.
// ignore_for_file: avoid_print

/// @docImport 'dart:io';
library;

import 'dart:async' show Completer, FutureOr;
import 'dart:io' as io show HttpClient, OSError, SocketException;
import 'dart:ui' as ui;

import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:platform/platform.dart';
import 'package:process/process.dart';

import 'skia_client.dart';
export 'skia_client.dart';

// If you are here trying to figure out how to use golden files in the Flutter
// repo itself, consider reading this wiki page:
// https://github.com/flutter/flutter/blob/main/docs/contributing/testing/Writing-a-golden-file-test-for-package-flutter.md

// If you are trying to debug this package, you may like to use the golden test
// titled "Inconsequential golden test" in this file:
//   /packages/flutter/test/widgets/basic_test.dart

// TODO(ianh): sort the parameters and arguments in this file so they use a consistent order throughout.

const String _kFlutterRootKey = 'FLUTTER_ROOT';

bool _isMainBranch(String? branch) {
  return branch == 'main' || branch == 'master';
}

/// Main method that can be used in a `flutter_test_config.dart` file to set
/// [goldenFileComparator] to an instance of [FlutterGoldenFileComparator] that
/// works for the current test. _Which_ [FlutterGoldenFileComparator] is
/// instantiated is based on the current testing environment.
///
/// When set, the `namePrefix` is prepended to the names of all gold images.
///
/// This function assumes the [goldenFileComparator] has been set to a
/// [LocalFileComparator], which happens in the bootstrap code used when running
/// tests using `flutter test`. This should not be called when running a test
/// using `flutter run`, as in that environment, the [goldenFileComparator] is a
/// [TrivialComparator].
///
/// An [HttpClient] is created when this method is called. That client is used
/// to communicate with the Skia Gold servers. Any [HttpOverrides] set in this
/// will affect whether this is effective or not. For example, if the current
/// override provides a mock client that always fails, then all calls to gold
/// comparison functions will fail.
Future<void> testExecutable(FutureOr<void> Function() testMain, {String? namePrefix}) async {
  assert(
    goldenFileComparator is LocalFileComparator,
    'The flutter_goldens package should be used from a flutter_test_config.dart '
    'file, which is only invoked when using "flutter test". The "flutter test" '
    'bootstrap logic sets "goldenFileComparator" to a LocalFileComparator. It '
    'appears in this instance however that the "goldenFileComparator" is a '
    '${goldenFileComparator.runtimeType}.\n'
    'See also: https://flutter.dev/to/flutter-test-docs',
  );
  const Platform platform = LocalPlatform();
  const FileSystem fs = LocalFileSystem();
  const ProcessManager process = LocalProcessManager();
  final httpClient = io.HttpClient();
  if (FlutterPostSubmitFileComparator.isForEnvironment(platform)) {
    goldenFileComparator = await FlutterPostSubmitFileComparator.fromLocalFileComparator(
      localFileComparator: goldenFileComparator as LocalFileComparator,
      platform: platform,
      namePrefix: namePrefix,
      log: print,
      fs: fs,
      process: process,
      httpClient: httpClient,
    );
  } else if (FlutterPreSubmitFileComparator.isForEnvironment(platform)) {
    goldenFileComparator = await FlutterPreSubmitFileComparator.fromLocalFileComparator(
      localFileComparator: goldenFileComparator as LocalFileComparator,
      platform: platform,
      namePrefix: namePrefix,
      log: print,
      fs: fs,
      process: process,
      httpClient: httpClient,
    );
  } else if (FlutterSkippingFileComparator.isForEnvironment(platform)) {
    goldenFileComparator = FlutterSkippingFileComparator.fromLocalFileComparator(
      localFileComparator: goldenFileComparator as LocalFileComparator,
      'Golden file testing is not executed on LUCI environments outside of '
      'flutter, or in test shards that are not configured for using goldctl.',
      platform: platform,
      namePrefix: namePrefix,
      log: print,
      fs: fs,
      process: process,
      httpClient: httpClient,
    );
  } else {
    goldenFileComparator = await FlutterLocalFileComparator.fromLocalFileComparator(
      localFileComparator: goldenFileComparator as LocalFileComparator,
      platform: platform,
      log: print,
      fs: fs,
      process: process,
      httpClient: httpClient,
    );
  }
  await testMain();
}

/// Abstract base class golden file comparator specific to the `flutter/flutter`
/// repository.
///
/// Golden file testing for the `flutter/flutter` repository is handled by three
/// different [FlutterGoldenFileComparator]s, depending on the current testing
/// environment.
///
///   * The [FlutterPostSubmitFileComparator] is utilized during post-submit
///     testing, after a pull request has landed on the master branch. This
///     comparator uses the [SkiaGoldClient] and the `goldctl` tool to upload
///     tests to the [Flutter Gold dashboard](https://flutter-gold.skia.org).
///     Flutter Gold manages the master golden files for the `flutter/flutter`
///     repository.
///
///   * The [FlutterPreSubmitFileComparator] is utilized in pre-submit testing,
///     before a pull request lands on the master branch. This
///     comparator uses the [SkiaGoldClient] to execute tryjobs, allowing
///     contributors to view and check in visual differences before landing the
///     change.
///
///   * The [FlutterLocalFileComparator] is used for local development testing.
///     This comparator will use the [SkiaGoldClient] to request baseline images
///     from [Flutter Gold](https://flutter-gold.skia.org) and manually compare
///     pixels. If a difference is detected, this comparator will
///     generate failure output illustrating the found difference. If a baseline
///     is not found for a given test image, it will consider it a new test and
///     output the new image for verification.
///
///  The [FlutterSkippingFileComparator] is utilized to skip tests outside
///  of the appropriate environments described above. Currently, some Luci
///  environments do not execute golden file testing, and as such do not require
///  a comparator. This comparator is also used when an internet connection is
///  unavailable.
abstract class FlutterGoldenFileComparator extends GoldenFileComparator {
  /// Creates a [FlutterGoldenFileComparator] that will resolve golden file
  /// URIs relative to the specified [basedir], and retrieve golden baselines
  /// using the [skiaClient]. The [basedir] is used for writing and accessing
  /// information and files for interacting with the [skiaClient]. When testing
  /// locally, the [basedir] will also contain any diffs from failed tests, or
  /// goldens generated from newly introduced tests.
  @visibleForTesting
  FlutterGoldenFileComparator(
    this.basedir,
    this.skiaClient, {
    required this.fs,
    required this.platform,
    this.namePrefix,
    required this.log,
  });

  /// The directory to which golden file URIs will be resolved in [compare] and
  /// [update].
  final Uri basedir;

  /// A client for uploading image tests and making baseline requests to the
  /// Flutter Gold Dashboard.
  final SkiaGoldClient skiaClient;

  /// The file system used to perform file access.
  final FileSystem fs;

  /// The environment (current working directory, identity of the OS,
  /// environment variables, etc).
  final Platform platform;

  /// The prefix that is added to all golden names.
  final String? namePrefix;

  /// The logging function to use when reporting messages to the console.
  final LogCallback log;

  @override
  Future<void> update(Uri golden, Uint8List imageBytes) async {
    final File goldenFile = getGoldenFile(golden);
    await goldenFile.parent.create(recursive: true);
    await goldenFile.writeAsBytes(imageBytes, flush: true);
  }

  @override
  Uri getTestUri(Uri key, int? version) => key;

  /// Calculate the appropriate basedir for the current test context.
  ///
  /// The optional [suffix] argument is used by the
  /// [FlutterPostSubmitFileComparator] and the [FlutterPreSubmitFileComparator].
  /// These [FlutterGoldenFileComparator]s randomize their base directories to
  /// maintain thread safety while using the `goldctl` tool.
  @protected
  @visibleForTesting
  static Directory getBaseDirectory(
    LocalFileComparator defaultComparator, {
    required Platform platform,
    String? suffix,
    required FileSystem fs,
  }) {
    final Directory flutterRoot = fs.directory(platform.environment[_kFlutterRootKey]);
    final Directory comparisonRoot = switch (suffix) {
      null => flutterRoot.childDirectory(fs.path.join('bin', 'cache', 'pkg', 'skia_goldens')),
      _ => fs.systemTempDirectory.createTempSync(suffix),
    };

    final String testPath = fs.directory(defaultComparator.basedir).path;
    return comparisonRoot.childDirectory(fs.path.relative(testPath, from: flutterRoot.path));
  }

  /// Returns the golden [File] identified by the given [Uri].
  @protected
  File getGoldenFile(Uri uri) {
    final File goldenFile = fs.directory(basedir).childFile(fs.file(uri).path);
    return goldenFile;
  }

  /// Prepends the golden URL with the library name that encloses the current
  /// test.
  Uri _addPrefix(Uri golden) {
    // Ensure the Uri ends in .png as the SkiaClient expects
    assert(
      golden.toString().split('.').last == 'png',
      'Golden files in the Flutter framework must end with the file extension '
      '.png.',
    );
    return Uri.parse(
      <String>[
        ?namePrefix,
        basedir.pathSegments[basedir.pathSegments.length - 2],
        golden.toString(),
      ].join('.'),
    );
  }
}

/// A [FlutterGoldenFileComparator] for testing golden images with Skia Gold in
/// post-submit.
///
/// For testing across all platforms, the [SkiaGoldClient] is used to upload
/// images for framework-related golden tests and process results.
///
/// See also:
///
///  * [GoldenFileComparator], the abstract class that
///    [FlutterGoldenFileComparator] implements.
///  * [FlutterPreSubmitFileComparator], another
///    [FlutterGoldenFileComparator] that tests golden images before changes are
///    merged into the master branch.
///  * [FlutterLocalFileComparator], another
///    [FlutterGoldenFileComparator] that tests golden images locally on your
///    current machine.
class FlutterPostSubmitFileComparator extends FlutterGoldenFileComparator {
  /// Creates a [FlutterPostSubmitFileComparator] that will test golden file
  /// images against Skia Gold.
  ///
  /// The [fs] parameter is useful in tests, where the default
  /// file system can be replaced by mock instances.
  FlutterPostSubmitFileComparator(
    super.basedir,
    super.skiaClient, {
    required super.fs,
    required super.platform,
    super.namePrefix,
    required super.log,
  });

  /// Creates a new [FlutterPostSubmitFileComparator] that mirrors the relative
  /// path resolution of the provided `localFileComparator`.
  ///
  /// The [goldens] parameter is visible for testing purposes only.
  static Future<FlutterPostSubmitFileComparator> fromLocalFileComparator({
    SkiaGoldClient? goldens,
    required LocalFileComparator localFileComparator,
    required Platform platform,
    String? namePrefix,
    required LogCallback log,
    required FileSystem fs,
    required ProcessManager process,
    required io.HttpClient httpClient,
  }) async {
    final Directory baseDirectory = FlutterGoldenFileComparator.getBaseDirectory(
      localFileComparator,
      platform: platform,
      suffix: 'flutter_goldens_postsubmit.',
      fs: fs,
    );
    baseDirectory.createSync(recursive: true);

    goldens ??= SkiaGoldClient(
      baseDirectory,
      log: log,
      platform: platform,
      fs: fs,
      process: process,
      httpClient: httpClient,
    );
    await goldens.auth();
    return FlutterPostSubmitFileComparator(
      baseDirectory.uri,
      goldens,
      platform: platform,
      namePrefix: namePrefix,
      log: log,
      fs: fs,
    );
  }

  @override
  Future<bool> compare(Uint8List imageBytes, Uri golden) async {
    await skiaClient.imgtestInit();
    golden = _addPrefix(golden);
    await update(golden, imageBytes);
    final File goldenFile = getGoldenFile(golden);
    try {
      return await skiaClient.imgtestAdd(golden.path, goldenFile);
    } on SkiaException catch (e) {
      // Convert SkiaException -> TestFailure so that this class implements the
      // contract of GoldenFileComparator, and matchesGoldenFile() converts the
      // TestFailure into a standard reported test error (with a better stack
      // trace, for example).
      //
      // https://github.com/flutter/flutter/issues/162621
      throw TestFailure('$e');
    }
  }

  /// Decides based on the current environment if goldens tests should be
  /// executed through Skia Gold.
  static bool isForEnvironment(Platform platform) {
    final bool luciPostSubmit =
        platform.environment.containsKey('SWARMING_TASK_ID') &&
        platform.environment.containsKey('GOLDCTL')
        // Luci tryjob environments contain this value to inform the [FlutterPreSubmitComparator].
        &&
        !platform.environment.containsKey('GOLD_TRYJOB')
        // Only run on main branch.
        &&
        _isMainBranch(platform.environment['GIT_BRANCH']);
    return luciPostSubmit;
  }
}

/// A [FlutterGoldenFileComparator] for testing golden images before changes are
/// merged into the master branch. The comparator executes tryjobs using the
/// [SkiaGoldClient].
///
/// See also:
///
///  * [GoldenFileComparator], the abstract class that
///    [FlutterGoldenFileComparator] implements.
///  * [FlutterPostSubmitFileComparator], another
///    [FlutterGoldenFileComparator] that uploads tests to the Skia Gold
///    dashboard in post-submit.
///  * [FlutterLocalFileComparator], another
///    [FlutterGoldenFileComparator] that tests golden images locally on your
///    current machine.
class FlutterPreSubmitFileComparator extends FlutterGoldenFileComparator {
  /// Creates a [FlutterPreSubmitFileComparator] that will test golden file
  /// images against baselines requested from Flutter Gold.
  ///
  /// The [fs] parameter is useful in tests, where the default
  /// file system can be replaced by mock instances.
  FlutterPreSubmitFileComparator(
    super.basedir,
    super.skiaClient, {
    required super.fs,
    required super.platform,
    super.namePrefix,
    required super.log,
  });

  /// Creates a new [FlutterPreSubmitFileComparator] that mirrors the
  /// relative path resolution of the default [goldenFileComparator].
  ///
  /// The [goldens] parameter is visible for testing purposes only.
  static Future<FlutterGoldenFileComparator> fromLocalFileComparator({
    SkiaGoldClient? goldens,
    required LocalFileComparator localFileComparator,
    required Platform platform,
    Directory? testBasedir,
    String? namePrefix,
    required LogCallback log,
    required FileSystem fs,
    required ProcessManager process,
    required io.HttpClient httpClient,
  }) async {
    final Directory baseDirectory =
        testBasedir ??
        FlutterGoldenFileComparator.getBaseDirectory(
          localFileComparator,
          platform: platform,
          suffix: 'flutter_goldens_presubmit.',
          fs: fs,
        );

    if (!baseDirectory.existsSync()) {
      baseDirectory.createSync(recursive: true);
    }

    goldens ??= SkiaGoldClient(
      baseDirectory,
      platform: platform,
      log: log,
      fs: fs,
      process: process,
      httpClient: httpClient,
    );

    await goldens.auth();
    return FlutterPreSubmitFileComparator(
      baseDirectory.uri,
      goldens,
      platform: platform,
      namePrefix: namePrefix,
      log: log,
      fs: fs,
    );
  }

  @override
  Future<bool> compare(Uint8List imageBytes, Uri golden) async {
    await skiaClient.tryjobInit();
    golden = _addPrefix(golden);
    await update(golden, imageBytes);
    final File goldenFile = getGoldenFile(golden);

    await skiaClient.tryjobAdd(golden.path, goldenFile);

    // This will always return true since golden file test failures are managed
    // in pre-submit checks by the flutter-gold status check.
    return true;
  }

  /// Decides based on the current environment if goldens tests should be
  /// executed as pre-submit tests with Skia Gold.
  static bool isForEnvironment(Platform platform) {
    final bool luciPreSubmit =
        platform.environment.containsKey('SWARMING_TASK_ID') &&
        platform.environment.containsKey('GOLDCTL') &&
        platform.environment.containsKey('GOLD_TRYJOB')
        // Only run on the main branch
        &&
        _isMainBranch(platform.environment['GIT_BRANCH']);
    return luciPreSubmit;
  }
}

/// A [FlutterGoldenFileComparator] for testing conditions that do not execute
/// golden file tests.
///
/// Currently, this comparator is used on Luci environments when executing tests
/// outside of the flutter/flutter repository.
///
/// See also:
///
///  * [FlutterPostSubmitFileComparator], another [FlutterGoldenFileComparator]
///    that tests golden images through Skia Gold.
///  * [FlutterPreSubmitFileComparator], another
///    [FlutterGoldenFileComparator] that tests golden images before changes are
///    merged into the master branch.
///  * [FlutterLocalFileComparator], another
///    [FlutterGoldenFileComparator] that tests golden images locally on your
///    current machine.
class FlutterSkippingFileComparator extends FlutterGoldenFileComparator {
  /// Creates a [FlutterSkippingFileComparator] that will skip tests that
  /// are not in the right environment for golden file testing.
  FlutterSkippingFileComparator(
    super.basedir,
    super.skiaClient,
    this.reason, {
    super.namePrefix,
    required super.platform,
    required super.log,
    required super.fs,
  });

  /// Describes the reason for using the [FlutterSkippingFileComparator].
  final String reason;

  /// Creates a new [FlutterSkippingFileComparator] that mirrors the
  /// relative path resolution of the given [localFileComparator].
  static FlutterSkippingFileComparator fromLocalFileComparator(
    String reason, {
    required LocalFileComparator localFileComparator,
    String? namePrefix,
    required Platform platform,
    required LogCallback log,
    required FileSystem fs,
    required ProcessManager process,
    required io.HttpClient httpClient,
  }) {
    final Uri basedir = localFileComparator.basedir;
    final skiaClient = SkiaGoldClient(
      fs.directory(basedir),
      platform: platform,
      log: log,
      fs: fs,
      process: process,
      httpClient: httpClient,
    );
    return FlutterSkippingFileComparator(
      basedir,
      skiaClient,
      reason,
      namePrefix: namePrefix,
      platform: platform,
      log: log,
      fs: fs,
    );
  }

  @override
  Future<bool> compare(Uint8List imageBytes, Uri golden) async {
    log('Skipping "$golden" test: $reason');
    return true;
  }

  @override
  Future<void> update(Uri golden, Uint8List imageBytes) async {}

  /// Decides, based on the current environment, if this comparator should be
  /// used.
  ///
  /// If we are in a CI environment, i.e. LUCI, but are not using the other
  /// comparators, we skip. Otherwise we would fallback to the local comparator,
  /// for which failures cannot be resolved in a CI environment.
  static bool isForEnvironment(Platform platform) {
    return platform.environment.containsKey('SWARMING_TASK_ID');
  }
}

/// A [FlutterGoldenFileComparator] for testing golden images locally on your
/// current machine.
///
/// This comparator utilizes the [SkiaGoldClient] to request baseline images for
/// the given device under test for comparison. This comparator is initialized
/// when conditions for all other [FlutterGoldenFileComparator]s have not been
/// met, see the `isForEnvironment` method for each one listed below.
///
/// The [FlutterLocalFileComparator] is intended to run on local machines and
/// serve as a smoke test during development. As such, it will not be able to
/// detect unintended changes on environments other than the currently executing
/// machine, until they are tested using the [FlutterPreSubmitFileComparator].
///
/// See also:
///
///  * [GoldenFileComparator], the abstract class that
///    [FlutterGoldenFileComparator] implements.
///  * [FlutterPostSubmitFileComparator], another
///    [FlutterGoldenFileComparator] that uploads tests to the Skia Gold
///    dashboard.
///  * [FlutterPreSubmitFileComparator], another
///    [FlutterGoldenFileComparator] that tests golden images before changes are
///    merged into the master branch.
///  * [FlutterSkippingFileComparator], another
///    [FlutterGoldenFileComparator] that controls post-submit testing
///    conditions that do not execute golden file tests.
class FlutterLocalFileComparator extends FlutterGoldenFileComparator with LocalComparisonOutput {
  /// Creates a [FlutterLocalFileComparator] that will test golden file
  /// images against baselines requested from Flutter Gold.
  ///
  /// The [fs] parameter is useful in tests, where the default
  /// file system can be replaced by mock instances.
  FlutterLocalFileComparator(
    super.basedir,
    super.skiaClient, {
    required super.fs,
    required super.platform,
    required super.log,
  });

  /// Creates a new [FlutterLocalFileComparator] that mirrors the
  /// relative path resolution of the given [localFileComparator].
  ///
  /// The [goldens] and [baseDirectory] parameters are
  /// visible for testing purposes only.
  static Future<FlutterGoldenFileComparator> fromLocalFileComparator({
    SkiaGoldClient? goldens,
    required LocalFileComparator localFileComparator,
    required Platform platform,
    Directory? baseDirectory,
    required LogCallback log,
    required FileSystem fs,
    required ProcessManager process,
    required io.HttpClient httpClient,
  }) async {
    baseDirectory ??= FlutterGoldenFileComparator.getBaseDirectory(
      localFileComparator,
      platform: platform,
      fs: fs,
    );

    if (!baseDirectory.existsSync()) {
      baseDirectory.createSync(recursive: true);
    }

    goldens ??= SkiaGoldClient(
      baseDirectory,
      platform: platform,
      log: log,
      fs: fs,
      process: process,
      httpClient: httpClient,
    );
    try {
      // Check if we can reach Gold.
      await goldens.getExpectationForTest('');
    } on io.OSError catch (_) {
      return FlutterSkippingFileComparator(
        baseDirectory.uri,
        goldens,
        'OSError occurred, could not reach Gold. '
        'Switching to FlutterSkippingGoldenFileComparator.',
        platform: platform,
        log: log,
        fs: fs,
      );
    } on io.SocketException catch (_) {
      return FlutterSkippingFileComparator(
        baseDirectory.uri,
        goldens,
        'SocketException occurred, could not reach Gold. '
        'Switching to FlutterSkippingGoldenFileComparator.',
        platform: platform,
        log: log,
        fs: fs,
      );
    } on FormatException catch (_) {
      return FlutterSkippingFileComparator(
        baseDirectory.uri,
        goldens,
        'FormatException occurred, could not reach Gold. '
        'Switching to FlutterSkippingGoldenFileComparator.',
        platform: platform,
        log: log,
        fs: fs,
      );
    }

    return FlutterLocalFileComparator(
      baseDirectory.uri,
      goldens,
      platform: platform,
      log: log,
      fs: fs,
    );
  }

  @override
  Future<bool> compare(Uint8List imageBytes, Uri golden) async {
    golden = _addPrefix(golden);
    final String testName = skiaClient.cleanTestName(golden.path);
    final String? testExpectation = await skiaClient.getExpectationForTest(testName);

    if (testExpectation == null || testExpectation.isEmpty) {
      log(
        'No expectations provided by Skia Gold for test: $golden. '
        'This may be a new test. If this is an unexpected result, check '
        'https://flutter-gold.skia.org.\n'
        'Validate image output found at $basedir',
      );
      await update(golden, imageBytes);
      return true;
    }

    final List<int> goldenBytes = await skiaClient.getImageBytes(testExpectation);

    if (skiaClient.isBrowserTest) {
      return _fuzzyCompareWeb(
        actualBytes: imageBytes,
        expectedBytes: goldenBytes,
        golden: golden,
        testName: testName,
      );
    }

    final ComparisonResult result = await GoldenFileComparator.compareLists(
      imageBytes,
      goldenBytes,
    );

    if (result.passed) {
      result.dispose();
      return true;
    }

    final String error = await generateFailureOutput(result, golden, basedir);
    result.dispose();
    throw FlutterError(error);
  }

  /// Computes the Manhattan distance (L1 norm) between two RGBA pixels.
  ///
  /// Calculates `|r1 - r2| + |g1 - g2| + |b1 - b2| + |a1 - a2|`. The result
  /// ranges from `0` (identical colors) to `1020` (maximum difference, e.g.
  /// solid black vs solid white with full opacity difference).
  static int _colorDelta(int r1, int g1, int b1, int a1, int r2, int g2, int b2, int a2) {
    return (r1 - r2).abs() + (g1 - g2).abs() + (b1 - b2).abs() + (a1 - a2).abs();
  }

  /// Converts a raw RGBA8888 byte buffer of dimension [width] x [height] into
  /// an uncompressed [ui.Image].
  static Future<ui.Image> _createImageFromPixels(ByteData bytes, int width, int height) {
    final completer = Completer<ui.Image>();
    ui.decodeImageFromPixels(
      bytes.buffer.asUint8List(),
      width,
      height,
      ui.PixelFormat.rgba8888,
      completer.complete,
    );
    return completer.future;
  }

  /// Performs a tolerance-aware fuzzy comparison between [actualBytes] and
  /// [expectedBytes] for web browser golden tests.
  ///
  /// Browser raster engines, font renderers, and GPU backends exhibit slight
  /// cross-platform rasterization variations (e.g. subpixel antialiasing and
  /// glyph rounding). To accommodate these without false positives:
  ///
  /// 1. Pixels whose Manhattan color delta is within `maxColorDelta` pass.
  /// 2. If the direct pixel mismatches, a 3x3 neighborhood search in the expected
  ///    image is performed to allow for 1-pixel subpixel layout shifts.
  /// 3. The test passes if the overall differing pixel ratio is <= `maxDifferentPixelsRate`.
  ///
  /// If the comparison fails, failure artifacts (`actual.png`, `expected.png`,
  /// `diff.png`) are written to disk and a [FlutterError] is thrown.
  Future<bool> _fuzzyCompareWeb({
    required Uint8List actualBytes,
    required List<int> expectedBytes,
    required Uri golden,
    required String testName,
  }) async {
    if (listEquals(actualBytes, expectedBytes)) {
      return true;
    }

    final ui.Codec actualCodec = await ui.instantiateImageCodec(actualBytes);
    final ui.Image actualImage = (await actualCodec.getNextFrame()).image;
    actualCodec.dispose();

    final ui.Codec expectedCodec = await ui.instantiateImageCodec(
      Uint8List.fromList(expectedBytes),
    );
    final ui.Image expectedImage = (await expectedCodec.getNextFrame()).image;
    expectedCodec.dispose();

    ui.Image? diffImage;
    try {
      final ByteData? actualRgba = await actualImage.toByteData();
      final ByteData? expectedRgba = await expectedImage.toByteData();

      final int width = actualImage.width;
      final int height = actualImage.height;
      final int expectedWidth = expectedImage.width;
      final int expectedHeight = expectedImage.height;

      // Maximum allowed Manhattan color delta across RGBA channels (7 per RGB channel = 21)
      // to tolerate subtle antialiasing differences.
      const int maxColorDelta = 7 * 3;
      // Maximum proportion of differing pixels allowed (10%) to absorb perimeter antialiasing fringes.
      const maxDifferentPixelsRate = 0.1;

      if (width != expectedWidth ||
          height != expectedHeight ||
          actualRgba == null ||
          expectedRgba == null) {
        final diffBytes = ByteData(width * height * 4);
        for (var i = 0; i < width * height * 4; i += 4) {
          diffBytes.setUint8(i, 255);
          diffBytes.setUint8(i + 1, 0);
          diffBytes.setUint8(i + 2, 127);
          diffBytes.setUint8(i + 3, 255);
        }
        diffImage = await _createImageFromPixels(diffBytes, width, height);
        final ByteData? diffPngData = await diffImage.toByteData(format: ui.ImageByteFormat.png);
        final Uint8List diffPngBytes = diffPngData!.buffer.asUint8List();

        await _writeFailureAndThrow(
          golden: golden,
          testName: testName,
          actualBytes: actualBytes,
          expectedBytes: Uint8List.fromList(expectedBytes),
          diffPngBytes: diffPngBytes,
          diffPixelCount: width * height,
          totalPixels: width * height,
          maxDifferentPixelsRate: maxDifferentPixelsRate,
          customMessage:
              'Image dimensions do not match (actual: ${width}x$height, expected: ${expectedWidth}x$expectedHeight).',
        );
        return false;
      }

      final Uint8List actualPixels = actualRgba.buffer.asUint8List(
        actualRgba.offsetInBytes,
        actualRgba.lengthInBytes,
      );
      final Uint8List expectedPixels = expectedRgba.buffer.asUint8List(
        expectedRgba.offsetInBytes,
        expectedRgba.lengthInBytes,
      );

      final int totalPixels = width * height;
      var diffPixelCount = 0;
      final diffBytes = ByteData(width * height * 4);

      for (var y = 0; y < height; y += 1) {
        for (var x = 0; x < width; x += 1) {
          final int offset = (y * width + x) * 4;
          final int r1 = actualPixels[offset];
          final int g1 = actualPixels[offset + 1];
          final int b1 = actualPixels[offset + 2];
          final int a1 = actualPixels[offset + 3];

          var pixelMatched = false;

          // Check direct pixel first
          final int r2 = expectedPixels[offset];
          final int g2 = expectedPixels[offset + 1];
          final int b2 = expectedPixels[offset + 2];
          final int a2 = expectedPixels[offset + 3];
          if (_colorDelta(r1, g1, b1, a1, r2, g2, b2, a2) <= maxColorDelta) {
            pixelMatched = true;
          } else {
            // Search 3x3 neighborhood in expected image
            neighborhoodSearch:
            for (var dy = -1; dy <= 1; dy += 1) {
              final int ny = y + dy;
              if (ny < 0 || ny >= height) {
                continue;
              }
              for (var dx = -1; dx <= 1; dx += 1) {
                final int nx = x + dx;
                if (nx < 0 || nx >= width) {
                  continue;
                }
                final int neighborOffset = (ny * width + nx) * 4;
                final int nr2 = expectedPixels[neighborOffset];
                final int ng2 = expectedPixels[neighborOffset + 1];
                final int nb2 = expectedPixels[neighborOffset + 2];
                final int na2 = expectedPixels[neighborOffset + 3];
                if (_colorDelta(r1, g1, b1, a1, nr2, ng2, nb2, na2) <= maxColorDelta) {
                  pixelMatched = true;
                  break neighborhoodSearch;
                }
              }
            }
          }

          if (pixelMatched) {
            diffBytes.setUint8(offset, r1);
            diffBytes.setUint8(offset + 1, g1);
            diffBytes.setUint8(offset + 2, b1);
            diffBytes.setUint8(offset + 3, a1);
          } else {
            diffPixelCount += 1;
            // Highlight mismatched pixels with bright Magenta (#FF007F) for clear visual diffing.
            diffBytes.setUint8(offset, 255);
            diffBytes.setUint8(offset + 1, 0);
            diffBytes.setUint8(offset + 2, 127);
            diffBytes.setUint8(offset + 3, 255);
          }
        }
      }

      final double diffRate = totalPixels == 0 ? 0.0 : diffPixelCount / totalPixels;
      if (diffRate <= maxDifferentPixelsRate) {
        return true;
      }

      diffImage = await _createImageFromPixels(diffBytes, width, height);
      final ByteData? diffPngData = await diffImage.toByteData(format: ui.ImageByteFormat.png);
      final Uint8List diffPngBytes = diffPngData!.buffer.asUint8List();

      await _writeFailureAndThrow(
        golden: golden,
        testName: testName,
        actualBytes: actualBytes,
        expectedBytes: Uint8List.fromList(expectedBytes),
        diffPngBytes: diffPngBytes,
        diffPixelCount: diffPixelCount,
        totalPixels: totalPixels,
        maxDifferentPixelsRate: maxDifferentPixelsRate,
      );
      return false;
    } finally {
      actualImage.dispose();
      expectedImage.dispose();
      diffImage?.dispose();
    }
  }

  /// Writes failure artifacts (`actual.png`, `expected.png`, `diff.png`) to the
  /// golden cache failure directory and throws a formatted [FlutterError].
  Future<void> _writeFailureAndThrow({
    required Uri golden,
    required String testName,
    required Uint8List actualBytes,
    required Uint8List expectedBytes,
    required Uint8List diffPngBytes,
    required int diffPixelCount,
    required int totalPixels,
    required double maxDifferentPixelsRate,
    String? customMessage,
  }) async {
    final Directory failureDir;
    if (platform.environment.containsKey(_kFlutterRootKey)) {
      failureDir = fs
          .directory(platform.environment[_kFlutterRootKey])
          .childDirectory('.dart_tool')
          .childDirectory('flutter_goldens_cache')
          .childDirectory('failures')
          .childDirectory(testName);
    } else {
      failureDir = fs.directory(basedir).childDirectory('failures').childDirectory(testName);
    }

    failureDir.createSync(recursive: true);
    final File actualFile = failureDir.childFile('actual.png');
    final File expectedFile = failureDir.childFile('expected.png');
    final File diffFile = failureDir.childFile('diff.png');

    actualFile.writeAsBytesSync(actualBytes, flush: true);
    expectedFile.writeAsBytesSync(expectedBytes, flush: true);
    diffFile.writeAsBytesSync(diffPngBytes, flush: true);

    final double diffRate = totalPixels == 0 ? 0.0 : diffPixelCount / totalPixels;
    final error =
        'Golden comparison failed for test "$golden".\n'
        '${customMessage != null ? '$customMessage\n' : ''}'
        'Pixel difference: ${(diffRate * 100).toStringAsFixed(2)}% ($diffPixelCount / $totalPixels pixels differed, max allowed: ${(maxDifferentPixelsRate * 100).toStringAsFixed(1)}%).\n'
        'Failure artifacts written to:\n'
        '  actual:   ${actualFile.uri}\n'
        '  expected: ${expectedFile.uri}\n'
        '  diff:     ${diffFile.uri}';
    throw FlutterError(error);
  }
}
