// 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';

import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/doctor_validator.dart';
import 'package:flutter_tools/src/http_host_validator.dart';

import '../../src/common.dart';
import '../../src/fake_http_client.dart';
import '../../src/fakes.dart';

// The environment variables used to override some URLs
const String kTestEnvPubHost = 'https://pub.flutter-io.cn';
const String kTestEnvGCloudHost = 'https://storage.flutter-io.cn';
const Map<String, String> kTestEnvironment = <String, String>{
  'PUB_HOSTED_URL': kTestEnvPubHost,
  'FLUTTER_STORAGE_BASE_URL': kTestEnvGCloudHost,
  'FLUTTER_DOCTOR_HOST_TIMEOUT': '1',
};

void main() {
  group('http host validator', () {
    const List<String> osTested = <String>['windows', 'macos', 'linux'];

    group('no env variables', () {
      testWithoutContext('all http hosts are available', () async {
        final FakeHttpClient mockClient = FakeHttpClient.any();

        // Run the check for all operating systems one by one
        for(final String os in osTested) {
          final HttpHostValidator httpHostValidator = HttpHostValidator(
            platform: FakePlatform(operatingSystem: os),
            featureFlags: TestFeatureFlags(),
            httpClient: mockClient,
          );

          // Run the validation check and get the results
          final ValidationResult result = await httpHostValidator.validate();

          // Check for a ValidationType.success result
          expect(result.type, equals(ValidationType.success));
        }
      });

      testWithoutContext('all http hosts are not available', () async {
        // Run the check for all operating systems one by one
        for(final String os in osTested) {
          final Platform platform = FakePlatform(operatingSystem: os);
          final HttpHostValidator httpHostValidator = HttpHostValidator(
            platform: platform,
            featureFlags: TestFeatureFlags(),
            httpClient: FakeHttpClient.list(<FakeRequest>[
              FakeRequest(Uri.parse(kgCloudHttpHost), method: HttpMethod.head, responseError: const OSError('Name or service not known', -2)),
              FakeRequest(Uri.parse(androidRequiredHttpHosts(platform)[0]), method: HttpMethod.head, responseError: const OSError('Name or service not known', -2)),
              FakeRequest(Uri.parse(kPubDevHttpHost), method: HttpMethod.head, responseError: const OSError('Name or service not known', -2)),
              FakeRequest(Uri.parse(macOSRequiredHttpHosts[0]), method: HttpMethod.head, responseError: const OSError('Name or service not known', -2)),
            ]),
          );

          // Run the validation check and get the results
          final ValidationResult result = await httpHostValidator.validate();

          // Check for a ValidationType.notAvailable result
          expect(result.type, equals(ValidationType.notAvailable));
        }
      });

      testWithoutContext('one http host is not available', () async {
        // Run the check for all operating systems one by one
        for(final String os in osTested) {
          final Platform platform = FakePlatform(operatingSystem: os);
          final HttpHostValidator httpHostValidator = HttpHostValidator(
            platform: platform,
            featureFlags: TestFeatureFlags(),
            httpClient: FakeHttpClient.list(<FakeRequest>[
              FakeRequest(Uri.parse(kgCloudHttpHost), method: HttpMethod.head, responseError: const OSError('Name or service not known', -2)),
              FakeRequest(Uri.parse(androidRequiredHttpHosts(platform)[0]), method: HttpMethod.head),
              FakeRequest(Uri.parse(kPubDevHttpHost), method: HttpMethod.head),
              FakeRequest(Uri.parse(macOSRequiredHttpHosts[0]), method: HttpMethod.head),
            ]),
          );

          // Run the validation check and get the results
          final ValidationResult result = await httpHostValidator.validate();

          // Check for a ValidationType.partial result
          expect(result.type, equals(ValidationType.partial));
        }
      });
    });

    group('with env variables', () {
      testWithoutContext('all http hosts are available', () async {
        final FakeHttpClient mockClient = FakeHttpClient.any();

        // Run the check for all operating systems one by one
        for(final String os in osTested) {
          final HttpHostValidator httpHostValidator = HttpHostValidator(
            platform: FakePlatform(operatingSystem: os, environment: kTestEnvironment),
            featureFlags: TestFeatureFlags(),
            httpClient: mockClient,
          );

          // Run the validation check and get the results
          final ValidationResult result = await httpHostValidator.validate();

          // Check for a ValidationType.success result
          expect(result.type, equals(ValidationType.success));
        }
      });

      testWithoutContext('all http hosts are not available', () async {
        // Run the check for all operating systems one by one
        for(final String os in osTested) {
          final Platform platform = FakePlatform(operatingSystem: os, environment: kTestEnvironment);
          final HttpHostValidator httpHostValidator = HttpHostValidator(
            platform: platform,
            featureFlags: TestFeatureFlags(),
            httpClient: FakeHttpClient.list(<FakeRequest>[
              FakeRequest(Uri.parse(kTestEnvGCloudHost), method: HttpMethod.head, responseError: const OSError('Name or service not known', -2)),
              FakeRequest(Uri.parse(kTestEnvPubHost), method: HttpMethod.head, responseError: const OSError('Name or service not known', -2)),
              FakeRequest(Uri.parse(macOSRequiredHttpHosts[0]), method: HttpMethod.head, responseError: const OSError('Name or service not known', -2)),
            ]),
          );

          // Run the validation check and get the results
          final ValidationResult result = await httpHostValidator.validate();

          // Check for a ValidationType.notAvailable result
          expect(result.type, equals(ValidationType.notAvailable));
        }
      });

      testWithoutContext('one http host is not available', () async {
        // Run the check for all operating systems one by one
        for(final String os in osTested) {
          final Platform platform = FakePlatform(operatingSystem: os, environment: kTestEnvironment);
          final HttpHostValidator httpHostValidator = HttpHostValidator(
            platform: platform,
            featureFlags: TestFeatureFlags(),
            httpClient: FakeHttpClient.list(<FakeRequest>[
              FakeRequest(Uri.parse(kTestEnvGCloudHost), method: HttpMethod.head, responseError: const OSError('Name or service not known', -2)),
              FakeRequest(Uri.parse(kTestEnvPubHost), method: HttpMethod.head),
              FakeRequest(Uri.parse(macOSRequiredHttpHosts[0]), method: HttpMethod.head),
            ]),
          );

          // Run the validation check and get the results
          final ValidationResult result = await httpHostValidator.validate();

          // Check for a ValidationType.partial result
          expect(result.type, equals(ValidationType.partial));
        }
      });

      testWithoutContext('does not throw on invalid user-defined timeout', () async {
        final HttpHostValidator httpHostValidator = HttpHostValidator(
          platform: FakePlatform(
            environment: <String,String> {
              'PUB_HOSTED_URL': kTestEnvPubHost,
              'FLUTTER_STORAGE_BASE_URL': kTestEnvGCloudHost,
              'FLUTTER_DOCTOR_HOST_TIMEOUT' : 'deadbeef',
            },
          ),
          featureFlags: TestFeatureFlags(isAndroidEnabled: false),
          httpClient: FakeHttpClient.any(),
        );

        // Run the validation check and get the results
        final ValidationResult result = await httpHostValidator.validate();

        expect(result.type, equals(ValidationType.notAvailable));
        expect(
          result.messages,
          contains(const ValidationMessage.error(
            'HTTP host "$kTestEnvPubHost" is not reachable. '
            'Reason: The value of FLUTTER_DOCTOR_HOST_TIMEOUT(deadbeef) is not a valid duration in seconds',
          )),
        );
      });

      testWithoutContext('does not throw on unparseable user-defined host uri', () async {
        final HttpHostValidator httpHostValidator = HttpHostValidator(
          platform: FakePlatform(
            environment: <String,String> {
              'PUB_HOSTED_URL': '::Not A Uri::',
              'FLUTTER_STORAGE_BASE_URL': kTestEnvGCloudHost,
              'FLUTTER_DOCTOR_HOST_TIMEOUT' : '1',
            },
          ),
          featureFlags: TestFeatureFlags(isAndroidEnabled: false),
          httpClient: FakeHttpClient.any(),
        );

        // Run the validation check and get the results
        final ValidationResult result = await httpHostValidator.validate();

        expect(result.type, equals(ValidationType.partial));
        expect(
          result.messages,
          contains(const ValidationMessage.error(
            'HTTP host "::Not A Uri::" is not reachable. '
            'Reason: The value of PUB_HOSTED_URL(::Not A Uri::) could not be parsed as a valid url',
          )),
        );
      });

      testWithoutContext('does not throw on invalid user-defined host', () async {
        final HttpHostValidator httpHostValidator = HttpHostValidator(
          platform: FakePlatform(
            environment: <String,String> {
              'PUB_HOSTED_URL': kTestEnvPubHost,
              'FLUTTER_STORAGE_BASE_URL': '',
              'FLUTTER_DOCTOR_HOST_TIMEOUT' : '1',
            },
          ),
          featureFlags: TestFeatureFlags(isAndroidEnabled: false),
          httpClient: FakeHttpClient.any(),
        );

        // Run the validation check and get the results
        final ValidationResult result = await httpHostValidator.validate();

        expect(result.type, equals(ValidationType.partial));
        expect(
          result.messages,
          contains(const ValidationMessage.error(
            'HTTP host "" is not reachable. '
            'Reason: The value of FLUTTER_STORAGE_BASE_URL() is not a valid host',
          )),
        );
      });
    });

    group('specific os disabled', () {
      testWithoutContext('all http hosts are available - android disabled', () async {
        // Run the check for all operating systems one by one
        for(final String os in osTested) {
          final HttpHostValidator httpHostValidator = HttpHostValidator(
            platform: FakePlatform(operatingSystem: os),
            featureFlags: TestFeatureFlags(isAndroidEnabled: false),
            httpClient: FakeHttpClient.list(<FakeRequest>[
              FakeRequest(Uri.parse(kgCloudHttpHost), method: HttpMethod.head),
              FakeRequest(Uri.parse(kPubDevHttpHost), method: HttpMethod.head),
              FakeRequest(Uri.parse(macOSRequiredHttpHosts[0]), method: HttpMethod.head),
            ]),
          );

          // Run the validation check and get the results
          final ValidationResult result = await httpHostValidator.validate();

          // Check for a ValidationType.success result
          expect(result.type, equals(ValidationType.success));
        }
      });

      testWithoutContext('all http hosts are available - iOS disabled', () async {
        // Run the check for all operating systems one by one
        for(final String os in osTested) {
          final Platform platform = FakePlatform(operatingSystem: os);
          final HttpHostValidator httpHostValidator = HttpHostValidator(
            platform: platform,
            featureFlags: TestFeatureFlags(isIOSEnabled: false),
            httpClient: FakeHttpClient.list(<FakeRequest>[
              FakeRequest(Uri.parse(kgCloudHttpHost), method: HttpMethod.head),
              FakeRequest(Uri.parse(kPubDevHttpHost), method: HttpMethod.head),
              FakeRequest(Uri.parse(androidRequiredHttpHosts(platform)[0]), method: HttpMethod.head),
            ]),
          );

          // Run the validation check and get the results
          final ValidationResult result = await httpHostValidator.validate();

          // Check for a ValidationType.success result
          expect(result.type, equals(ValidationType.success));
        }
      });

      testWithoutContext('all http hosts are available - android, iOS disabled', () async {
        // Run the check for all operating systems one by one
        for(final String os in osTested) {
          final HttpHostValidator httpHostValidator = HttpHostValidator(
            platform: FakePlatform(operatingSystem: os),
            featureFlags: TestFeatureFlags(isAndroidEnabled: false, isIOSEnabled: false),
            httpClient: FakeHttpClient.list(<FakeRequest>[
              FakeRequest(Uri.parse(kgCloudHttpHost), method: HttpMethod.head),
              FakeRequest(Uri.parse(kPubDevHttpHost), method: HttpMethod.head),
            ]),
          );

          // Run the validation check and get the results
          final ValidationResult result = await httpHostValidator.validate();

          // Check for a ValidationType.success result
          expect(result.type, equals(ValidationType.success));
        }
      });
    });
  });

  testWithoutContext('Does not throw on HandshakeException', () async {
    const String handshakeMessage = '''
Handshake error in client (OS Error:
        BLOCK_TYPE_IS_NOT_01(../../third_party/boringssl/src/crypto/fipsmodule/rsa/padding.c:108)
        PADDING_CHECK_FAILED(../../third_party/boringssl/src/crypto/fipsmodule/rsa/rsa_impl.c:676)
        public key routines(../../third_party/boringssl/src/crypto/x509/a_verify.c:108)
        CERTIFICATE_VERIFY_FAILED: certificate signature failure(../../third_party/boringssl/src/ssl/handshake.cc:393))
''';
    final HttpHostValidator httpHostValidator = HttpHostValidator(
      platform: FakePlatform(environment: kTestEnvironment),
      featureFlags: TestFeatureFlags(isAndroidEnabled: false),
      httpClient: FakeHttpClient.list(<FakeRequest>[
        FakeRequest(
          Uri.parse(kTestEnvPubHost),
          method: HttpMethod.head,
          responseError: const HandshakeException(handshakeMessage),
        ),
        FakeRequest(Uri.parse(kTestEnvGCloudHost), method: HttpMethod.head),
      ]),
    );

    // Run the validation check and get the results
    final ValidationResult result = await httpHostValidator.validate();

    expect(
      result.messages.first,
      isA<ValidationMessage>().having(
        (ValidationMessage msg) => msg.message,
        'message',
        contains(handshakeMessage),
      ),
    );
  });

  testWithoutContext('Http host validator timeout message includes timeout duration.', () async {
    final HttpHostValidator httpHostValidator = HttpHostValidator(
      platform: FakePlatform(environment: kTestEnvironment),
      featureFlags: TestFeatureFlags(isAndroidEnabled: false),
      httpClient: FakeHttpClient.list(<FakeRequest>[
        FakeRequest(Uri.parse(kTestEnvPubHost), method: HttpMethod.head, responseError: TimeoutException('Timeout error')),
        FakeRequest(Uri.parse(kTestEnvGCloudHost), method: HttpMethod.head),
      ]),
    );

    // Run the validation check and get the results
    final ValidationResult result = await httpHostValidator.validate();

    // Timeout duration for tests is set to 1 second
    expect(
      result.messages,
      contains(const ValidationMessage.error('HTTP host "$kTestEnvPubHost" is not reachable. Reason: Failed to connect to host in 1 second')),
    );
  });
}
