// 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:args/command_runner.dart';
import 'package:fake_async/fake_async.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_studio_validator.dart';
import 'package:flutter_tools/src/android/android_workflow.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/base/user_messages.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/doctor.dart';
import 'package:flutter_tools/src/custom_devices/custom_device_workflow.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/reporting/reporting.dart';
import 'package:flutter_tools/src/version.dart';
import 'package:flutter_tools/src/vscode/vscode.dart';
import 'package:flutter_tools/src/vscode/vscode_validator.dart';
import 'package:flutter_tools/src/web/workflow.dart';
import 'package:test/fake.dart';

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

void main() {
  late FakeFlutterVersion flutterVersion;
  late BufferLogger logger;
  late FakeProcessManager fakeProcessManager;

  setUp(() {
    flutterVersion = FakeFlutterVersion();
    logger = BufferLogger.test();
    fakeProcessManager = FakeProcessManager.empty();
  });

  testWithoutContext('ValidationMessage equality and hashCode includes contextUrl', () {
    const ValidationMessage messageA = ValidationMessage('ab', contextUrl: 'a');
    const ValidationMessage messageB = ValidationMessage('ab', contextUrl: 'b');

    expect(messageB, isNot(messageA));
    expect(messageB.hashCode, isNot(messageA.hashCode));
    expect(messageA, isNot(messageB));
    expect(messageA.hashCode, isNot(messageB.hashCode));
  });

  group('doctor', () {
    testUsingContext('vs code validator when both installed', () async {
      final ValidationResult result = await VsCodeValidatorTestTargets.installedWithExtension.validate();
      expect(result.type, ValidationType.installed);
      expect(result.statusInfo, 'version 1.2.3');
      expect(result.messages, hasLength(2));

      ValidationMessage message = result.messages
          .firstWhere((ValidationMessage m) => m.message.startsWith('VS Code '));
      expect(message.message, 'VS Code at ${VsCodeValidatorTestTargets.validInstall}');

      message = result.messages
          .firstWhere((ValidationMessage m) => m.message.startsWith('Flutter '));
      expect(message.message, 'Flutter extension version 4.5.6');
      expect(message.isError, isFalse);
    });

    testUsingContext('No IDE Validator includes expected installation messages', () async {
      final ValidationResult result = await NoIdeValidator().validate();
      expect(result.type, ValidationType.notAvailable);

      expect(
        result.messages.map((ValidationMessage vm) => vm.message),
        UserMessages().noIdeInstallationInfo,
      );
    });

    testUsingContext('vs code validator when 64bit installed', () async {
      expect(VsCodeValidatorTestTargets.installedWithExtension64bit.title, 'VS Code, 64-bit edition');
      final ValidationResult result = await VsCodeValidatorTestTargets.installedWithExtension64bit.validate();
      expect(result.type, ValidationType.installed);
      expect(result.statusInfo, 'version 1.2.3');
      expect(result.messages, hasLength(2));

      ValidationMessage message = result.messages
          .firstWhere((ValidationMessage m) => m.message.startsWith('VS Code '));
      expect(message.message, 'VS Code at ${VsCodeValidatorTestTargets.validInstall}');

      message = result.messages
          .firstWhere((ValidationMessage m) => m.message.startsWith('Flutter '));
      expect(message.message, 'Flutter extension version 4.5.6');
    });

    testUsingContext('vs code validator when extension missing', () async {
      final ValidationResult result = await VsCodeValidatorTestTargets.installedWithoutExtension.validate();
      expect(result.type, ValidationType.installed);
      expect(result.statusInfo, 'version 1.2.3');
      expect(result.messages, hasLength(2));

      ValidationMessage message = result.messages
          .firstWhere((ValidationMessage m) => m.message.startsWith('VS Code '));
      expect(message.message, 'VS Code at ${VsCodeValidatorTestTargets.validInstall}');

      message = result.messages
          .firstWhere((ValidationMessage m) => m.message.startsWith('Flutter '));
      expect(message.message, startsWith('Flutter extension can be installed from'));
      expect(message.contextUrl, 'https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter');
      expect(message.isError, false);
    });

    group('device validator', () {
      testWithoutContext('no devices', () async {
        final FakeDeviceManager deviceManager = FakeDeviceManager();
        final DeviceValidator deviceValidator = DeviceValidator(
          deviceManager: deviceManager,
          userMessages: UserMessages(),
        );
        final ValidationResult result = await deviceValidator.validate();
        expect(result.type, ValidationType.notAvailable);
        expect(result.messages, const <ValidationMessage>[
          ValidationMessage.hint('No devices available'),
        ]);
        expect(result.statusInfo, isNull);
      });

      testWithoutContext('diagnostic message', () async {
        final FakeDeviceManager deviceManager = FakeDeviceManager()
          ..diagnostics = <String>['Device locked'];

        final DeviceValidator deviceValidator = DeviceValidator(
          deviceManager: deviceManager,
          userMessages: UserMessages(),
        );
        final ValidationResult result = await deviceValidator.validate();
        expect(result.type, ValidationType.notAvailable);
        expect(result.messages, const <ValidationMessage>[
          ValidationMessage.hint('Device locked'),
        ]);
        expect(result.statusInfo, isNull);
      });

      testWithoutContext('diagnostic message and devices', () async {
        final FakeDevice device = FakeDevice();
        final FakeDeviceManager deviceManager = FakeDeviceManager()
          ..devices = <Device>[device]
          ..diagnostics = <String>['Device locked'];

        final DeviceValidator deviceValidator = DeviceValidator(
          deviceManager: deviceManager,
          userMessages: UserMessages(),
        );
        final ValidationResult result = await deviceValidator.validate();
        expect(result.type, ValidationType.installed);
        expect(result.messages, const <ValidationMessage>[
          ValidationMessage('name (mobile) • device-id • android • 1.2.3'),
          ValidationMessage.hint('Device locked'),
        ]);
        expect(result.statusInfo, '1 available');
      });
    });
  });

  group('doctor with overridden validators', () {
    testUsingContext('validate non-verbose output format for run without issues', () async {
      final Doctor doctor = Doctor(logger: logger);
      expect(await doctor.diagnose(verbose: false), isTrue);
      expect(logger.statusText, equals(
              'Doctor summary (to see all details, run flutter doctor -v):\n'
              '[✓] Passing Validator (with statusInfo)\n'
              '[✓] Another Passing Validator (with statusInfo)\n'
              '[✓] Providing validators is fun (with statusInfo)\n'
              '\n'
              '• No issues found!\n'
      ));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
      DoctorValidatorsProvider: () => FakeDoctorValidatorsProvider(),
    });
  });

  group('doctor usage params', () {
    late TestUsage testUsage;

    setUp(() {
      testUsage = TestUsage();
    });

    testUsingContext('contains installed', () async {
      final Doctor doctor = Doctor(logger: logger);
      await doctor.diagnose(verbose: false);

      expect(testUsage.events.length, 3);
      expect(testUsage.events, contains(
        const TestUsageEvent(
          'doctor-result',
          'PassingValidator',
          label: 'installed',
        ),
      ));
    }, overrides: <Type, Generator>{
      DoctorValidatorsProvider: () => FakeDoctorValidatorsProvider(),
      Usage: () => testUsage,
    });

    testUsingContext('contains installed and partial', () async {
      await FakePassingDoctor(logger).diagnose(verbose: false);

      expect(testUsage.events, unorderedEquals(<TestUsageEvent>[
        const TestUsageEvent(
          'doctor-result',
          'PassingValidator',
          label: 'installed',
        ),
        const TestUsageEvent(
          'doctor-result',
          'PassingValidator',
          label: 'installed',
        ),
        const TestUsageEvent(
          'doctor-result',
          'PartialValidatorWithHintsOnly',
          label: 'partial',
        ),
        const TestUsageEvent(
          'doctor-result',
          'PartialValidatorWithErrors',
          label: 'partial',
        ),
      ]));
    }, overrides: <Type, Generator>{
      Usage: () => testUsage,
    });

    testUsingContext('contains installed, missing and partial', () async {
      await FakeDoctor(logger).diagnose(verbose: false);

      expect(testUsage.events, unorderedEquals(<TestUsageEvent>[
        const TestUsageEvent(
          'doctor-result',
          'PassingValidator',
          label: 'installed',
        ),
        const TestUsageEvent(
          'doctor-result',
          'MissingValidator',
          label: 'missing',
        ),
        const TestUsageEvent(
          'doctor-result',
          'NotAvailableValidator',
          label: 'notAvailable',
        ),
        const TestUsageEvent(
          'doctor-result',
          'PartialValidatorWithHintsOnly',
          label: 'partial',
        ),
        const TestUsageEvent(
          'doctor-result',
          'PartialValidatorWithErrors',
          label: 'partial',
        ),
      ]));
    }, overrides: <Type, Generator>{
      Usage: () => testUsage,
    });

    testUsingContext('events for grouped validators are properly decomposed', () async {
      await FakeGroupedDoctor(logger).diagnose(verbose: false);

      expect(testUsage.events, unorderedEquals(<TestUsageEvent>[
        const TestUsageEvent(
          'doctor-result',
          'PassingGroupedValidator',
          label: 'installed',
        ),
        const TestUsageEvent(
          'doctor-result',
          'PassingGroupedValidator',
          label: 'installed',
        ),
        const TestUsageEvent(
          'doctor-result',
          'PassingGroupedValidator',
          label: 'installed',
        ),
        const TestUsageEvent(
          'doctor-result',
          'MissingGroupedValidator',
          label: 'missing',
        ),
      ]));
    }, overrides: <Type, Generator>{
      Usage: () => testUsage,
    });

    testUsingContext('sending events can be skipped', () async {
      await FakePassingDoctor(logger).diagnose(verbose: false, sendEvent: false);

      expect(testUsage.events, isEmpty);
    }, overrides: <Type, Generator>{
      Usage: () => testUsage,
    });
  });

  group('doctor with fake validators', () {
    testUsingContext('validate non-verbose output format for run without issues', () async {
      expect(await FakeQuietDoctor(logger).diagnose(verbose: false), isTrue);
      expect(logger.statusText, equals(
              'Doctor summary (to see all details, run flutter doctor -v):\n'
              '[✓] Passing Validator (with statusInfo)\n'
              '[✓] Another Passing Validator (with statusInfo)\n'
              '[✓] Validators are fun (with statusInfo)\n'
              '[✓] Four score and seven validators ago (with statusInfo)\n'
              '\n'
              '• No issues found!\n'
      ));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate non-verbose output format for run with crash', () async {
      expect(await FakeCrashingDoctor(logger).diagnose(verbose: false), isFalse);
      expect(logger.statusText, equals(
              'Doctor summary (to see all details, run flutter doctor -v):\n'
              '[✓] Passing Validator (with statusInfo)\n'
              '[✓] Another Passing Validator (with statusInfo)\n'
              '[☠] Crashing validator (the doctor check crashed)\n'
              '    ✗ Due to an error, the doctor check did not complete. If the error message below is not helpful, '
              'please let us know about this issue at https://github.com/flutter/flutter/issues.\n'
              '    ✗ Bad state: fatal error\n'
              '[✓] Validators are fun (with statusInfo)\n'
              '[✓] Four score and seven validators ago (with statusInfo)\n'
              '\n'
              '! Doctor found issues in 1 category.\n'
      ));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate verbose output format contains trace for run with crash', () async {
      expect(await FakeCrashingDoctor(logger).diagnose(), isFalse);
      expect(logger.statusText, contains('#0      CrashingValidator.validate'));
    });

    testUsingContext('validate tool exit when exceeding timeout', () async {
      FakeAsync().run<void>((FakeAsync time) {
        final Doctor doctor = FakeAsyncStuckDoctor(logger);
        doctor.diagnose(verbose: false);
        time.elapse(const Duration(minutes: 5));
        time.flushMicrotasks();
      });

      expect(logger.statusText, contains('Stuck validator that never completes exceeded maximum allowed duration of '));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate non-verbose output format for run with an async crash', () async {
      final Completer<void> completer = Completer<void>();
      await FakeAsync().run((FakeAsync time) {
        unawaited(FakeAsyncCrashingDoctor(time, logger).diagnose(verbose: false).then((bool r) {
          expect(r, isFalse);
          completer.complete(null);
        }));
        time.elapse(const Duration(seconds: 1));
        time.flushMicrotasks();
        return completer.future;
      });
      expect(logger.statusText, equals(
              'Doctor summary (to see all details, run flutter doctor -v):\n'
              '[✓] Passing Validator (with statusInfo)\n'
              '[✓] Another Passing Validator (with statusInfo)\n'
              '[☠] Async crashing validator (the doctor check crashed)\n'
              '    ✗ Due to an error, the doctor check did not complete. If the error message below is not helpful, '
              'please let us know about this issue at https://github.com/flutter/flutter/issues.\n'
              '    ✗ Bad state: fatal error\n'
              '[✓] Validators are fun (with statusInfo)\n'
              '[✓] Four score and seven validators ago (with statusInfo)\n'
              '\n'
              '! Doctor found issues in 1 category.\n'
      ));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });


    testUsingContext('validate non-verbose output format when only one category fails', () async {
      expect(await FakeSinglePassingDoctor(logger).diagnose(verbose: false), isTrue);
      expect(logger.statusText, equals(
              'Doctor summary (to see all details, run flutter doctor -v):\n'
              '[!] Partial Validator with only a Hint\n'
              '    ! There is a hint here\n'
              '\n'
              '! Doctor found issues in 1 category.\n'
      ));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate non-verbose output format for a passing run', () async {
      expect(await FakePassingDoctor(logger).diagnose(verbose: false), isTrue);
      expect(logger.statusText, equals(
              'Doctor summary (to see all details, run flutter doctor -v):\n'
              '[✓] Passing Validator (with statusInfo)\n'
              '[!] Partial Validator with only a Hint\n'
              '    ! There is a hint here\n'
              '[!] Partial Validator with Errors\n'
              '    ✗ An error message indicating partial installation\n'
              '    ! Maybe a hint will help the user\n'
              '[✓] Another Passing Validator (with statusInfo)\n'
              '\n'
              '! Doctor found issues in 2 categories.\n'
      ));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate non-verbose output format', () async {
      expect(await FakeDoctor(logger).diagnose(verbose: false), isFalse);
      expect(logger.statusText, equals(
              'Doctor summary (to see all details, run flutter doctor -v):\n'
              '[✓] Passing Validator (with statusInfo)\n'
              '[✗] Missing Validator\n'
              '    ✗ A useful error message\n'
              '    ! A hint message\n'
              '[!] Not Available Validator\n'
              '    ✗ A useful error message\n'
              '    ! A hint message\n'
              '[!] Partial Validator with only a Hint\n'
              '    ! There is a hint here\n'
              '[!] Partial Validator with Errors\n'
              '    ✗ An error message indicating partial installation\n'
              '    ! Maybe a hint will help the user\n'
              '\n'
              '! Doctor found issues in 4 categories.\n'
      ));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate verbose output format', () async {
      expect(await FakeDoctor(logger).diagnose(), isFalse);
      expect(logger.statusText, equals(
              '[✓] Passing Validator (with statusInfo)\n'
              '    • A helpful message\n'
              '    • A second, somewhat longer helpful message\n'
              '\n'
              '[✗] Missing Validator\n'
              '    ✗ A useful error message\n'
              '    • A message that is not an error\n'
              '    ! A hint message\n'
              '\n'
              '[!] Not Available Validator\n'
              '    ✗ A useful error message\n'
              '    • A message that is not an error\n'
              '    ! A hint message\n'
              '\n'
              '[!] Partial Validator with only a Hint\n'
              '    ! There is a hint here\n'
              '    • But there is no error\n'
              '\n'
              '[!] Partial Validator with Errors\n'
              '    ✗ An error message indicating partial installation\n'
              '    ! Maybe a hint will help the user\n'
              '    • An extra message with some verbose details\n'
              '\n'
              '! Doctor found issues in 4 categories.\n'
      ));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate PII can be hidden', () async {
      expect(await FakePiiDoctor(logger).diagnose(showPii: false), isTrue);
      expect(logger.statusText, equals(
        '[✓] PII Validator\n'
        '    • Does not contain PII\n'
        '\n'
        '• No issues found!\n'
      ));
      logger.clear();
      // PII shown.
      expect(await FakePiiDoctor(logger).diagnose(), isTrue);
      expect(logger.statusText, equals(
          '[✓] PII Validator\n'
              '    • Contains PII path/to/username\n'
              '\n'
              '• No issues found!\n'
      ));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });
  });

  group('doctor diagnosis wrapper', () {
    late TestUsage testUsage;
    late BufferLogger logger;

    setUp(() {
      testUsage = TestUsage();
      logger = BufferLogger.test();
    });

    testUsingContext('PII separated, events only sent once', () async {
      final Doctor fakeDoctor = FakePiiDoctor(logger);
      final DoctorText doctorText = DoctorText(logger, doctor: fakeDoctor);
      const String expectedPiiText = '[✓] PII Validator\n'
          '    • Contains PII path/to/username\n'
          '\n'
          '• No issues found!\n';
      const String expectedPiiStrippedText =
          '[✓] PII Validator\n'
          '    • Does not contain PII\n'
          '\n'
          '• No issues found!\n';

      // Run each multiple times to make sure the logger buffer is being cleared,
      // and that events are only sent once.
      expect(await doctorText.text, expectedPiiText);
      expect(await doctorText.text, expectedPiiText);

      expect(await doctorText.piiStrippedText, expectedPiiStrippedText);
      expect(await doctorText.piiStrippedText, expectedPiiStrippedText);

      // Only one event sent.
      expect(testUsage.events, <TestUsageEvent>[
        const TestUsageEvent(
          'doctor-result',
          'PiiValidator',
          label: 'installed',
        ),
      ]);
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
      Usage: () => testUsage,
    });

    testUsingContext('without PII has same text and PII-stripped text', () async {
      final Doctor fakeDoctor = FakePassingDoctor(logger);
      final DoctorText doctorText = DoctorText(logger, doctor: fakeDoctor);
      final String piiText = await doctorText.text;
      expect(piiText, isNotEmpty);
      expect(piiText, await doctorText.piiStrippedText);
    }, overrides: <Type, Generator>{
      Usage: () => testUsage,
    });
  });

  testUsingContext('validate non-verbose output wrapping', () async {
    final BufferLogger wrapLogger = BufferLogger.test(
      outputPreferences: OutputPreferences(wrapText: true, wrapColumn: 30),
    );
    expect(await FakeDoctor(wrapLogger).diagnose(verbose: false), isFalse);
    expect(wrapLogger.statusText, equals(
        'Doctor summary (to see all\n'
        'details, run flutter doctor\n'
        '-v):\n'
        '[✓] Passing Validator (with\n'
        '    statusInfo)\n'
        '[✗] Missing Validator\n'
        '    ✗ A useful error message\n'
        '    ! A hint message\n'
        '[!] Not Available Validator\n'
        '    ✗ A useful error message\n'
        '    ! A hint message\n'
        '[!] Partial Validator with\n'
        '    only a Hint\n'
        '    ! There is a hint here\n'
        '[!] Partial Validator with\n'
        '    Errors\n'
        '    ✗ An error message\n'
        '      indicating partial\n'
        '      installation\n'
        '    ! Maybe a hint will help\n'
        '      the user\n'
        '\n'
        '! Doctor found issues in 4\n'
        '  categories.\n'
    ));
  }, overrides: <Type, Generator>{
    AnsiTerminal: () => FakeTerminal(),
  });

  testUsingContext('validate verbose output wrapping', () async {
    final BufferLogger wrapLogger = BufferLogger.test(
      outputPreferences: OutputPreferences(wrapText: true, wrapColumn: 30),
    );
    expect(await FakeDoctor(wrapLogger).diagnose(), isFalse);
    expect(wrapLogger.statusText, equals(
        '[✓] Passing Validator (with\n'
        '    statusInfo)\n'
        '    • A helpful message\n'
        '    • A second, somewhat\n'
        '      longer helpful message\n'
        '\n'
        '[✗] Missing Validator\n'
        '    ✗ A useful error message\n'
        '    • A message that is not an\n'
        '      error\n'
        '    ! A hint message\n'
        '\n'
        '[!] Not Available Validator\n'
        '    ✗ A useful error message\n'
        '    • A message that is not an\n'
        '      error\n'
        '    ! A hint message\n'
        '\n'
        '[!] Partial Validator with\n'
        '    only a Hint\n'
        '    ! There is a hint here\n'
        '    • But there is no error\n'
        '\n'
        '[!] Partial Validator with\n'
        '    Errors\n'
        '    ✗ An error message\n'
        '      indicating partial\n'
        '      installation\n'
        '    ! Maybe a hint will help\n'
        '      the user\n'
        '    • An extra message with\n'
        '      some verbose details\n'
        '\n'
        '! Doctor found issues in 4\n'
        '  categories.\n'
    ));
  }, overrides: <Type, Generator>{
    AnsiTerminal: () => FakeTerminal(),
  });

  group('doctor with grouped validators', () {
    testUsingContext('validate diagnose combines validator output', () async {
      expect(await FakeGroupedDoctor(logger).diagnose(), isTrue);
      expect(logger.statusText, equals(
              '[✓] Category 1\n'
              '    • A helpful message\n'
              '    • A helpful message\n'
              '\n'
              '[!] Category 2\n'
              '    • A helpful message\n'
              '    ✗ A useful error message\n'
              '\n'
              '! Doctor found issues in 1 category.\n'
      ));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate merging assigns statusInfo and title', () async {
      // There are two subvalidators. Only the second contains statusInfo.
      expect(await FakeGroupedDoctorWithStatus(logger).diagnose(), isTrue);
      expect(logger.statusText, equals(
              '[✓] First validator title (A status message)\n'
              '    • A helpful message\n'
              '    • A different message\n'
              '\n'
              '• No issues found!\n'
      ));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });
  });

  group('grouped validator merging results', () {
    final PassingGroupedValidator installed = PassingGroupedValidator('Category');
    final PartialGroupedValidator partial = PartialGroupedValidator('Category');
    final MissingGroupedValidator missing = MissingGroupedValidator('Category');

    testUsingContext('validate installed + installed = installed', () async {
      expect(await FakeSmallGroupDoctor(logger, installed, installed).diagnose(), isTrue);
      expect(logger.statusText, startsWith('[✓]'));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate installed + partial = partial', () async {
      expect(await FakeSmallGroupDoctor(logger, installed, partial).diagnose(), isTrue);
      expect(logger.statusText, startsWith('[!]'));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate installed + missing = partial', () async {
      expect(await FakeSmallGroupDoctor(logger, installed, missing).diagnose(), isTrue);
      expect(logger.statusText, startsWith('[!]'));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate partial + installed = partial', () async {
      expect(await FakeSmallGroupDoctor(logger, partial, installed).diagnose(), isTrue);
      expect(logger.statusText, startsWith('[!]'));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate partial + partial = partial', () async {
      expect(await FakeSmallGroupDoctor(logger, partial, partial).diagnose(), isTrue);
      expect(logger.statusText, startsWith('[!]'));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate partial + missing = partial', () async {
      expect(await FakeSmallGroupDoctor(logger, partial, missing).diagnose(), isTrue);
      expect(logger.statusText, startsWith('[!]'));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate missing + installed = partial', () async {
      expect(await FakeSmallGroupDoctor(logger, missing, installed).diagnose(), isTrue);
      expect(logger.statusText, startsWith('[!]'));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate missing + partial = partial', () async {
      expect(await FakeSmallGroupDoctor(logger, missing, partial).diagnose(), isTrue);
      expect(logger.statusText, startsWith('[!]'));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });

    testUsingContext('validate missing + missing = missing', () async {
      expect(await FakeSmallGroupDoctor(logger, missing, missing).diagnose(), isFalse);
      expect(logger.statusText, startsWith('[✗]'));
    }, overrides: <Type, Generator>{
      AnsiTerminal: () => FakeTerminal(),
    });
  });

  testUsingContext('WebWorkflow is a part of validator workflows if enabled', () async {
    final List<Workflow> workflows = DoctorValidatorsProvider.test(
      featureFlags: TestFeatureFlags(isWebEnabled: true),
      platform: FakePlatform(),
    ).workflows;
    expect(
      workflows,
      contains(isA<WebWorkflow>()),
    );
  }, overrides: <Type, Generator>{
    FileSystem: () => MemoryFileSystem.test(),
    ProcessManager: () => fakeProcessManager,
  });

  testUsingContext('CustomDevicesWorkflow is a part of validator workflows if enabled', () async {
    final List<Workflow> workflows = DoctorValidatorsProvider.test(
      featureFlags: TestFeatureFlags(areCustomDevicesEnabled: true),
      platform: FakePlatform(),
    ).workflows;
    expect(
      workflows,
      contains(isA<CustomDeviceWorkflow>()),
    );
  }, overrides: <Type, Generator>{
    FileSystem: () => MemoryFileSystem.test(),
    ProcessManager: () => fakeProcessManager,
  });

  testUsingContext('Fetches tags to get the right version', () async {
    Cache.disableLocking();

    final DoctorCommand doctorCommand = DoctorCommand();
    final CommandRunner<void> commandRunner = createTestCommandRunner(doctorCommand);

    await commandRunner.run(<String>['doctor']);

    expect(flutterVersion.didFetchTagsAndUpdate, true);
    Cache.enableLocking();
  }, overrides: <Type, Generator>{
    ProcessManager: () => FakeProcessManager.any(),
    FileSystem: () => MemoryFileSystem.test(),
    FlutterVersion: () => flutterVersion,
    Doctor: () => NoOpDoctor(),
  }, initializeFlutterRoot: false);

  testUsingContext('If android workflow is disabled, AndroidStudio validator is not included', () {
    final DoctorValidatorsProvider provider = DoctorValidatorsProvider.test(
      featureFlags: TestFeatureFlags(isAndroidEnabled: false),
    );
    expect(provider.validators, isNot(contains(isA<AndroidStudioValidator>())));
    expect(provider.validators, isNot(contains(isA<NoAndroidStudioValidator>())));
  }, overrides: <Type, Generator>{
    AndroidWorkflow: () => FakeAndroidWorkflow(appliesToHostPlatform: false),
  });
}

class FakeAndroidWorkflow extends Fake implements AndroidWorkflow {
  FakeAndroidWorkflow({
    this.canListDevices = true,
    this.appliesToHostPlatform = true,
  });

  @override
  final bool canListDevices;

  @override
  final bool appliesToHostPlatform;
}


class NoOpDoctor implements Doctor {
  @override
  bool get canLaunchAnything => true;

  @override
  bool get canListAnything => true;

  @override
  Future<bool> checkRemoteArtifacts(String engineRevision) async => true;

  @override
  Future<bool> diagnose({
    bool androidLicenses = false,
    bool verbose = true,
    bool showColor = true,
    AndroidLicenseValidator? androidLicenseValidator,
    bool showPii = true,
    List<ValidatorTask>? startedValidatorTasks,
    bool sendEvent = true,
  }) async => true;

  @override
  List<ValidatorTask> startValidatorTasks() => <ValidatorTask>[];

  @override
  Future<void> summary() async { }

  @override
  List<DoctorValidator> get validators => <DoctorValidator>[];

  @override
  List<Workflow> get workflows => <Workflow>[];
}

class PassingValidator extends DoctorValidator {
  PassingValidator(super.name);

  @override
  Future<ValidationResult> validate() async {
    const List<ValidationMessage> messages = <ValidationMessage>[
      ValidationMessage('A helpful message'),
      ValidationMessage('A second, somewhat longer helpful message'),
    ];
    return const ValidationResult(ValidationType.installed, messages, statusInfo: 'with statusInfo');
  }
}

class PiiValidator extends DoctorValidator {
  PiiValidator() : super('PII Validator');

  @override
  Future<ValidationResult> validate() async {
    const List<ValidationMessage> messages = <ValidationMessage>[
      ValidationMessage('Contains PII path/to/username', piiStrippedMessage: 'Does not contain PII'),
    ];
    return const ValidationResult(ValidationType.installed, messages);
  }
}

class MissingValidator extends DoctorValidator {
  MissingValidator() : super('Missing Validator');

  @override
  Future<ValidationResult> validate() async {
    const List<ValidationMessage> messages = <ValidationMessage>[
      ValidationMessage.error('A useful error message'),
      ValidationMessage('A message that is not an error'),
      ValidationMessage.hint('A hint message'),
    ];
    return const ValidationResult(ValidationType.missing, messages);
  }
}

class NotAvailableValidator extends DoctorValidator {
  NotAvailableValidator() : super('Not Available Validator');

  @override
  Future<ValidationResult> validate() async {
    const List<ValidationMessage> messages = <ValidationMessage>[
      ValidationMessage.error('A useful error message'),
      ValidationMessage('A message that is not an error'),
      ValidationMessage.hint('A hint message'),
    ];
    return const ValidationResult(ValidationType.notAvailable, messages);
  }
}

class StuckValidator extends DoctorValidator {
  StuckValidator() : super('Stuck validator that never completes');

  @override
  Future<ValidationResult> validate() {
    final Completer<ValidationResult> completer = Completer<ValidationResult>();

    // This future will never complete
    return completer.future;
  }
}

class PartialValidatorWithErrors extends DoctorValidator {
  PartialValidatorWithErrors() : super('Partial Validator with Errors');

  @override
  Future<ValidationResult> validate() async {
    const List<ValidationMessage> messages = <ValidationMessage>[
      ValidationMessage.error('An error message indicating partial installation'),
      ValidationMessage.hint('Maybe a hint will help the user'),
      ValidationMessage('An extra message with some verbose details'),
    ];
    return const ValidationResult(ValidationType.partial, messages);
  }
}

class PartialValidatorWithHintsOnly extends DoctorValidator {
  PartialValidatorWithHintsOnly() : super('Partial Validator with only a Hint');

  @override
  Future<ValidationResult> validate() async {
    const List<ValidationMessage> messages = <ValidationMessage>[
      ValidationMessage.hint('There is a hint here'),
      ValidationMessage('But there is no error'),
    ];
    return const ValidationResult(ValidationType.partial, messages);
  }
}

class CrashingValidator extends DoctorValidator {
  CrashingValidator() : super('Crashing validator');

  @override
  Future<ValidationResult> validate() async {
    throw StateError('fatal error');
  }
}

class AsyncCrashingValidator extends DoctorValidator {
  AsyncCrashingValidator(this._time) : super('Async crashing validator');

  final FakeAsync _time;

  @override
  Future<ValidationResult> validate() {
    const Duration delay = Duration(seconds: 1);
    final Future<ValidationResult> result = Future<ValidationResult>.delayed(
      delay,
      () => throw StateError('fatal error'),
    );
    _time.elapse(const Duration(seconds: 1));
    _time.flushMicrotasks();
    return result;
  }
}

/// A doctor that fails with a missing [ValidationResult].
class FakeDoctor extends Doctor {
  FakeDoctor(Logger logger) : super(logger: logger);

  @override
  late final List<DoctorValidator> validators = <DoctorValidator>[
    PassingValidator('Passing Validator'),
    MissingValidator(),
    NotAvailableValidator(),
    PartialValidatorWithHintsOnly(),
    PartialValidatorWithErrors(),
  ];
}

/// A doctor that should pass, but still has issues in some categories.
class FakePassingDoctor extends Doctor {
  FakePassingDoctor(Logger logger) : super(logger: logger);

  @override
  late final List<DoctorValidator> validators = <DoctorValidator>[
    PassingValidator('Passing Validator'),
    PartialValidatorWithHintsOnly(),
    PartialValidatorWithErrors(),
    PassingValidator('Another Passing Validator'),
  ];
}

/// A doctor that should pass, but still has 1 issue to test the singular of
/// categories.
class FakeSinglePassingDoctor extends Doctor {
  FakeSinglePassingDoctor(Logger logger) : super(logger: logger);

  @override
  late final List<DoctorValidator> validators = <DoctorValidator>[
    PartialValidatorWithHintsOnly(),
  ];
}

/// A doctor that passes and has no issues anywhere.
class FakeQuietDoctor extends Doctor {
  FakeQuietDoctor(Logger logger) : super(logger: logger);

  @override
  late final List<DoctorValidator> validators = <DoctorValidator>[
    PassingValidator('Passing Validator'),
    PassingValidator('Another Passing Validator'),
    PassingValidator('Validators are fun'),
    PassingValidator('Four score and seven validators ago'),
  ];
}

/// A doctor that passes and contains PII that can be hidden.
class FakePiiDoctor extends Doctor {
  FakePiiDoctor(Logger logger) : super(logger: logger);

  @override
  late final List<DoctorValidator> validators = <DoctorValidator>[
    PiiValidator(),
  ];
}

/// A doctor with a validator that throws an exception.
class FakeCrashingDoctor extends Doctor {
  FakeCrashingDoctor(Logger logger) : super(logger: logger);

  @override
  late final List<DoctorValidator> validators = <DoctorValidator>[
    PassingValidator('Passing Validator'),
    PassingValidator('Another Passing Validator'),
    CrashingValidator(),
    PassingValidator('Validators are fun'),
    PassingValidator('Four score and seven validators ago'),
  ];
}

/// A doctor with a validator that will never finish.
class FakeAsyncStuckDoctor extends Doctor {
  FakeAsyncStuckDoctor(Logger logger) : super(logger: logger);

  @override
  late final List<DoctorValidator> validators = <DoctorValidator>[
    PassingValidator('Passing Validator'),
    PassingValidator('Another Passing Validator'),
    StuckValidator(),
    PassingValidator('Validators are fun'),
    PassingValidator('Four score and seven validators ago'),
  ];
}

/// A doctor with a validator that throws an exception.
class FakeAsyncCrashingDoctor extends Doctor {
  FakeAsyncCrashingDoctor(this._time, Logger logger) : super(logger: logger);

  final FakeAsync _time;

  @override
  late final List<DoctorValidator> validators = <DoctorValidator>[
    PassingValidator('Passing Validator'),
    PassingValidator('Another Passing Validator'),
    AsyncCrashingValidator(_time),
    PassingValidator('Validators are fun'),
    PassingValidator('Four score and seven validators ago'),
  ];
}

/// A DoctorValidatorsProvider that overrides the default validators without
/// overriding the doctor.
class FakeDoctorValidatorsProvider implements DoctorValidatorsProvider {
  @override
  List<DoctorValidator> get validators {
    return <DoctorValidator>[
      PassingValidator('Passing Validator'),
      PassingValidator('Another Passing Validator'),
      PassingValidator('Providing validators is fun'),
    ];
  }

  @override
  List<Workflow> get workflows => <Workflow>[];
}

class PassingGroupedValidator extends DoctorValidator {
  PassingGroupedValidator(super.name);

  @override
  Future<ValidationResult> validate() async {
    const List<ValidationMessage> messages = <ValidationMessage>[
      ValidationMessage('A helpful message'),
    ];
    return const ValidationResult(ValidationType.installed, messages);
  }
}

class MissingGroupedValidator extends DoctorValidator {
  MissingGroupedValidator(super.name);

  @override
  Future<ValidationResult> validate() async {
    const List<ValidationMessage> messages = <ValidationMessage>[
      ValidationMessage.error('A useful error message'),
    ];
    return const ValidationResult(ValidationType.missing, messages);
  }
}

class PartialGroupedValidator extends DoctorValidator {
  PartialGroupedValidator(super.name);

  @override
  Future<ValidationResult> validate() async {
    const List<ValidationMessage> messages = <ValidationMessage>[
      ValidationMessage.error('An error message for partial installation'),
    ];
    return const ValidationResult(ValidationType.partial, messages);
  }
}

class PassingGroupedValidatorWithStatus extends DoctorValidator {
  PassingGroupedValidatorWithStatus(super.name);

  @override
  Future<ValidationResult> validate() async {
    const List<ValidationMessage> messages = <ValidationMessage>[
      ValidationMessage('A different message'),
    ];
    return const ValidationResult(ValidationType.installed, messages, statusInfo: 'A status message');
  }
}

/// A doctor that has two groups of two validators each.
class FakeGroupedDoctor extends Doctor {
  FakeGroupedDoctor(Logger logger) : super(logger: logger);

  @override
  late final List<DoctorValidator> validators = <DoctorValidator>[
    GroupedValidator(<DoctorValidator>[
      PassingGroupedValidator('Category 1'),
      PassingGroupedValidator('Category 1'),
    ]),
    GroupedValidator(<DoctorValidator>[
      PassingGroupedValidator('Category 2'),
      MissingGroupedValidator('Category 2'),
    ]),
  ];
}

class FakeGroupedDoctorWithStatus extends Doctor {
  FakeGroupedDoctorWithStatus(Logger logger) : super(logger: logger);

  @override
  late final List<DoctorValidator> validators = <DoctorValidator>[
    GroupedValidator(<DoctorValidator>[
      PassingGroupedValidator('First validator title'),
      PassingGroupedValidatorWithStatus('Second validator title'),
    ]),
  ];
}

/// A doctor that takes any two validators. Used to check behavior when
/// merging ValidationTypes (installed, missing, partial).
class FakeSmallGroupDoctor extends Doctor {
  FakeSmallGroupDoctor(Logger logger, DoctorValidator val1, DoctorValidator val2)
    : validators = <DoctorValidator>[GroupedValidator(<DoctorValidator>[val1, val2])],
      super(logger: logger);

  @override
  final List<DoctorValidator> validators;
}

class VsCodeValidatorTestTargets extends VsCodeValidator {
  VsCodeValidatorTestTargets._(String installDirectory, String extensionDirectory, {String? edition})
    : super(VsCode.fromDirectory(installDirectory, extensionDirectory, edition: edition, fileSystem: globals.fs));

  static VsCodeValidatorTestTargets get installedWithExtension =>
      VsCodeValidatorTestTargets._(validInstall, validExtensions);

  static VsCodeValidatorTestTargets get installedWithExtension64bit =>
      VsCodeValidatorTestTargets._(validInstall, validExtensions, edition: '64-bit edition');

  static VsCodeValidatorTestTargets get installedWithoutExtension =>
      VsCodeValidatorTestTargets._(validInstall, missingExtensions);

  static final String validInstall = globals.fs.path.join('test', 'data', 'vscode', 'application');
  static final String validExtensions = globals.fs.path.join('test', 'data', 'vscode', 'extensions');
  static final String missingExtensions = globals.fs.path.join('test', 'data', 'vscode', 'notExtensions');
}

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

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

  @override
  Future<List<String>> getDeviceDiagnostics() async => diagnostics;
}

// 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 FakeDevice extends Fake implements Device {
  @override
  String get name => 'name';

  @override
  String get id => 'device-id';

  @override
  Category get category => Category.mobile;

  @override
  bool isSupported() => true;

  @override
  Future<bool> get isLocalEmulator async => false;

  @override
  Future<String> get targetPlatformDisplayName async => 'android';

  @override
  Future<String> get sdkNameAndVersion async => '1.2.3';

  @override
  Future<TargetPlatform> get targetPlatform =>  Future<TargetPlatform>.value(TargetPlatform.android);
}

class FakeTerminal extends Fake implements AnsiTerminal {
  @override
  final bool supportsColor = false;
}
