// 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:io' as io;

import 'package:fake_async/fake_async.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/base/async_guard.dart';
import 'package:flutter_tools/src/base/common.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/platform.dart';
import 'package:flutter_tools/src/base/signals.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/drive.dart';
import 'package:flutter_tools/src/dart/pub.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/drive/drive_service.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:package_config/package_config.dart';
import 'package:test/fake.dart';

import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/test_flutter_command_runner.dart';

void main() {
  late FileSystem fileSystem;
  late BufferLogger logger;
  late Platform platform;
  late FakeDeviceManager fakeDeviceManager;
  late Signals signals;

  setUp(() {
    fileSystem = MemoryFileSystem.test();
    logger = BufferLogger.test();
    platform = FakePlatform();
    fakeDeviceManager = FakeDeviceManager();
    signals = FakeSignals();
  });

  setUpAll(() {
    Cache.disableLocking();
  });

  tearDownAll(() {
    Cache.enableLocking();
  });

  testUsingContext('warns if screenshot is not supported but continues test', () async {
    final DriveCommand command = DriveCommand(
      fileSystem: fileSystem,
      logger: logger,
      platform: platform,
      signals: signals,
    );
    fileSystem.file('lib/main.dart').createSync(recursive: true);
    fileSystem.file('test_driver/main_test.dart').createSync(recursive: true);
    fileSystem.file('pubspec.yaml').createSync();
    fileSystem.directory('drive_screenshots').createSync();

    final Device screenshotDevice = ThrowingScreenshotDevice()
      ..supportsScreenshot = false;
    fakeDeviceManager.devices = <Device>[screenshotDevice];

    await expectLater(() => createTestCommandRunner(command).run(
      <String>[
        'drive',
        '--no-pub',
        '-d',
        screenshotDevice.id,
        '--screenshot',
        'drive_screenshots',
      ]),
      throwsToolExit(message: 'cannot start app'),
    );

    expect(logger.errorText, contains('Screenshot not supported for FakeDevice'));
    expect(logger.statusText, isEmpty);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => FakeProcessManager.any(),
    Pub: () => FakePub(),
    DeviceManager: () => fakeDeviceManager,
  });

  testUsingContext('takes screenshot and rethrows on drive exception', () async {
    final DriveCommand command = DriveCommand(
      fileSystem: fileSystem,
      logger: logger,
      platform: platform,
      signals: signals,
    );
    fileSystem.file('lib/main.dart').createSync(recursive: true);
    fileSystem.file('test_driver/main_test.dart').createSync(recursive: true);
    fileSystem.file('pubspec.yaml').createSync();
    fileSystem.directory('drive_screenshots').createSync();

    final Device screenshotDevice = ThrowingScreenshotDevice();
    fakeDeviceManager.devices = <Device>[screenshotDevice];

    await expectLater(() => createTestCommandRunner(command).run(
      <String>[
        'drive',
        '--no-pub',
        '-d',
        screenshotDevice.id,
        '--screenshot',
        'drive_screenshots',
      ]),
      throwsToolExit(message: 'cannot start app'),
    );

    expect(logger.statusText, contains('Screenshot written to drive_screenshots/drive_01.png'));
    expect(logger.statusText, isNot(contains('drive_02.png')));
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => FakeProcessManager.any(),
    Pub: () => FakePub(),
    DeviceManager: () => fakeDeviceManager,
  });

  testUsingContext('takes screenshot on drive test failure', () async {
    final DriveCommand command = DriveCommand(
      fileSystem: fileSystem,
      logger: logger,
      platform: platform,
      signals: signals,
      flutterDriverFactory: FailingFakeFlutterDriverFactory(),
    );

    fileSystem.file('lib/main.dart').createSync(recursive: true);
    fileSystem.file('test_driver/main_test.dart').createSync(recursive: true);
    fileSystem.file('pubspec.yaml').createSync();
    fileSystem.directory('drive_screenshots').createSync();

    final Device screenshotDevice = ScreenshotDevice();
    fakeDeviceManager.devices = <Device>[screenshotDevice];

    await expectLater(() => createTestCommandRunner(command).run(
      <String>[
        'drive',
        '--no-pub',
        '-d',
        screenshotDevice.id,
        '--use-existing-app',
        'http://localhost:8181',
        '--keep-app-running',
        '--screenshot',
        'drive_screenshots',
      ]),
      throwsToolExit(),
    );

    // Takes the screenshot before the application would be killed (if --keep-app-running not passed).
    expect(logger.statusText, contains('Screenshot written to drive_screenshots/drive_01.png\n'
        'Leaving the application running.'));
    expect(logger.statusText, isNot(contains('drive_02.png')));
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => FakeProcessManager.any(),
    Pub: () => FakePub(),
    DeviceManager: () => fakeDeviceManager,
  });

  testUsingContext('drive --screenshot errors but does not fail if screenshot fails', () async {
    final DriveCommand command = DriveCommand(
      fileSystem: fileSystem,
      logger: logger,
      platform: platform,
      signals: signals,
    );

    fileSystem.file('lib/main.dart').createSync(recursive: true);
    fileSystem.file('test_driver/main_test.dart').createSync(recursive: true);
    fileSystem.file('pubspec.yaml').createSync();
    fileSystem.file('drive_screenshots').createSync();

    final Device screenshotDevice = ThrowingScreenshotDevice();
    fakeDeviceManager.devices = <Device>[screenshotDevice];

    await expectLater(() => createTestCommandRunner(command).run(
      <String>[
        'drive',
        '--no-pub',
        '-d',
        screenshotDevice.id,
        '--screenshot',
        'drive_screenshots',
      ]),
      throwsToolExit(message: 'cannot start app'),
    );

    expect(logger.statusText, isEmpty);
    expect(logger.errorText, contains('Error taking screenshot: FileSystemException: Not a directory'));
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => FakeProcessManager.any(),
    Pub: () => FakePub(),
    DeviceManager: () => fakeDeviceManager,
  });

  testUsingContext('drive --timeout takes screenshot and tool exits after timeout', () async {
    final DriveCommand command = DriveCommand(
      fileSystem: fileSystem,
      logger: logger,
      platform: platform,
      signals: Signals.test(),
      flutterDriverFactory: NeverEndingFlutterDriverFactory(() {}),
    );

    fileSystem.file('lib/main.dart').createSync(recursive: true);
    fileSystem.file('test_driver/main_test.dart').createSync(recursive: true);
    fileSystem.file('pubspec.yaml').createSync();
    fileSystem.directory('drive_screenshots').createSync();

    final ScreenshotDevice screenshotDevice = ScreenshotDevice();
    fakeDeviceManager.devices = <Device>[screenshotDevice];

    expect(screenshotDevice.screenshots, isEmpty);
    bool caughtToolExit = false;
    FakeAsync().run<void>((FakeAsync time) {
      // Because the tool exit will be thrown asynchronously by a [Timer],
      // use [asyncGuard] to catch it
      asyncGuard<void>(
        () => createTestCommandRunner(command).run(
          <String>[
            'drive',
            '--no-pub',
            '-d',
            screenshotDevice.id,
            '--use-existing-app',
            'http://localhost:8181',
            '--screenshot',
            'drive_screenshots',
            '--timeout',
            '300', // 5 minutes
          ],
        ),
        onError: (Object error) {
          expect(error, isA<ToolExit>());
          expect(
            (error as ToolExit).message,
            contains('Timed out after 300 seconds'),
          );
          caughtToolExit = true;
        }
      );
      time.elapse(const Duration(seconds: 299));
      expect(screenshotDevice.screenshots, isEmpty);
      time.elapse(const Duration(seconds: 2));
      expect(
        screenshotDevice.screenshots,
        contains(isA<File>().having(
          (File file) => file.path,
          'path',
          'drive_screenshots/drive_01.png',
        )),
      );
    });
    expect(caughtToolExit, isTrue);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => FakeProcessManager.any(),
    Pub: () => FakePub(),
    DeviceManager: () => fakeDeviceManager,
  });

  testUsingContext('drive --screenshot takes screenshot if sent a registered signal', () async {
    final FakeProcessSignal signal = FakeProcessSignal();
    final ProcessSignal signalUnderTest = ProcessSignal(signal);
    final DriveCommand command = DriveCommand(
      fileSystem: fileSystem,
      logger: logger,
      platform: platform,
      signals: Signals.test(),
      flutterDriverFactory: NeverEndingFlutterDriverFactory(() {
        signal.controller.add(signal);
      }),
      signalsToHandle: <ProcessSignal>{signalUnderTest},
    );

    fileSystem.file('lib/main.dart').createSync(recursive: true);
    fileSystem.file('test_driver/main_test.dart').createSync(recursive: true);
    fileSystem.file('pubspec.yaml').createSync();
    fileSystem.directory('drive_screenshots').createSync();

    final ScreenshotDevice screenshotDevice = ScreenshotDevice();
    fakeDeviceManager.devices = <Device>[screenshotDevice];

    expect(screenshotDevice.screenshots, isEmpty);

    // This command will never complete. In reality, a real signal would have
    // shut down the Dart process.
    unawaited(
      createTestCommandRunner(command).run(
        <String>[
          'drive',
          '--no-pub',
          '-d',
          screenshotDevice.id,
          '--use-existing-app',
          'http://localhost:8181',
          '--screenshot',
          'drive_screenshots',
        ],
      ),
    );

    await screenshotDevice.firstScreenshot;
    expect(
      screenshotDevice.screenshots,
      contains(isA<File>().having(
        (File file) => file.path,
        'path',
        'drive_screenshots/drive_01.png',
      )),
    );
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => FakeProcessManager.any(),
    Pub: () => FakePub(),
    DeviceManager: () => fakeDeviceManager,
  });

  testUsingContext('shouldRunPub is true unless user specifies --no-pub', () async {
    final DriveCommand command = DriveCommand(
      fileSystem: fileSystem,
      logger: logger,
      platform: platform,
      signals: signals,
    );

    fileSystem.file('lib/main.dart').createSync(recursive: true);
    fileSystem.file('test_driver/main_test.dart').createSync(recursive: true);
    fileSystem.file('pubspec.yaml').createSync();

    try {
      await createTestCommandRunner(command).run(const <String>['drive', '--no-pub']);
    } on Exception {
      // Expected to throw
    }

    expect(command.shouldRunPub, false);

    try {
      await createTestCommandRunner(command).run(const <String>['drive']);
    } on Exception {
      // Expected to throw
    }

    expect(command.shouldRunPub, true);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => FakeProcessManager.any(),
    Pub: () => FakePub(),
  });

  testUsingContext('flags propagate to debugging options', () async {
    final DriveCommand command = DriveCommand(
      fileSystem: fileSystem,
      logger: logger,
      platform: platform,
      signals: signals,
    );

    fileSystem.file('lib/main.dart').createSync(recursive: true);
    fileSystem.file('test_driver/main_test.dart').createSync(recursive: true);
    fileSystem.file('pubspec.yaml').createSync();

    await expectLater(() => createTestCommandRunner(command).run(<String>[
      'drive',
      '--start-paused',
      '--disable-service-auth-codes',
      '--trace-skia',
      '--trace-systrace',
      '--verbose-system-logs',
      '--null-assertions',
      '--native-null-assertions',
      '--enable-impeller',
      '--trace-systrace',
      '--enable-software-rendering',
      '--skia-deterministic-rendering',
    ]), throwsToolExit());

    final DebuggingOptions options = await command.createDebuggingOptions(false);

    expect(options.startPaused, true);
    expect(options.disableServiceAuthCodes, true);
    expect(options.traceSkia, true);
    expect(options.traceSystrace, true);
    expect(options.verboseSystemLogs, true);
    expect(options.nullAssertions, true);
    expect(options.nativeNullAssertions, true);
    expect(options.enableImpeller, true);
    expect(options.traceSystrace, true);
    expect(options.enableSoftwareRendering, true);
    expect(options.skiaDeterministicRendering, true);
  }, overrides: <Type, Generator>{
    Cache: () => Cache.test(processManager: FakeProcessManager.any()),
    FileSystem: () => MemoryFileSystem.test(),
    ProcessManager: () => FakeProcessManager.any(),
  });
}

// Unfortunately Device, despite not being immutable, has an `operator ==`.
// Until we fix that, we have to also ignore related lints here.
class ThrowingScreenshotDevice extends ScreenshotDevice {
  @override
  Future<LaunchResult> startApp(
    ApplicationPackage? package, {
      String? mainPath,
      String? route,
      DebuggingOptions? debuggingOptions,
      Map<String, dynamic>? platformArgs,
      bool prebuiltApplication = false,
      bool usesTerminalUi = true,
      bool ipv6 = false,
      String? userIdentifier,
    }) async {
    throwToolExit('cannot start app');
  }
}

// Unfortunately Device, despite not being immutable, has an `operator ==`.
// Until we fix that, we have to also ignore related lints here.
// ignore: avoid_implementing_value_types
class ScreenshotDevice extends Fake implements Device {
  final List<File> screenshots = <File>[];

  final Completer<void> _firstScreenshotCompleter = Completer<void>();

  /// A Future that completes when [takeScreenshot] is called the first time.
  Future<void> get firstScreenshot => _firstScreenshotCompleter.future;

  @override
  final String name = 'FakeDevice';

  @override
  final Category category = Category.mobile;

  @override
  final String id = 'fake_device';

  @override
  Future<TargetPlatform> get targetPlatform async => TargetPlatform.android;

  @override
  bool supportsScreenshot = true;

  @override
  Future<LaunchResult> startApp(
    ApplicationPackage? package, {
      String? mainPath,
      String? route,
      DebuggingOptions? debuggingOptions,
      Map<String, dynamic>? platformArgs,
      bool prebuiltApplication = false,
      bool usesTerminalUi = true,
      bool ipv6 = false,
      String? userIdentifier,
    }) async => LaunchResult.succeeded();

  @override
  Future<void> takeScreenshot(File outputFile) async {
    if (!_firstScreenshotCompleter.isCompleted) {
      _firstScreenshotCompleter.complete();
    }
    screenshots.add(outputFile);
  }
}

class FakePub extends Fake implements Pub {
  @override
  Future<void> get({
    PubContext? context,
    required FlutterProject project,
    bool upgrade = false,
    bool offline = false,
    bool generateSyntheticPackage = false,
    String? flutterRootOverride,
    bool checkUpToDate = false,
    bool shouldSkipThirdPartyGenerator = true,
    PubOutputMode outputMode = PubOutputMode.all,
  }) async { }
}

class FakeDeviceManager extends Fake implements DeviceManager {
  List<Device> devices = <Device>[];

  @override
  String? specifiedDeviceId;

  @override
  Future<List<Device>> getDevices() async => devices;

  @override
  Future<List<Device>> findTargetDevices(FlutterProject? flutterProject, {Duration? timeout, bool promptUserToChooseDevice = true}) async => devices;
}

/// A [FlutterDriverFactory] that creates a [NeverEndingDriverService].
class NeverEndingFlutterDriverFactory extends Fake implements FlutterDriverFactory {
  NeverEndingFlutterDriverFactory(this.callback);

  final void Function() callback;

  @override
  DriverService createDriverService(bool web) => NeverEndingDriverService(callback);
}

/// A [DriverService] that will return a Future from [startTest] that will never complete.
///
/// This is to similate when the test will take a long time, but a signal is
/// expected to interrupt the process.
class NeverEndingDriverService extends Fake implements DriverService {
  NeverEndingDriverService(this.callback);

  final void Function() callback;
  @override
  Future<void> reuseApplication(Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions, bool ipv6) async { }

  @override
  Future<int> startTest(
    String testFile,
    List<String> arguments,
    Map<String, String> environment,
    PackageConfig packageConfig, {
      bool? headless,
      String? chromeBinary,
      String? browserName,
      bool? androidEmulator,
      int? driverPort,
      List<String>? webBrowserFlags,
      List<String>? browserDimension,
      String? profileMemory,
    }) async {
      callback();
      // return a Future that will never complete.
      return Completer<int>().future;
  }
}

class FailingFakeFlutterDriverFactory extends Fake implements FlutterDriverFactory {
  @override
  DriverService createDriverService(bool web) => FailingFakeDriverService();
}

class FailingFakeDriverService extends Fake implements DriverService {
  @override
  Future<void> reuseApplication(Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions, bool ipv6) async { }

  @override
  Future<int> startTest(
    String testFile,
    List<String> arguments,
    Map<String, String> environment,
    PackageConfig packageConfig, {
      bool? headless,
      String? chromeBinary,
      String? browserName,
      bool? androidEmulator,
      int? driverPort,
      List<String>? webBrowserFlags,
      List<String>? browserDimension,
      String? profileMemory,
    }) async => 1;
}

class FakeProcessSignal extends Fake implements io.ProcessSignal {
  final StreamController<io.ProcessSignal> controller = StreamController<io.ProcessSignal>();

  @override
  Stream<io.ProcessSignal> watch() => controller.stream;
}
