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

import 'package:args/command_runner.dart';
import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:flutter_plugin_tools/src/publish_plugin_command.dart';
import 'package:flutter_plugin_tools/src/common.dart';
import 'package:git/git.dart';
import 'package:matcher/matcher.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';

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

void main() {
  const String testPluginName = 'foo';
  final List<String> printedMessages = <String>[];

  Directory parentDir;
  Directory pluginDir;
  GitDir gitDir;
  TestProcessRunner processRunner;
  CommandRunner<void> commandRunner;
  MockStdin mockStdin;

  setUp(() async {
    // This test uses a local file system instead of an in memory one throughout
    // so that git actually works. In setup we initialize a mono repo of plugins
    // with one package and commit everything to Git.
    parentDir = const LocalFileSystem()
        .systemTempDirectory
        .createTempSync('publish_plugin_command_test-');
    initializeFakePackages(parentDir: parentDir);
    pluginDir = createFakePlugin(testPluginName, withSingleExample: false);
    assert(pluginDir != null && pluginDir.existsSync());
    createFakePubspec(pluginDir, includeVersion: true);
    io.Process.runSync('git', <String>['init'],
        workingDirectory: mockPackagesDir.path);
    gitDir = await GitDir.fromExisting(mockPackagesDir.path);
    await gitDir.runCommand(<String>['add', '-A']);
    await gitDir.runCommand(<String>['commit', '-m', 'Initial commit']);
    processRunner = TestProcessRunner();
    mockStdin = MockStdin();
    commandRunner = CommandRunner<void>('tester', '')
      ..addCommand(PublishPluginCommand(
          mockPackagesDir, mockPackagesDir.fileSystem,
          processRunner: processRunner,
          print: (Object message) => printedMessages.add(message.toString()),
          stdinput: mockStdin));
  });

  tearDown(() {
    parentDir.deleteSync(recursive: true);
    printedMessages.clear();
  });

  group('Initial validation', () {
    test('requires a package flag', () async {
      await expectLater(() => commandRunner.run(<String>['publish-plugin']),
          throwsA(const TypeMatcher<ToolExit>()));
      expect(
          printedMessages.last, contains('Must specify a package to publish.'));
    });

    test('requires an existing flag', () async {
      await expectLater(
          () => commandRunner.run(<String>[
                'publish-plugin',
                '--package',
                'iamerror',
                '--no-push-tags'
              ]),
          throwsA(const TypeMatcher<ToolExit>()));

      expect(printedMessages.last, contains('iamerror does not exist'));
    });

    test('refuses to proceed with dirty files', () async {
      pluginDir.childFile('tmp').createSync();

      await expectLater(
          () => commandRunner.run(<String>[
                'publish-plugin',
                '--package',
                testPluginName,
                '--no-push-tags'
              ]),
          throwsA(const TypeMatcher<ToolExit>()));

      expect(
          printedMessages.last,
          contains(
              "There are files in the package directory that haven't been saved in git."));
    });

    test('fails immediately if the remote doesn\'t exist', () async {
      await expectLater(
          () => commandRunner
              .run(<String>['publish-plugin', '--package', testPluginName]),
          throwsA(const TypeMatcher<ToolExit>()));
      expect(processRunner.results.last.stderr, contains('No such remote'));
    });

    test("doesn't validate the remote if it's not pushing tags", () async {
      // Immediately return 0 when running `pub publish`.
      processRunner.mockPublishProcess.exitCodeCompleter.complete(0);

      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--no-push-tags',
        '--no-tag-release'
      ]);

      expect(printedMessages.last, 'Done!');
    });

    test('can publish non-flutter package', () async {
      createFakePubspec(pluginDir, includeVersion: true, isFlutter: false);
      io.Process.runSync('git', <String>['init'],
          workingDirectory: mockPackagesDir.path);
      gitDir = await GitDir.fromExisting(mockPackagesDir.path);
      await gitDir.runCommand(<String>['add', '-A']);
      await gitDir.runCommand(<String>['commit', '-m', 'Initial commit']);
      // Immediately return 0 when running `pub publish`.
      processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--no-push-tags',
        '--no-tag-release'
      ]);
      expect(printedMessages.last, 'Done!');
    });
  });

  group('Publishes package', () {
    test('while showing all output from pub publish to the user', () async {
      final Future<void> publishCommand = commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--no-push-tags',
        '--no-tag-release'
      ]);
      processRunner.mockPublishProcess.stdoutController.add(utf8.encode('Foo'));
      processRunner.mockPublishProcess.stderrController.add(utf8.encode('Bar'));
      processRunner.mockPublishProcess.exitCodeCompleter.complete(0);

      await publishCommand;

      expect(printedMessages, contains('Foo'));
      expect(printedMessages, contains('Bar'));
    });

    test('forwards input from the user to `pub publish`', () async {
      final Future<void> publishCommand = commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--no-push-tags',
        '--no-tag-release'
      ]);
      mockStdin.controller.add(utf8.encode('user input'));
      processRunner.mockPublishProcess.exitCodeCompleter.complete(0);

      await publishCommand;

      expect(processRunner.mockPublishProcess.stdinMock.lines,
          contains('user input'));
    });

    test('forwards --pub-publish-flags to pub publish', () async {
      processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--no-push-tags',
        '--no-tag-release',
        '--pub-publish-flags',
        '--dry-run,--server=foo'
      ]);

      expect(processRunner.mockPublishArgs.length, 4);
      expect(processRunner.mockPublishArgs[0], 'pub');
      expect(processRunner.mockPublishArgs[1], 'publish');
      expect(processRunner.mockPublishArgs[2], '--dry-run');
      expect(processRunner.mockPublishArgs[3], '--server=foo');
    });

    test('throws if pub publish fails', () async {
      processRunner.mockPublishProcess.exitCodeCompleter.complete(128);
      await expectLater(
          () => commandRunner.run(<String>[
                'publish-plugin',
                '--package',
                testPluginName,
                '--no-push-tags',
                '--no-tag-release',
              ]),
          throwsA(const TypeMatcher<ToolExit>()));

      expect(printedMessages, contains('Publish failed. Exiting.'));
    });
  });

  group('Tags release', () {
    test('with the version and name from the pubspec.yaml', () async {
      processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--no-push-tags',
      ]);

      final String tag =
          (await gitDir.runCommand(<String>['show-ref', 'fake_package-v0.0.1']))
              .stdout as String;
      expect(tag, isNotEmpty);
    });

    test('only if publishing succeeded', () async {
      processRunner.mockPublishProcess.exitCodeCompleter.complete(128);
      await expectLater(
          () => commandRunner.run(<String>[
                'publish-plugin',
                '--package',
                testPluginName,
                '--no-push-tags',
              ]),
          throwsA(const TypeMatcher<ToolExit>()));

      expect(printedMessages, contains('Publish failed. Exiting.'));
      final String tag = (await gitDir.runCommand(
              <String>['show-ref', 'fake_package-v0.0.1'],
              throwOnError: false))
          .stdout as String;
      expect(tag, isEmpty);
    });
  });

  group('Pushes tags', () {
    setUp(() async {
      await gitDir.runCommand(
          <String>['remote', 'add', 'upstream', 'http://localhost:8000']);
    });

    test('requires user confirmation', () async {
      processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
      mockStdin.readLineOutput = 'help';
      await expectLater(
          () => commandRunner.run(<String>[
                'publish-plugin',
                '--package',
                testPluginName,
              ]),
          throwsA(const TypeMatcher<ToolExit>()));

      expect(printedMessages, contains('Tag push canceled.'));
    });

    test('to upstream by default', () async {
      await gitDir.runCommand(<String>['tag', 'garbage']);
      processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
      mockStdin.readLineOutput = 'y';
      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
      ]);

      expect(processRunner.pushTagsArgs.isNotEmpty, isTrue);
      expect(processRunner.pushTagsArgs[1], 'upstream');
      expect(processRunner.pushTagsArgs[2], 'fake_package-v0.0.1');
      expect(printedMessages.last, 'Done!');
    });

    test('to different remotes based on a flag', () async {
      await gitDir.runCommand(
          <String>['remote', 'add', 'origin', 'http://localhost:8001']);
      processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
      mockStdin.readLineOutput = 'y';
      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--remote',
        'origin',
      ]);

      expect(processRunner.pushTagsArgs.isNotEmpty, isTrue);
      expect(processRunner.pushTagsArgs[1], 'origin');
      expect(processRunner.pushTagsArgs[2], 'fake_package-v0.0.1');
      expect(printedMessages.last, 'Done!');
    });

    test('only if tagging and pushing to remotes are both enabled', () async {
      processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--no-tag-release',
      ]);

      expect(processRunner.pushTagsArgs.isEmpty, isTrue);
      expect(printedMessages.last, 'Done!');
    });
  });
}

class TestProcessRunner extends ProcessRunner {
  final List<io.ProcessResult> results = <io.ProcessResult>[];
  final MockProcess mockPublishProcess = MockProcess();
  final List<String> mockPublishArgs = <String>[];
  final MockProcessResult mockPushTagsResult = MockProcessResult();
  final List<String> pushTagsArgs = <String>[];

  @override
  Future<io.ProcessResult> runAndExitOnError(
    String executable,
    List<String> args, {
    Directory workingDir,
  }) async {
    // Don't ever really push tags.
    if (executable == 'git' && args.isNotEmpty && args[0] == 'push') {
      pushTagsArgs.addAll(args);
      return mockPushTagsResult;
    }

    final io.ProcessResult result = io.Process.runSync(executable, args,
        workingDirectory: workingDir?.path);
    results.add(result);
    if (result.exitCode != 0) {
      throw ToolExit(result.exitCode);
    }
    return result;
  }

  @override
  Future<io.Process> start(String executable, List<String> args,
      {Directory workingDirectory}) async {
    /// Never actually publish anything. Start is always and only used for this
    /// since it returns something we can route stdin through.
    assert(executable == 'flutter' &&
        args.isNotEmpty &&
        args[0] == 'pub' &&
        args[1] == 'publish');
    mockPublishArgs.addAll(args);
    return mockPublishProcess;
  }
}

class MockStdin extends Mock implements io.Stdin {
  final StreamController<List<int>> controller = StreamController<List<int>>();
  String readLineOutput;

  @override
  Stream<S> transform<S>(StreamTransformer<List<int>, S> streamTransformer) {
    return controller.stream.transform(streamTransformer);
  }

  @override
  StreamSubscription<List<int>> listen(void onData(List<int> event),
      {Function onError, void onDone(), bool cancelOnError}) {
    return controller.stream.listen(onData,
        onError: onError, onDone: onDone, cancelOnError: cancelOnError);
  }

  @override
  String readLineSync(
          {Encoding encoding = io.systemEncoding,
          bool retainNewlines = false}) =>
      readLineOutput;
}

class MockProcessResult extends Mock implements io.ProcessResult {}
