// 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:async';
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/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:test/test.dart';

import 'common_test.mocks.dart';
import 'util.dart';

@GenerateMocks(<Type>[GitDir])
void main() {
  late RecordingProcessRunner processRunner;
  late CommandRunner<void> runner;
  late FileSystem fileSystem;
  late Directory packagesDir;
  late Directory thirdPartyPackagesDir;
  late List<String> plugins;
  late List<List<String>?> gitDirCommands;
  late 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, throwOnError: anyNamed('throwOnError')))
        .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', () {
    late List<List<String>?> gitDirCommands;
    late String gitDiffResponse;
    String? mergeBaseResponse;
    late MockGitDir gitDir;

    setUp(() {
      gitDirCommands = <List<String>?>[];
      gitDiffResponse = '';
      gitDir = MockGitDir();
      when(gitDir.runCommand(any, throwOnError: anyNamed('throwOnError')))
          .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 MockProcessResult extends Mock implements ProcessResult {}
