// 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 'package:flutter_tools/src/android/android_workflow.dart';
import 'package:flutter_tools/src/base/bot_detector.dart';
import 'package:flutter_tools/src/base/config.dart';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/process.dart';
import 'package:flutter_tools/src/base/signals.dart';
import 'package:flutter_tools/src/base/template.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:flutter_tools/src/base/version.dart';
import 'package:flutter_tools/src/build_system/build_targets.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/context_runner.dart';
import 'package:flutter_tools/src/dart/pub.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/doctor_validator.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/ios/plist_parser.dart';
import 'package:flutter_tools/src/ios/simulators.dart';
import 'package:flutter_tools/src/ios/xcodeproj.dart';
import 'package:flutter_tools/src/isolated/build_targets.dart';
import 'package:flutter_tools/src/isolated/mustache_template.dart';
import 'package:flutter_tools/src/persistent_tool_state.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/crash_reporting.dart';
import 'package:flutter_tools/src/version.dart';
import 'package:meta/meta.dart';
import 'package:test/fake.dart';
import 'package:unified_analytics/unified_analytics.dart';

import 'common.dart';
import 'fake_http_client.dart';
import 'fake_process_manager.dart';
import 'fakes.dart';
import 'throwing_pub.dart';

export 'package:flutter_tools/src/base/context.dart' show Generator;

export 'fake_process_manager.dart' show FakeCommand, FakeProcessManager, ProcessManager;

/// Return the test logger. This assumes that the current Logger is a BufferLogger.
BufferLogger get testLogger => context.get<Logger>()! as BufferLogger;

FakeDeviceManager get testDeviceManager => context.get<DeviceManager>()! as FakeDeviceManager;

@isTest
void testUsingContext(
  String description,
  dynamic Function() testMethod, {
  Map<Type, Generator> overrides = const <Type, Generator>{},
  bool initializeFlutterRoot = true,
  String? testOn,
  bool?
  skip, // should default to `false`, but https://github.com/dart-lang/test/issues/545 doesn't allow this
}) {
  if (overrides[FileSystem] != null && overrides[ProcessManager] == null) {
    fail(
      'If you override the FileSystem context you must also provide a ProcessManager, '
      'otherwise the processes you launch will not be dealing with the same file system '
      'that you are dealing with in your test.',
    );
  }
  if (overrides.containsKey(ProcessUtils)) {
    fail('Do not inject ProcessUtils for testing, use ProcessManager instead.');
  }

  // Ensure we don't rely on the default [Config] constructor which will
  // leak a sticky $HOME/.flutter_settings behind!
  Directory? configDir;
  tearDown(() {
    if (configDir != null) {
      tryToDelete(configDir!);
      configDir = null;
    }
  });
  Config buildConfig(FileSystem fs) {
    configDir ??= globals.fs.systemTempDirectory.createTempSync('flutter_config_dir_test.');
    return Config.test(name: Config.kFlutterSettings, directory: configDir, logger: globals.logger);
  }

  PersistentToolState buildPersistentToolState(FileSystem fs) {
    configDir ??= globals.fs.systemTempDirectory.createTempSync('flutter_config_dir_test.');
    return PersistentToolState.test(directory: configDir!, logger: globals.logger);
  }

  test(
    description,
    () async {
      await runInContext<dynamic>(
        () {
          return context.run<dynamic>(
            name: 'mocks',
            overrides: <Type, Generator>{
              AnsiTerminal: () => AnsiTerminal(platform: globals.platform, stdio: globals.stdio),
              Config: () => buildConfig(globals.fs),
              DeviceManager: () => FakeDeviceManager(),
              Doctor: () => FakeDoctor(globals.logger),
              FlutterVersion: () => FakeFlutterVersion(),
              HttpClient: () => FakeHttpClient.any(),
              IOSSimulatorUtils: () => const NoopIOSSimulatorUtils(),
              OutputPreferences: () => OutputPreferences.test(),
              Logger: () => BufferLogger.test(outputPreferences: context.get<OutputPreferences>()),
              OperatingSystemUtils: () => FakeOperatingSystemUtils(),
              PersistentToolState: () => buildPersistentToolState(globals.fs),
              XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(),
              FileSystem: () => LocalFileSystemBlockingSetCurrentDirectory(),
              PlistParser: () => FakePlistParser(),
              Signals: () => FakeSignals(),
              Pub: () => const ThrowingPub(), // prevent accidentally using pub.
              CrashReporter: () => const NoopCrashReporter(),
              TemplateRenderer: () => const MustacheTemplateRenderer(),
              BuildTargets: () => const BuildTargetsImpl(),
              Analytics: () => const NoOpAnalytics(),
              Stdio: () => FakeStdio(),
            },
            body: () {
              // To catch all errors thrown by the test, even uncaught async errors, we use a zone.
              //
              // Zones introduce their own event loop, so we do not await futures created inside
              // the zone from outside the zone. Instead, we create a Completer outside the zone,
              // and have the test complete it when the test ends (in success or failure), and we
              // await that.
              final completer = Completer<void>();
              runZonedGuarded<Future<dynamic>>(
                () async {
                  try {
                    return await context.run<dynamic>(
                      // Apply the overrides to the test context in the zone since their
                      // instantiation may reference items already stored on the context.
                      overrides: overrides,
                      name: 'test-specific overrides',
                      body: () async {
                        if (initializeFlutterRoot) {
                          // Provide a sane default for the flutterRoot directory. Individual
                          // tests can override this either in the test or during setup.
                          Cache.flutterRoot ??= getFlutterRoot();
                        }
                        return await testMethod();
                      },
                    );
                  } finally {
                    // We do not need a catch { ... } block because the error zone
                    // will catch all errors and send them to the completer below.
                    //
                    // See https://github.com/flutter/flutter/pull/141821/files#r1462288131.
                    if (!completer.isCompleted) {
                      completer.complete();
                    }
                  }
                },
                (Object error, StackTrace stackTrace) {
                  // When things fail, it's ok to print to the console!
                  print(error); // ignore: avoid_print
                  print(stackTrace); // ignore: avoid_print
                  _printBufferedErrors(context);
                  if (!completer.isCompleted) {
                    completer.completeError(error, stackTrace);
                  }
                  throw error; //ignore: only_throw_errors
                },
              );
              return completer.future;
            },
          );
        },
        overrides: <Type, Generator>{
          // This has to go here so that runInContext will pick it up when it tries
          // to do bot detection before running the closure. This is important
          // because the test may be giving us a fake HttpClientFactory, which may
          // throw in unexpected/abnormal ways.
          // If a test needs a BotDetector that does not always return true, it
          // can provide the AlwaysFalseBotDetector in the overrides, or its own
          // BotDetector implementation in the overrides.
          BotDetector: overrides[BotDetector] ?? () => const FakeBotDetector(true),
        },
      );
    },
    testOn: testOn,
    skip: skip,
  );
  // We don't support "timeout"; see ../../dart_test.yaml which
  // configures all tests to have a 15 minute timeout which should
  // definitely be enough.
}

void _printBufferedErrors(AppContext testContext) {
  if (testContext.get<Logger>() is BufferLogger) {
    final bufferLogger = testContext.get<Logger>()! as BufferLogger;
    if (bufferLogger.errorText.isNotEmpty) {
      // This is where the logger outputting errors is implemented, so it has
      // to use `print`.
      print(bufferLogger.errorText); // ignore: avoid_print
    }
    bufferLogger.clear();
  }
}

class FakeDeviceManager implements DeviceManager {
  List<Device> attachedDevices = <Device>[];
  List<Device> wirelessDevices = <Device>[];

  String? _specifiedDeviceId;

  @override
  String? get specifiedDeviceId {
    if (_specifiedDeviceId == null || _specifiedDeviceId == 'all') {
      return null;
    }
    return _specifiedDeviceId;
  }

  @override
  void stopExtendedWirelessDeviceDiscoverers() {}

  @override
  set specifiedDeviceId(String? id) {
    _specifiedDeviceId = id;
  }

  @override
  bool get hasSpecifiedDeviceId => specifiedDeviceId != null;

  @override
  bool get hasSpecifiedAllDevices {
    return _specifiedDeviceId != null && _specifiedDeviceId == 'all';
  }

  @override
  Future<List<Device>> getAllDevices({DeviceDiscoveryFilter? filter}) async =>
      filteredDevices(filter);

  @override
  Future<List<Device>> refreshAllDevices({
    Duration? timeout,
    DeviceDiscoveryFilter? filter,
  }) async => filteredDevices(filter);

  @override
  Future<List<Device>> refreshExtendedWirelessDeviceDiscoverers({
    Duration? timeout,
    DeviceDiscoveryFilter? filter,
  }) async => filteredDevices(filter);

  @override
  Future<List<Device>> getDevicesById(
    String deviceId, {
    DeviceDiscoveryFilter? filter,
    bool waitForDeviceToConnect = false,
  }) async {
    return filteredDevices(filter).where((Device device) {
      return device.id == deviceId || device.id.startsWith(deviceId);
    }).toList();
  }

  @override
  Future<List<Device>> getDevices({
    DeviceDiscoveryFilter? filter,
    bool waitForDeviceToConnect = false,
  }) {
    return hasSpecifiedDeviceId
        ? getDevicesById(specifiedDeviceId!, filter: filter)
        : getAllDevices(filter: filter);
  }

  void addAttachedDevice(Device device) => attachedDevices.add(device);
  void addWirelessDevice(Device device) => wirelessDevices.add(device);

  @override
  bool get canListAnything => true;

  @override
  Future<List<String>> getDeviceDiagnostics() async => <String>[];

  @override
  List<DeviceDiscovery> get deviceDiscoverers => <DeviceDiscovery>[];

  @override
  DeviceDiscoverySupportFilter deviceSupportFilter({
    bool includeDevicesUnsupportedByProject = false,
    FlutterProject? flutterProject,
  }) {
    return TestDeviceDiscoverySupportFilter();
  }

  @override
  Device? getSingleEphemeralDevice(List<Device> devices) => null;

  List<Device> filteredDevices(DeviceDiscoveryFilter? filter) {
    return switch (filter?.deviceConnectionInterface) {
      DeviceConnectionInterface.attached => attachedDevices,
      DeviceConnectionInterface.wireless => wirelessDevices,
      null => attachedDevices + wirelessDevices,
    };
  }
}

class TestDeviceDiscoverySupportFilter extends Fake implements DeviceDiscoverySupportFilter {
  TestDeviceDiscoverySupportFilter();
}

class FakeAndroidLicenseValidator extends Fake implements AndroidLicenseValidator {
  @override
  Future<LicensesAccepted> get licensesAccepted async => LicensesAccepted.all;
}

class FakeDoctor extends Doctor {
  FakeDoctor(Logger logger, {super.clock = const SystemClock()}) : super(logger: logger);

  // True for testing.
  @override
  bool get canListAnything => true;

  // True for testing.
  @override
  bool get canLaunchAnything => true;

  @override
  /// Replaces the android workflow with a version that overrides licensesAccepted,
  /// to prevent individual tests from having to mock out the process for
  /// the Doctor.
  List<DoctorValidator> get validators {
    final List<DoctorValidator> superValidators = super.validators;
    return superValidators.map<DoctorValidator>((DoctorValidator v) {
      if (v is AndroidLicenseValidator) {
        return FakeAndroidLicenseValidator();
      }
      return v;
    }).toList();
  }
}

class NoopIOSSimulatorUtils implements IOSSimulatorUtils {
  const NoopIOSSimulatorUtils();

  @override
  Future<List<IOSSimulator>> getAttachedDevices() async => <IOSSimulator>[];

  @override
  Future<List<IOSSimulatorRuntime>> getAvailableIOSRuntimes() async => <IOSSimulatorRuntime>[];
}

class FakeXcodeProjectInterpreter implements XcodeProjectInterpreter {
  FakeXcodeProjectInterpreter({
    bool isInstalled = true,
    String? versionText = 'Xcode 15',
    Version? version = const Version.withText(15, 0, 0, '15.0.0'),
    String? build = '15A240D',
  }) : _isInstalled = isInstalled,
       _versionText = versionText,
       _version = version,
       _build = build;

  final bool _isInstalled;
  final String? _versionText;
  final Version? _version;
  final String? _build;

  @override
  bool get isInstalled => _isInstalled;

  @override
  String? get versionText => _versionText;

  @override
  Version? get version => _version;

  @override
  String? get build => _build;

  @override
  Future<Map<String, String>> getBuildSettings(
    XcodeBasedProject xcodeProject, {
    required XcodeProjectBuildContext buildContext,
    Duration timeout = const Duration(minutes: 1),
  }) async {
    return <String, String>{};
  }

  @override
  Future<String> pluginsBuildSettingsOutput(
    Directory podXcodeProject, {
    Duration timeout = const Duration(minutes: 1),
  }) async {
    return '';
  }

  @override
  Future<void> cleanWorkspace(
    XcodeBasedProject xcodeProject,
    String workspacePath,
    String scheme, {
    required Directory buildDirectory,
    bool verbose = false,
  }) async {}

  @override
  Future<XcodeProjectInfo?> getInfo(
    XcodeBasedProject xcodeProject, {
    String? projectFilename,
    required Directory buildDirectory,
  }) async {
    return XcodeProjectInfo(<String>['Runner'], <String>['Debug', 'Release'], <String>[
      'Runner',
    ], BufferLogger.test());
  }

  @override
  List<String> xcrunCommand() => <String>['xcrun'];

  @override
  Future<void> prefetchSwiftPackagesForProject(
    XcodeBasedProject xcodeProject, {
    required Directory buildDirectory,
  }) async {}

  @override
  Future<List<String>> fetchDependenciesAndGenerateXcodebuildArgs(
    XcodeBasedProject xcodeProject,
    Directory buildDirectory, {
    bool skipPackageValidation = true,
  }) async {
    return <String>['xcrun', 'xcodebuild'];
  }

  @override
  String swiftPackageCachePath(Directory buildDirectory) {
    return '';
  }
}

/// Prevent test crashes from being reported to the crash backend.
class NoopCrashReporter implements CrashReporter {
  const NoopCrashReporter();

  @override
  Future<void> informUser(CrashDetails details, File crashFile) async {}
}

class LocalFileSystemBlockingSetCurrentDirectory extends LocalFileSystem {
  // Use [FakeSignals] so developers running the test suite can kill the test
  // runner.
  LocalFileSystemBlockingSetCurrentDirectory() : super.test(signals: FakeSignals());

  @override
  set currentDirectory(dynamic value) {
    throw Exception(
      'globals.fs.currentDirectory should not be set on the local file system during '
      'tests as this can cause race conditions with concurrent tests. '
      'Consider using a MemoryFileSystem for testing if possible or refactor '
      'code to not require setting globals.fs.currentDirectory.',
    );
  }
}

class FakeSignals implements Signals {
  @override
  Object addHandler(ProcessSignal signal, SignalHandler handler) {
    return const Object();
  }

  @override
  Future<bool> removeHandler(ProcessSignal signal, Object token) async {
    return true;
  }

  @override
  Stream<Object> get errors => const Stream<Object>.empty();
}
