// Copyright 2013 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:convert';
import 'dart:io';

import 'package:args/command_runner.dart';
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_plugin_tools/src/common.dart';
import 'package:git/git.dart';
import 'package:http/http.dart' as http;
import 'package:http/testing.dart';
import 'package:mockito/mockito.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:test/test.dart';

import 'util.dart';

void main() {
  RecordingProcessRunner processRunner;
  CommandRunner<void> runner;
  FileSystem fileSystem;
  Directory packagesDir;
  Directory thirdPartyPackagesDir;
  List<String> plugins;
  List<List<String>> gitDirCommands;
  String gitDiffResponse;

  setUp(() {
    fileSystem = MemoryFileSystem();
    packagesDir = fileSystem.currentDirectory.childDirectory('packages');
    thirdPartyPackagesDir = packagesDir.parent
        .childDirectory('third_party')
        .childDirectory('packages');

    gitDirCommands = <List<String>>[];
    gitDiffResponse = '';
    final MockGitDir gitDir = MockGitDir();
    when(gitDir.runCommand(any)).thenAnswer((Invocation invocation) {
      gitDirCommands.add(invocation.positionalArguments[0] as List<String>);
      final MockProcessResult mockProcessResult = MockProcessResult();
      if (invocation.positionalArguments[0][0] == 'diff') {
        when<String>(mockProcessResult.stdout as String)
            .thenReturn(gitDiffResponse);
      }
      return Future<ProcessResult>.value(mockProcessResult);
    });
    initializeFakePackages(parentDir: packagesDir.parent);
    processRunner = RecordingProcessRunner();
    plugins = <String>[];
    final SamplePluginCommand samplePluginCommand = SamplePluginCommand(
      plugins,
      packagesDir,
      fileSystem,
      processRunner: processRunner,
      gitDir: gitDir,
    );
    runner =
        CommandRunner<void>('common_command', 'Test for common functionality');
    runner.addCommand(samplePluginCommand);
  });

  test('all plugins from file system', () async {
    final Directory plugin1 =
        createFakePlugin('plugin1', packagesDirectory: packagesDir);
    final Directory plugin2 =
        createFakePlugin('plugin2', packagesDirectory: packagesDir);
    await runner.run(<String>['sample']);
    expect(plugins, unorderedEquals(<String>[plugin1.path, plugin2.path]));
  });

  test('all plugins includes third_party/packages', () async {
    final Directory plugin1 =
        createFakePlugin('plugin1', packagesDirectory: packagesDir);
    final Directory plugin2 =
        createFakePlugin('plugin2', packagesDirectory: packagesDir);
    final Directory plugin3 =
        createFakePlugin('plugin3', packagesDirectory: thirdPartyPackagesDir);
    await runner.run(<String>['sample']);
    expect(plugins,
        unorderedEquals(<String>[plugin1.path, plugin2.path, plugin3.path]));
  });

  test('exclude plugins when plugins flag is specified', () async {
    createFakePlugin('plugin1', packagesDirectory: packagesDir);
    final Directory plugin2 =
        createFakePlugin('plugin2', packagesDirectory: packagesDir);
    await runner.run(
        <String>['sample', '--plugins=plugin1,plugin2', '--exclude=plugin1']);
    expect(plugins, unorderedEquals(<String>[plugin2.path]));
  });

  test('exclude plugins when plugins flag isn\'t specified', () async {
    createFakePlugin('plugin1', packagesDirectory: packagesDir);
    createFakePlugin('plugin2', packagesDirectory: packagesDir);
    await runner.run(<String>['sample', '--exclude=plugin1,plugin2']);
    expect(plugins, unorderedEquals(<String>[]));
  });

  test('exclude federated plugins when plugins flag is specified', () async {
    createFakePlugin('plugin1',
        parentDirectoryName: 'federated', packagesDirectory: packagesDir);
    final Directory plugin2 =
        createFakePlugin('plugin2', packagesDirectory: packagesDir);
    await runner.run(<String>[
      'sample',
      '--plugins=federated/plugin1,plugin2',
      '--exclude=federated/plugin1'
    ]);
    expect(plugins, unorderedEquals(<String>[plugin2.path]));
  });

  test('exclude entire federated plugins when plugins flag is specified',
      () async {
    createFakePlugin('plugin1',
        parentDirectoryName: 'federated', packagesDirectory: packagesDir);
    final Directory plugin2 =
        createFakePlugin('plugin2', packagesDirectory: packagesDir);
    await runner.run(<String>[
      'sample',
      '--plugins=federated/plugin1,plugin2',
      '--exclude=federated'
    ]);
    expect(plugins, unorderedEquals(<String>[plugin2.path]));
  });

  group('test run-on-changed-packages', () {
    test('all plugins should be tested if there are no changes.', () async {
      final Directory plugin1 =
          createFakePlugin('plugin1', packagesDirectory: packagesDir);
      final Directory plugin2 =
          createFakePlugin('plugin2', packagesDirectory: packagesDir);
      await runner.run(
          <String>['sample', '--base-sha=master', '--run-on-changed-packages']);

      expect(plugins, unorderedEquals(<String>[plugin1.path, plugin2.path]));
    });

    test('all plugins should be tested if there are no plugin related changes.',
        () async {
      gitDiffResponse = '.cirrus';
      final Directory plugin1 =
          createFakePlugin('plugin1', packagesDirectory: packagesDir);
      final Directory plugin2 =
          createFakePlugin('plugin2', packagesDirectory: packagesDir);
      await runner.run(
          <String>['sample', '--base-sha=master', '--run-on-changed-packages']);

      expect(plugins, unorderedEquals(<String>[plugin1.path, plugin2.path]));
    });

    test('Only changed plugin should be tested.', () async {
      gitDiffResponse = 'packages/plugin1/plugin1.dart';
      final Directory plugin1 =
          createFakePlugin('plugin1', packagesDirectory: packagesDir);
      createFakePlugin('plugin2', packagesDirectory: packagesDir);
      await runner.run(
          <String>['sample', '--base-sha=master', '--run-on-changed-packages']);

      expect(plugins, unorderedEquals(<String>[plugin1.path]));
    });

    test('multiple files in one plugin should also test the plugin', () async {
      gitDiffResponse = '''
packages/plugin1/plugin1.dart
packages/plugin1/ios/plugin1.m
''';
      final Directory plugin1 =
          createFakePlugin('plugin1', packagesDirectory: packagesDir);
      createFakePlugin('plugin2', packagesDirectory: packagesDir);
      await runner.run(
          <String>['sample', '--base-sha=master', '--run-on-changed-packages']);

      expect(plugins, unorderedEquals(<String>[plugin1.path]));
    });

    test('multiple plugins changed should test all the changed plugins',
        () async {
      gitDiffResponse = '''
packages/plugin1/plugin1.dart
packages/plugin2/ios/plugin2.m
''';
      final Directory plugin1 =
          createFakePlugin('plugin1', packagesDirectory: packagesDir);
      final Directory plugin2 =
          createFakePlugin('plugin2', packagesDirectory: packagesDir);
      createFakePlugin('plugin3', packagesDirectory: packagesDir);
      await runner.run(
          <String>['sample', '--base-sha=master', '--run-on-changed-packages']);

      expect(plugins, unorderedEquals(<String>[plugin1.path, plugin2.path]));
    });

    test(
        'multiple plugins inside the same plugin group changed should output the plugin group name',
        () async {
      gitDiffResponse = '''
packages/plugin1/plugin1/plugin1.dart
packages/plugin1/plugin1_platform_interface/plugin1_platform_interface.dart
packages/plugin1/plugin1_web/plugin1_web.dart
''';
      final Directory plugin1 = createFakePlugin('plugin1',
          parentDirectoryName: 'plugin1', packagesDirectory: packagesDir);
      createFakePlugin('plugin2', packagesDirectory: packagesDir);
      createFakePlugin('plugin3', packagesDirectory: packagesDir);
      await runner.run(
          <String>['sample', '--base-sha=master', '--run-on-changed-packages']);

      expect(plugins, unorderedEquals(<String>[plugin1.path]));
    });

    test('--plugins flag overrides the behavior of --run-on-changed-packages',
        () async {
      gitDiffResponse = '''
packages/plugin1/plugin1.dart
packages/plugin2/ios/plugin2.m
packages/plugin3/plugin3.dart
''';
      final Directory plugin1 = createFakePlugin('plugin1',
          parentDirectoryName: 'plugin1', packagesDirectory: packagesDir);
      final Directory plugin2 =
          createFakePlugin('plugin2', packagesDirectory: packagesDir);
      createFakePlugin('plugin3', packagesDirectory: packagesDir);
      await runner.run(<String>[
        'sample',
        '--plugins=plugin1,plugin2',
        '--base-sha=master',
        '--run-on-changed-packages'
      ]);

      expect(plugins, unorderedEquals(<String>[plugin1.path, plugin2.path]));
    });

    test('--exclude flag works with --run-on-changed-packages', () async {
      gitDiffResponse = '''
packages/plugin1/plugin1.dart
packages/plugin2/ios/plugin2.m
packages/plugin3/plugin3.dart
''';
      final Directory plugin1 = createFakePlugin('plugin1',
          parentDirectoryName: 'plugin1', packagesDirectory: packagesDir);
      createFakePlugin('plugin2', packagesDirectory: packagesDir);
      createFakePlugin('plugin3', packagesDirectory: packagesDir);
      await runner.run(<String>[
        'sample',
        '--exclude=plugin2,plugin3',
        '--base-sha=master',
        '--run-on-changed-packages'
      ]);

      expect(plugins, unorderedEquals(<String>[plugin1.path]));
    });
  });

  group('$GitVersionFinder', () {
    List<List<String>> gitDirCommands;
    String gitDiffResponse;
    String mergeBaseResponse;
    MockGitDir gitDir;

    setUp(() {
      gitDirCommands = <List<String>>[];
      gitDiffResponse = '';
      gitDir = MockGitDir();
      when(gitDir.runCommand(any)).thenAnswer((Invocation invocation) {
        gitDirCommands.add(invocation.positionalArguments[0] as List<String>);
        final MockProcessResult mockProcessResult = MockProcessResult();
        if (invocation.positionalArguments[0][0] == 'diff') {
          when<String>(mockProcessResult.stdout as String)
              .thenReturn(gitDiffResponse);
        } else if (invocation.positionalArguments[0][0] == 'merge-base') {
          when<String>(mockProcessResult.stdout as String)
              .thenReturn(mergeBaseResponse);
        }
        return Future<ProcessResult>.value(mockProcessResult);
      });
      initializeFakePackages();
      processRunner = RecordingProcessRunner();
    });

    tearDown(() {
      cleanupPackages();
    });

    test('No git diff should result no files changed', () async {
      final GitVersionFinder finder = GitVersionFinder(gitDir, 'some base sha');
      final List<String> changedFiles = await finder.getChangedFiles();

      expect(changedFiles, isEmpty);
    });

    test('get correct files changed based on git diff', () async {
      gitDiffResponse = '''
file1/file1.cc
file2/file2.cc
''';
      final GitVersionFinder finder = GitVersionFinder(gitDir, 'some base sha');
      final List<String> changedFiles = await finder.getChangedFiles();

      expect(
          changedFiles, equals(<String>['file1/file1.cc', 'file2/file2.cc']));
    });

    test('get correct pubspec change based on git diff', () async {
      gitDiffResponse = '''
file1/pubspec.yaml
file2/file2.cc
''';
      final GitVersionFinder finder = GitVersionFinder(gitDir, 'some base sha');
      final List<String> changedFiles = await finder.getChangedPubSpecs();

      expect(changedFiles, equals(<String>['file1/pubspec.yaml']));
    });

    test('use correct base sha if not specified', () async {
      mergeBaseResponse = 'shaqwiueroaaidf12312jnadf123nd';
      gitDiffResponse = '''
file1/pubspec.yaml
file2/file2.cc
''';
      final GitVersionFinder finder = GitVersionFinder(gitDir, null);
      await finder.getChangedFiles();
      verify(gitDir.runCommand(
          <String>['diff', '--name-only', mergeBaseResponse, 'HEAD']));
    });

    test('use correct base sha if specified', () async {
      const String customBaseSha = 'aklsjdcaskf12312';
      gitDiffResponse = '''
file1/pubspec.yaml
file2/file2.cc
''';
      final GitVersionFinder finder = GitVersionFinder(gitDir, customBaseSha);
      await finder.getChangedFiles();
      verify(gitDir
          .runCommand(<String>['diff', '--name-only', customBaseSha, 'HEAD']));
    });
  });

  group('$PubVersionFinder', () {
    test('Package does not exist.', () async {
      final MockClient mockClient = MockClient((http.Request request) async {
        return http.Response('', 404);
      });
      final PubVersionFinder finder = PubVersionFinder(httpClient: mockClient);
      final PubVersionFinderResponse response =
          await finder.getPackageVersion(package: 'some_package');

      expect(response.versions, isNull);
      expect(response.result, PubVersionFinderResult.noPackageFound);
      expect(response.httpResponse.statusCode, 404);
      expect(response.httpResponse.body, '');
    });

    test('HTTP error when getting versions from pub', () async {
      final MockClient mockClient = MockClient((http.Request request) async {
        return http.Response('', 400);
      });
      final PubVersionFinder finder = PubVersionFinder(httpClient: mockClient);
      final PubVersionFinderResponse response =
          await finder.getPackageVersion(package: 'some_package');

      expect(response.versions, isNull);
      expect(response.result, PubVersionFinderResult.fail);
      expect(response.httpResponse.statusCode, 400);
      expect(response.httpResponse.body, '');
    });

    test('Get a correct list of versions when http response is OK.', () async {
      const Map<String, dynamic> httpResponse = <String, dynamic>{
        'name': 'some_package',
        'versions': <String>[
          '0.0.1',
          '0.0.2',
          '0.0.2+2',
          '0.1.1',
          '0.0.1+1',
          '0.1.0',
          '0.2.0',
          '0.1.0+1',
          '0.0.2+1',
          '2.0.0',
          '1.2.0',
          '1.0.0',
        ],
      };
      final MockClient mockClient = MockClient((http.Request request) async {
        return http.Response(json.encode(httpResponse), 200);
      });
      final PubVersionFinder finder = PubVersionFinder(httpClient: mockClient);
      final PubVersionFinderResponse response =
          await finder.getPackageVersion(package: 'some_package');

      expect(response.versions, <Version>[
        Version.parse('2.0.0'),
        Version.parse('1.2.0'),
        Version.parse('1.0.0'),
        Version.parse('0.2.0'),
        Version.parse('0.1.1'),
        Version.parse('0.1.0+1'),
        Version.parse('0.1.0'),
        Version.parse('0.0.2+2'),
        Version.parse('0.0.2+1'),
        Version.parse('0.0.2'),
        Version.parse('0.0.1+1'),
        Version.parse('0.0.1'),
      ]);
      expect(response.result, PubVersionFinderResult.success);
      expect(response.httpResponse.statusCode, 200);
      expect(response.httpResponse.body, json.encode(httpResponse));
    });
  });
}

class SamplePluginCommand extends PluginCommand {
  SamplePluginCommand(
    this._plugins,
    Directory packagesDir,
    FileSystem fileSystem, {
    ProcessRunner processRunner = const ProcessRunner(),
    GitDir gitDir,
  }) : super(packagesDir, fileSystem,
            processRunner: processRunner, gitDir: gitDir);

  final List<String> _plugins;

  @override
  final String name = 'sample';

  @override
  final String description = 'sample command';

  @override
  Future<void> run() async {
    await for (final Directory package in getPlugins()) {
      _plugins.add(package.path);
    }
  }
}

class MockGitDir extends Mock implements GitDir {}

class MockProcessResult extends Mock implements ProcessResult {}
