// 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 'package:args/command_runner.dart';
import 'package:conductor_core/src/git.dart';
import 'package:conductor_core/src/globals.dart';
import 'package:conductor_core/src/next.dart';
import 'package:conductor_core/src/proto/conductor_state.pb.dart' as pb;
import 'package:conductor_core/src/proto/conductor_state.pbenum.dart' show ReleasePhase;
import 'package:conductor_core/src/repository.dart';
import 'package:conductor_core/src/state.dart';
import 'package:conductor_core/src/stdio.dart';
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:platform/platform.dart';

import './common.dart';

void main() {
  const String flutterRoot = '/flutter';
  const String checkoutsParentDirectory = '$flutterRoot/dev/conductor';
  const String candidateBranch = 'flutter-1.2-candidate.3';
  const String workingBranch = 'cherrypicks-$candidateBranch';
  const String remoteUrl = 'https://github.com/org/repo.git';
  const String revision1 = 'd3af60d18e01fcb36e0c0fa06c8502e4935ed095';
  const String revision2 = 'f99555c1e1392bf2a8135056b9446680c2af4ddf';
  const String revision3 = 'ffffffffffffffffffffffffffffffffffffffff';
  const String revision4 = '280e23318a0d8341415c66aa32581352a421d974';
  const String releaseVersion = '1.2.0-3.0.pre';
  const String releaseChannel = 'beta';
  const String stateFile = '/state-file.json';
  final String localPathSeparator = const LocalPlatform().pathSeparator;
  final String localOperatingSystem = const LocalPlatform().operatingSystem;

  group('next command', () {
    late MemoryFileSystem fileSystem;
    late TestStdio stdio;

    setUp(() {
      stdio = TestStdio();
      fileSystem = MemoryFileSystem.test();
    });

    CommandRunner<void> createRunner({
      required Checkouts checkouts,
    }) {
      final NextCommand command = NextCommand(
        checkouts: checkouts,
      );
      return CommandRunner<void>('codesign-test', '')..addCommand(command);
    }

    test('throws if no state file found', () async {
      final FakeProcessManager processManager = FakeProcessManager.list(
        <FakeCommand>[],
      );
      final FakePlatform platform = FakePlatform(
        environment: <String, String>{
          'HOME': <String>['path', 'to', 'home'].join(localPathSeparator),
        },
        operatingSystem: localOperatingSystem,
        pathSeparator: localPathSeparator,
      );
      final Checkouts checkouts = Checkouts(
        fileSystem: fileSystem,
        parentDirectory: fileSystem.directory(checkoutsParentDirectory)..createSync(recursive: true),
        platform: platform,
        processManager: processManager,
        stdio: stdio,
      );
      final CommandRunner<void> runner = createRunner(checkouts: checkouts);
      expect(
        () async => runner.run(<String>[
          'next',
          '--$kStateOption',
          stateFile,
        ]),
        throwsExceptionWith('No persistent state file found at $stateFile'),
      );
    });

    group('APPLY_ENGINE_CHERRYPICKS to CODESIGN_ENGINE_BINARIES', () {
      test('does not prompt user and updates currentPhase if there are no engine cherrypicks', () async {
        final FakeProcessManager processManager = FakeProcessManager.empty();
        final FakePlatform platform = FakePlatform(
          environment: <String, String>{
            'HOME': <String>['path', 'to', 'home'].join(localPathSeparator),
          },
          operatingSystem: localOperatingSystem,
          pathSeparator: localPathSeparator,
        );
        final File ciYaml = fileSystem.file('$checkoutsParentDirectory/engine/.ci.yaml')
            ..createSync(recursive: true);
        // this branch already present in ciYaml
        _initializeCiYamlFile(ciYaml, enabledBranches: <String>[candidateBranch]);
        final pb.ConductorState state = pb.ConductorState(
          currentPhase: ReleasePhase.APPLY_ENGINE_CHERRYPICKS,
          engine: pb.Repository(
            candidateBranch: candidateBranch,
            checkoutPath: fileSystem.path.join(checkoutsParentDirectory, 'engine'),
            workingBranch: workingBranch,
            startingGitHead: revision1,
            upstream: pb.Remote(name: 'upstream', url: remoteUrl),
          ),
        );
        writeStateToFile(
          fileSystem.file(stateFile),
          state,
          <String>[],
        );
        final Checkouts checkouts = Checkouts(
          fileSystem: fileSystem,
          parentDirectory: fileSystem.directory(checkoutsParentDirectory)..createSync(recursive: true),
          platform: platform,
          processManager: processManager,
          stdio: stdio,
        );
        final CommandRunner<void> runner = createRunner(checkouts: checkouts);
        await runner.run(<String>[
          'next',
          '--$kStateOption',
          stateFile,
        ]);

        final pb.ConductorState finalState = readStateFromFile(
          fileSystem.file(stateFile),
        );

        expect(processManager, hasNoRemainingExpectations);
        expect(finalState.currentPhase, ReleasePhase.CODESIGN_ENGINE_BINARIES);
        expect(stdio.error, isEmpty);
        expect(
          stdio.stdout,
          contains('You must now codesign the engine binaries for commit $revision1'));
      });

      test('confirms to stdout when all engine cherrypicks were auto-applied', () async {
        stdio.stdin.add('n');
        final File ciYaml = fileSystem.file('$checkoutsParentDirectory/engine/.ci.yaml')
            ..createSync(recursive: true);
        _initializeCiYamlFile(ciYaml);
        final FakeProcessManager processManager = FakeProcessManager.empty();
        final FakePlatform platform = FakePlatform(
          environment: <String, String>{
            'HOME': <String>['path', 'to', 'home'].join(localPathSeparator),
          },
          operatingSystem: localOperatingSystem,
          pathSeparator: localPathSeparator,
        );
        final pb.ConductorState state = pb.ConductorState(
          engine: pb.Repository(
            candidateBranch: candidateBranch,
            cherrypicks: <pb.Cherrypick>[
              pb.Cherrypick(
                trunkRevision: 'abc123',
                state: pb.CherrypickState.COMPLETED,
              ),
            ],
            checkoutPath: fileSystem.path.join(checkoutsParentDirectory, 'engine'),
            workingBranch: workingBranch,
            upstream: pb.Remote(name: 'upstream', url: remoteUrl),
            mirror: pb.Remote(name: 'mirror', url: remoteUrl),
          ),
          currentPhase: ReleasePhase.APPLY_ENGINE_CHERRYPICKS,
        );
        writeStateToFile(
          fileSystem.file(stateFile),
          state,
          <String>[],
        );
        final Checkouts checkouts = Checkouts(
          fileSystem: fileSystem,
          parentDirectory: fileSystem.directory(checkoutsParentDirectory)..createSync(recursive: true),
          platform: platform,
          processManager: processManager,
          stdio: stdio,
        );
        final CommandRunner<void> runner = createRunner(checkouts: checkouts);
        await runner.run(<String>[
          'next',
          '--$kStateOption',
          stateFile,
        ]);

        expect(processManager, hasNoRemainingExpectations);
        expect(
          stdio.stdout,
          contains('All engine cherrypicks have been auto-applied by the conductor'),
        );
      });

      test('updates lastPhase if user responds yes', () async {
        const String remoteUrl = 'https://github.com/org/repo.git';
        const String releaseChannel = 'beta';
        stdio.stdin.add('y');
        final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
          const FakeCommand(
            command: <String>['git', 'fetch', 'upstream'],
          ),
          FakeCommand(
            command: const <String>['git', 'checkout', workingBranch],
            onRun: () {
              final File file = fileSystem.file('$checkoutsParentDirectory/engine/.ci.yaml')
                  ..createSync(recursive: true);
              _initializeCiYamlFile(file);
            },
          ),
          const FakeCommand(command: <String>['git', 'push', 'mirror', 'HEAD:refs/heads/$workingBranch']),
        ]);
        final FakePlatform platform = FakePlatform(
          environment: <String, String>{
            'HOME': <String>['path', 'to', 'home'].join(localPathSeparator),
          },
          operatingSystem: localOperatingSystem,
          pathSeparator: localPathSeparator,
        );
        final pb.ConductorState state = pb.ConductorState(
          currentPhase: ReleasePhase.APPLY_ENGINE_CHERRYPICKS,
          engine: pb.Repository(
            candidateBranch: candidateBranch,
            checkoutPath: fileSystem.path.join(checkoutsParentDirectory, 'engine'),
            cherrypicks: <pb.Cherrypick>[
              pb.Cherrypick(
                trunkRevision: revision2,
                state: pb.CherrypickState.PENDING,
              ),
            ],
            workingBranch: workingBranch,
            upstream: pb.Remote(name: 'upstream', url: remoteUrl),
            mirror: pb.Remote(name: 'mirror', url: remoteUrl),
          ),
          releaseChannel: releaseChannel,
          releaseVersion: releaseVersion,
        );
        writeStateToFile(
          fileSystem.file(stateFile),
          state,
          <String>[],
        );
        // engine dir is expected to already exist
        fileSystem.directory(checkoutsParentDirectory).childDirectory('engine').createSync(recursive: true);
        final Checkouts checkouts = Checkouts(
          fileSystem: fileSystem,
          parentDirectory: fileSystem.directory(checkoutsParentDirectory),
          platform: platform,
          processManager: processManager,
          stdio: stdio,
        );
        final CommandRunner<void> runner = createRunner(checkouts: checkouts);
        await runner.run(<String>[
          'next',
          '--$kStateOption',
          stateFile,
        ]);

        final pb.ConductorState finalState = readStateFromFile(
          fileSystem.file(stateFile),
        );

        expect(processManager, hasNoRemainingExpectations);
        expect(
          stdio.stdout,
          contains('You must now open a pull request at https://github.com/flutter/engine/compare/flutter-1.2-candidate.3...org:cherrypicks-flutter-1.2-candidate.3?expand=1'));
        expect(stdio.stdout, contains(
                'Are you ready to push your engine branch to the repository $remoteUrl? (y/n) '));
        expect(finalState.currentPhase, ReleasePhase.CODESIGN_ENGINE_BINARIES);
        expect(stdio.error, isEmpty);
      });
    });

    group('CODESIGN_ENGINE_BINARIES to APPLY_FRAMEWORK_CHERRYPICKS', () {
      late pb.ConductorState state;
      late FakeProcessManager processManager;
      late FakePlatform platform;

      setUp(() {
        state = pb.ConductorState(
          engine: pb.Repository(
            cherrypicks: <pb.Cherrypick>[
              pb.Cherrypick(
                trunkRevision: 'abc123',
                state: pb.CherrypickState.PENDING,
              ),
            ],
          ),
          currentPhase: ReleasePhase.CODESIGN_ENGINE_BINARIES,
        );

        processManager = FakeProcessManager.empty();

        platform = FakePlatform(
          environment: <String, String>{
            'HOME': <String>['path', 'to', 'home'].join(localPathSeparator),
          },
          operatingSystem: localOperatingSystem,
          pathSeparator: localPathSeparator,
        );
      });

      test('does not update currentPhase if user responds no', () async {
        stdio.stdin.add('n');
        writeStateToFile(
          fileSystem.file(stateFile),
          state,
          <String>[],
        );
        final Checkouts checkouts = Checkouts(
          fileSystem: fileSystem,
          parentDirectory: fileSystem.directory(checkoutsParentDirectory)..createSync(recursive: true),
          platform: platform,
          processManager: processManager,
          stdio: stdio,
        );
        final CommandRunner<void> runner = createRunner(checkouts: checkouts);
        await runner.run(<String>[
          'next',
          '--$kStateOption',
          stateFile,
        ]);

        final pb.ConductorState finalState = readStateFromFile(
          fileSystem.file(stateFile),
        );

        expect(processManager, hasNoRemainingExpectations);
        expect(stdio.stdout, contains('Has CI passed for the engine PR and binaries been codesigned? (y/n) '));
        expect(finalState.currentPhase, ReleasePhase.CODESIGN_ENGINE_BINARIES);
        expect(stdio.error.contains('Aborting command.'), true);
      });

      test('updates currentPhase if user responds yes', () async {
        stdio.stdin.add('y');
        final FakePlatform platform = FakePlatform(
          environment: <String, String>{
            'HOME': <String>['path', 'to', 'home'].join(localPathSeparator),
          },
          operatingSystem: localOperatingSystem,
          pathSeparator: localPathSeparator,
        );
        writeStateToFile(
          fileSystem.file(stateFile),
          state,
          <String>[],
        );
        final Checkouts checkouts = Checkouts(
          fileSystem: fileSystem,
          parentDirectory: fileSystem.directory(checkoutsParentDirectory)..createSync(recursive: true),
          platform: platform,
          processManager: processManager,
          stdio: stdio,
        );
        final CommandRunner<void> runner = createRunner(checkouts: checkouts);
        await runner.run(<String>[
          'next',
          '--$kStateOption',
          stateFile,
        ]);

        final pb.ConductorState finalState = readStateFromFile(
          fileSystem.file(stateFile),
        );

        expect(processManager, hasNoRemainingExpectations);
        expect(stdio.stdout, contains('Has CI passed for the engine PR and binaries been codesigned? (y/n) '));
        expect(finalState.currentPhase, ReleasePhase.APPLY_FRAMEWORK_CHERRYPICKS);
      });
    });

    group('APPLY_FRAMEWORK_CHERRYPICKS to PUBLISH_VERSION', () {
      const String mirrorRemoteUrl = 'https://github.com/org/repo.git';
      const String upstreamRemoteUrl = 'https://github.com/mirror/repo.git';
      const String engineUpstreamRemoteUrl = 'https://github.com/mirror/engine.git';
      const String frameworkCheckoutPath = '$checkoutsParentDirectory/framework';
      const String engineCheckoutPath = '$checkoutsParentDirectory/engine';
      const String oldEngineVersion = '000000001';
      const String frameworkCherrypick = '431ae69b4dd2dd48f7ba0153671e0311014c958b';
      late FakeProcessManager processManager;
      late FakePlatform platform;
      late pb.ConductorState state;

      setUp(() {
        processManager = FakeProcessManager.empty();
        platform = FakePlatform(
          environment: <String, String>{
            'HOME': <String>['path', 'to', 'home'].join(localPathSeparator),
          },
          operatingSystem: localOperatingSystem,
          pathSeparator: localPathSeparator,
        );
        state = pb.ConductorState(
          releaseChannel: releaseChannel,
          releaseVersion: releaseVersion,
          framework: pb.Repository(
            candidateBranch: candidateBranch,
            checkoutPath: frameworkCheckoutPath,
            cherrypicks: <pb.Cherrypick>[
              pb.Cherrypick(
                trunkRevision: frameworkCherrypick,
                state: pb.CherrypickState.PENDING,
              ),
            ],
            mirror: pb.Remote(name: 'mirror', url: mirrorRemoteUrl),
            upstream: pb.Remote(name: 'upstream', url: upstreamRemoteUrl),
            workingBranch: workingBranch,
          ),
          engine: pb.Repository(
            candidateBranch: candidateBranch,
            checkoutPath: engineCheckoutPath,
            dartRevision: 'cdef0123',
            workingBranch: workingBranch,
            upstream: pb.Remote(name: 'upstream', url: engineUpstreamRemoteUrl),
          ),
          currentPhase: ReleasePhase.APPLY_FRAMEWORK_CHERRYPICKS,
        );
        // create engine repo
        fileSystem.directory(engineCheckoutPath).createSync(recursive: true);
        // create framework repo
        final Directory frameworkDir = fileSystem.directory(frameworkCheckoutPath);
        final File engineRevisionFile = frameworkDir
            .childDirectory('bin')
            .childDirectory('internal')
            .childFile('engine.version');
        engineRevisionFile.createSync(recursive: true);
        engineRevisionFile.writeAsStringSync(oldEngineVersion, flush: true);
      });

      test('with no dart, engine or framework cherrypicks, no user input, no PR needed', () async {
        state = pb.ConductorState(
          framework: pb.Repository(
            candidateBranch: candidateBranch,
            checkoutPath: frameworkCheckoutPath,
            mirror: pb.Remote(name: 'mirror', url: mirrorRemoteUrl),
            upstream: pb.Remote(name: 'upstream', url: upstreamRemoteUrl),
            workingBranch: workingBranch,
          ),
          engine: pb.Repository(
            candidateBranch: candidateBranch,
            checkoutPath: engineCheckoutPath,
            upstream: pb.Remote(name: 'upstream', url: engineUpstreamRemoteUrl),
          ),
          currentPhase: ReleasePhase.APPLY_FRAMEWORK_CHERRYPICKS,
        );

        writeStateToFile(
          fileSystem.file(stateFile),
          state,
          <String>[],
        );

        final Checkouts checkouts = Checkouts(
          fileSystem: fileSystem,
          parentDirectory: fileSystem.directory(checkoutsParentDirectory)..createSync(recursive: true),
          platform: platform,
          processManager: processManager,
          stdio: stdio,
        );
        final CommandRunner<void> runner = createRunner(checkouts: checkouts);

        await runner.run(<String>[
          'next',
          '--$kStateOption',
          stateFile,
        ]);

        final pb.ConductorState finalState = readStateFromFile(
          fileSystem.file(stateFile),
        );

        expect(finalState.currentPhase, ReleasePhase.PUBLISH_VERSION);
        expect(stdio.error, isEmpty);
        expect(
          stdio.stdout,
          contains('pull request is not required'),
        );
      });

      test('with no engine cherrypicks but a dart revision update, updates engine revision', () async {
        stdio.stdin.add('n');
        processManager.addCommands(<FakeCommand>[
          const FakeCommand(command: <String>['git', 'fetch', 'upstream']),
          // we want merged upstream commit, not local working commit
          const FakeCommand(command: <String>['git', 'checkout', 'upstream/$candidateBranch']),
          const FakeCommand(
            command: <String>['git', 'rev-parse', 'HEAD'],
            stdout: revision1,
          ),
          const FakeCommand(command: <String>['git', 'fetch', 'upstream']),
          FakeCommand(
            command: const <String>['git', 'checkout', workingBranch],
            onRun: () {
              final File file = fileSystem.file('$checkoutsParentDirectory/framework/.ci.yaml')
                  ..createSync();
              _initializeCiYamlFile(file);
            },
          ),
          const FakeCommand(
            command: <String>['git', 'status', '--porcelain'],
            stdout: 'MM bin/internal/release-candidate-branch.version',
          ),
          const FakeCommand(command: <String>['git', 'add', '--all']),
          const FakeCommand(command: <String>[
            'git',
            'commit',
            '--message',
            'Create candidate branch version $candidateBranch for $releaseChannel',
          ]),
          const FakeCommand(
            command: <String>['git', 'rev-parse', 'HEAD'],
            stdout: revision3,
          ),
          const FakeCommand(
            command: <String>['git', 'status', '--porcelain'],
            stdout: 'MM bin/internal/engine.version',
          ),
          const FakeCommand(command: <String>['git', 'add', '--all']),
          const FakeCommand(command: <String>[
            'git',
            'commit',
            '--message',
            'Update Engine revision to $revision1 for $releaseChannel release $releaseVersion',
          ]),
          const FakeCommand(
            command: <String>['git', 'rev-parse', 'HEAD'],
            stdout: revision4,
          ),
        ]);
        final pb.ConductorState state = pb.ConductorState(
          releaseChannel: releaseChannel,
          releaseVersion: releaseVersion,
          currentPhase: ReleasePhase.APPLY_FRAMEWORK_CHERRYPICKS,
          framework: pb.Repository(
            candidateBranch: candidateBranch,
            checkoutPath: frameworkCheckoutPath,
            mirror: pb.Remote(name: 'mirror', url: mirrorRemoteUrl),
            upstream: pb.Remote(name: 'upstream', url: upstreamRemoteUrl),
            workingBranch: workingBranch,
          ),
          engine: pb.Repository(
            candidateBranch: candidateBranch,
            checkoutPath: engineCheckoutPath,
            upstream: pb.Remote(name: 'upstream', url: engineUpstreamRemoteUrl),
            dartRevision: 'abc123',
          ),
        );
        writeStateToFile(
          fileSystem.file(stateFile),
          state,
          <String>[],
        );
        final Checkouts checkouts = Checkouts(
          fileSystem: fileSystem,
          parentDirectory: fileSystem.directory(checkoutsParentDirectory)..createSync(recursive: true),
          platform: platform,
          processManager: processManager,
          stdio: stdio,
        );
        final CommandRunner<void> runner = createRunner(checkouts: checkouts);
        await runner.run(<String>[
          'next',
          '--$kStateOption',
          stateFile,
        ]);

        expect(processManager, hasNoRemainingExpectations);
        expect(stdio.stdout, contains('release-candidate-branch.version containing $candidateBranch'));
        expect(stdio.stdout, contains('Updating engine revision from $oldEngineVersion to $revision1'));
        expect(stdio.stdout, contains('Are you ready to push your framework branch'));
      });

      test('does not update state.currentPhase if user responds no', () async {
        stdio.stdin.add('n');
        processManager.addCommands(<FakeCommand>[
          const FakeCommand(command: <String>['git', 'fetch', 'upstream']),
          // we want merged upstream commit, not local working commit
          FakeCommand(
            command: const <String>['git', 'checkout', 'upstream/$candidateBranch'],
            onRun: () {
              final File file = fileSystem.file('$checkoutsParentDirectory/framework/.ci.yaml')
                  ..createSync();
              _initializeCiYamlFile(file);
            },
          ),
          const FakeCommand(
            command: <String>['git', 'rev-parse', 'HEAD'],
            stdout: revision1,
          ),
          const FakeCommand(command: <String>['git', 'fetch', 'upstream']),
          const FakeCommand(command: <String>['git', 'checkout', workingBranch]),
          const FakeCommand(
            command: <String>['git', 'status', '--porcelain'],
            stdout: 'MM bin/internal/release-candidate-branch.version',
          ),
          const FakeCommand(command: <String>['git', 'add', '--all']),
          const FakeCommand(command: <String>[
            'git',
            'commit',
            '--message',
            'Create candidate branch version $candidateBranch for $releaseChannel',
          ]),
          const FakeCommand(
            command: <String>['git', 'rev-parse', 'HEAD'],
            stdout: revision3,
          ),
          const FakeCommand(
            command: <String>['git', 'status', '--porcelain'],
            stdout: 'MM bin/internal/engine.version',
          ),
          const FakeCommand(command: <String>['git', 'add', '--all']),
          const FakeCommand(command: <String>[
            'git',
            'commit',
            '--message',
            'Update Engine revision to $revision1 for $releaseChannel release $releaseVersion',
          ]),
          const FakeCommand(
            command: <String>['git', 'rev-parse', 'HEAD'],
            stdout: revision4,
          ),
        ]);
        writeStateToFile(
          fileSystem.file(stateFile),
          state,
          <String>[],
        );
        final Checkouts checkouts = Checkouts(
          fileSystem: fileSystem,
          parentDirectory: fileSystem.directory(checkoutsParentDirectory)..createSync(recursive: true),
          platform: platform,
          processManager: processManager,
          stdio: stdio,
        );
        final CommandRunner<void> runner = createRunner(checkouts: checkouts);
        await runner.run(<String>[
          'next',
          '--$kStateOption',
          stateFile,
        ]);

        final pb.ConductorState finalState = readStateFromFile(
          fileSystem.file(stateFile),
        );

        expect(stdio.stdout, contains('Are you ready to push your framework branch to the repository $mirrorRemoteUrl? (y/n) '));
        expect(stdio.error, contains('Aborting command.'));
        expect(finalState.currentPhase, ReleasePhase.APPLY_FRAMEWORK_CHERRYPICKS);
      });

      test('updates state.currentPhase if user responds yes', () async {
        stdio.stdin.add('y');
        processManager.addCommands(<FakeCommand>[
          // Engine repo
          const FakeCommand(command: <String>['git', 'fetch', 'upstream']),
          // we want merged upstream commit, not local working commit
          const FakeCommand(command: <String>['git', 'checkout', 'upstream/$candidateBranch']),
          const FakeCommand(
            command: <String>['git', 'rev-parse', 'HEAD'],
            stdout: revision1,
          ),
          // Framework repo
          const FakeCommand(command: <String>['git', 'fetch', 'upstream']),
          FakeCommand(
            command: const <String>['git', 'checkout', workingBranch],
            onRun: () {
              final File file = fileSystem.file('$checkoutsParentDirectory/framework/.ci.yaml')
                  ..createSync();
              _initializeCiYamlFile(file);
            },
          ),
          const FakeCommand(
            command: <String>['git', 'status', '--porcelain'],
            stdout: 'MM bin/internal/release-candidate-branch.version',
          ),
          const FakeCommand(command: <String>['git', 'add', '--all']),
          const FakeCommand(command: <String>[
            'git',
            'commit',
            '--message',
            'Create candidate branch version $candidateBranch for $releaseChannel',
          ]),
          const FakeCommand(
            command: <String>['git', 'rev-parse', 'HEAD'],
            stdout: revision3,
          ),
          const FakeCommand(
            command: <String>['git', 'status', '--porcelain'],
            stdout: 'MM bin/internal/engine.version',
          ),
          const FakeCommand(command: <String>['git', 'add', '--all']),
          const FakeCommand(command: <String>[
            'git',
            'commit',
            '--message',
            'Update Engine revision to $revision1 for $releaseChannel release $releaseVersion',
          ]),
          const FakeCommand(
            command: <String>['git', 'rev-parse', 'HEAD'],
            stdout: revision4,
          ),
          const FakeCommand(
            command: <String>['git', 'push', 'mirror', 'HEAD:refs/heads/$workingBranch'],
          ),
        ]);
        writeStateToFile(
          fileSystem.file(stateFile),
          state,
          <String>[],
        );
        final Checkouts checkouts = Checkouts(
          fileSystem: fileSystem,
          parentDirectory: fileSystem.directory(checkoutsParentDirectory)..createSync(recursive: true),
          platform: platform,
          processManager: processManager,
          stdio: stdio,
        );
        final CommandRunner<void> runner = createRunner(checkouts: checkouts);
        await runner.run(<String>[
          'next',
          '--$kStateOption',
          stateFile,
        ]);

        final pb.ConductorState finalState = readStateFromFile(
          fileSystem.file(stateFile),
        );

        expect(finalState.currentPhase, ReleasePhase.PUBLISH_VERSION);
        expect(
          stdio.stdout,
          contains('Rolling new engine hash $revision1 to framework checkout...'),
        );
        expect(
          stdio.stdout,
          contains('There was 1 cherrypick that was not auto-applied'),
        );
        expect(
          stdio.stdout,
          contains('Are you ready to push your framework branch to the repository $mirrorRemoteUrl? (y/n)'),
        );
        expect(
          stdio.stdout,
          contains('Executed command: `git push mirror HEAD:refs/heads/$workingBranch`'),
        );
        expect(stdio.error, isEmpty);
      });
    });

    group('PUBLISH_VERSION to PUBLISH_CHANNEL', () {
      const String remoteName = 'upstream';
      const String releaseVersion = '1.2.0-3.0.pre';
      late pb.ConductorState state;
      late FakePlatform platform;

      setUp(() {
        state = pb.ConductorState(
          currentPhase: ReleasePhase.PUBLISH_VERSION,
          framework: pb.Repository(
            candidateBranch: candidateBranch,
            upstream: pb.Remote(url: FrameworkRepository.defaultUpstream),
          ),
          releaseVersion: releaseVersion,
        );
        platform = FakePlatform(
          environment: <String, String>{
            'HOME': <String>['path', 'to', 'home'].join(localPathSeparator),
          },
          operatingSystem: localOperatingSystem,
          pathSeparator: localPathSeparator,
        );
      });

      test('does not update state.currentPhase if user responds no', () async {
        stdio.stdin.add('n');
        final FakeProcessManager processManager = FakeProcessManager.list(
          <FakeCommand>[
            const FakeCommand(
              command: <String>['git', 'fetch', 'upstream'],
            ),
            const FakeCommand(
              command: <String>['git', 'checkout', '$remoteName/$candidateBranch'],
            ),
            const FakeCommand(
              command: <String>['git', 'rev-parse', 'HEAD'],
              stdout: revision1,
            ),
          ],
        );
        writeStateToFile(
          fileSystem.file(stateFile),
          state,
          <String>[],
        );
        final Checkouts checkouts = Checkouts(
          fileSystem: fileSystem,
          parentDirectory: fileSystem.directory(checkoutsParentDirectory)..createSync(recursive: true),
          platform: platform,
          processManager: processManager,
          stdio: stdio,
        );
        final CommandRunner<void> runner = createRunner(checkouts: checkouts);
        await runner.run(<String>[
          'next',
          '--$kStateOption',
          stateFile,
        ]);

        final pb.ConductorState finalState = readStateFromFile(
          fileSystem.file(stateFile),
        );

        expect(processManager, hasNoRemainingExpectations);
        expect(stdio.stdout, contains('Are you ready to tag commit $revision1 as $releaseVersion'));
        expect(stdio.error, contains('Aborting command.'));
        expect(finalState.currentPhase, ReleasePhase.PUBLISH_VERSION);
        expect(finalState.logs, stdio.logs);
      });

      test('updates state.currentPhase if user responds yes', () async {
        stdio.stdin.add('y');
        final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
          const FakeCommand(
            command: <String>['git', 'fetch', 'upstream'],
          ),
          const FakeCommand(
            command: <String>['git', 'checkout', '$remoteName/$candidateBranch'],
          ),
          const FakeCommand(
            command: <String>['git', 'rev-parse', 'HEAD'],
            stdout: revision1,
          ),
          const FakeCommand(
            command: <String>['git', 'tag', releaseVersion, revision1],
          ),
          const FakeCommand(
            command: <String>['git', 'push', remoteName, releaseVersion],
          ),
        ]);
        final FakePlatform platform = FakePlatform(
          environment: <String, String>{
            'HOME': <String>['path', 'to', 'home'].join(localPathSeparator),
          },
          operatingSystem: localOperatingSystem,
          pathSeparator: localPathSeparator,
        );
        writeStateToFile(
          fileSystem.file(stateFile),
          state,
          <String>[],
        );
        final Checkouts checkouts = Checkouts(
          fileSystem: fileSystem,
          parentDirectory: fileSystem.directory(checkoutsParentDirectory)..createSync(recursive: true),
          platform: platform,
          processManager: processManager,
          stdio: stdio,
        );
        final CommandRunner<void> runner = createRunner(checkouts: checkouts);
        await runner.run(<String>[
          'next',
          '--$kStateOption',
          stateFile,
        ]);

        final pb.ConductorState finalState = readStateFromFile(
          fileSystem.file(stateFile),
        );

        expect(processManager, hasNoRemainingExpectations);
        expect(finalState.currentPhase, ReleasePhase.PUBLISH_CHANNEL);
        expect(stdio.stdout, contains('Are you ready to tag commit $revision1 as $releaseVersion'));
        expect(finalState.logs, stdio.logs);
      });
    });

    group('PUBLISH_CHANNEL to VERIFY_RELEASE', () {
      const String remoteName = 'upstream';
      late pb.ConductorState state;
      late FakePlatform platform;

      setUp(() {
        state = pb.ConductorState(
          currentPhase: ReleasePhase.PUBLISH_CHANNEL,
          framework: pb.Repository(
            candidateBranch: candidateBranch,
            upstream: pb.Remote(url: FrameworkRepository.defaultUpstream),
          ),
          releaseChannel: releaseChannel,
          releaseVersion: releaseVersion,
        );
        platform = FakePlatform(
          environment: <String, String>{
            'HOME': <String>['path', 'to', 'home'].join(localPathSeparator),
          },
          operatingSystem: localOperatingSystem,
          pathSeparator: localPathSeparator,
        );
      });

      test('does not update currentPhase if user responds no', () async {
        stdio.stdin.add('n');
        final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
          const FakeCommand(
            command: <String>['git', 'fetch', 'upstream'],
          ),
          const FakeCommand(
            command: <String>['git', 'checkout', '$remoteName/$candidateBranch'],
          ),
          const FakeCommand(
            command: <String>['git', 'rev-parse', 'HEAD'],
            stdout: revision1,
          ),
        ]);
        writeStateToFile(
          fileSystem.file(stateFile),
          state,
          <String>[],
        );
        final Checkouts checkouts = Checkouts(
          fileSystem: fileSystem,
          parentDirectory: fileSystem.directory(checkoutsParentDirectory)..createSync(recursive: true),
          platform: platform,
          processManager: processManager,
          stdio: stdio,
        );
        final CommandRunner<void> runner = createRunner(checkouts: checkouts);
        await runner.run(<String>[
          'next',
          '--$kStateOption',
          stateFile,
        ]);

        final pb.ConductorState finalState = readStateFromFile(
          fileSystem.file(stateFile),
        );

        expect(processManager, hasNoRemainingExpectations);
        expect(stdio.error, contains('Aborting command.'));
        expect(
          stdio.stdout,
          contains('About to execute command: `git push ${FrameworkRepository.defaultUpstream} $revision1:$releaseChannel`'),
        );
        expect(finalState.currentPhase, ReleasePhase.PUBLISH_CHANNEL);
      });

      test('updates currentPhase if user responds yes', () async {
        stdio.stdin.add('y');
        // for kSynchronizeDevWithBeta
        stdio.stdin.add('y');
        final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
          const FakeCommand(
            command: <String>['git', 'fetch', 'upstream'],
          ),
          const FakeCommand(
            command: <String>['git', 'checkout', '$remoteName/$candidateBranch'],
          ),
          const FakeCommand(
            command: <String>['git', 'rev-parse', 'HEAD'],
            stdout: revision1,
          ),
          const FakeCommand(
            command: <String>['git', 'push', FrameworkRepository.defaultUpstream, '$revision1:$releaseChannel'],
          ),
          // for kSynchronizeDevWithBeta
          const FakeCommand(
            command: <String>['git', 'push', FrameworkRepository.defaultUpstream, '$revision1:dev'],
          ),
        ]);
        writeStateToFile(
          fileSystem.file(stateFile),
          state,
          <String>[],
        );
        final Checkouts checkouts = Checkouts(
          fileSystem: fileSystem,
          parentDirectory: fileSystem.directory(checkoutsParentDirectory)..createSync(recursive: true),
          platform: platform,
          processManager: processManager,
          stdio: stdio,
        );
        final CommandRunner<void> runner = createRunner(checkouts: checkouts);
        await runner.run(<String>[
          'next',
          '--$kStateOption',
          stateFile,
        ]);

        final pb.ConductorState finalState = readStateFromFile(
          fileSystem.file(stateFile),
        );

        expect(processManager, hasNoRemainingExpectations);
        expect(stdio.error, isEmpty);
        expect(
          stdio.stdout,
          contains('About to execute command: `git push ${FrameworkRepository.defaultUpstream} $revision1:$releaseChannel`'),
        );
        expect(
          stdio.stdout,
          contains('Release archive packages must be verified on cloud storage: https://ci.chromium.org/p/flutter/g/beta_packaging/console'),
        );
        expect(finalState.currentPhase, ReleasePhase.VERIFY_RELEASE);
      });
    });

    test('throws exception if state.currentPhase is RELEASE_COMPLETED', () async {
      final FakeProcessManager processManager = FakeProcessManager.empty();
      final FakePlatform platform = FakePlatform(
        environment: <String, String>{
          'HOME': <String>['path', 'to', 'home'].join(localPathSeparator),
        },
        operatingSystem: localOperatingSystem,
        pathSeparator: localPathSeparator,
      );
      final pb.ConductorState state = pb.ConductorState(
        currentPhase: ReleasePhase.RELEASE_COMPLETED,
      );
      writeStateToFile(
        fileSystem.file(stateFile),
        state,
        <String>[],
      );
      final Checkouts checkouts = Checkouts(
        fileSystem: fileSystem,
        parentDirectory: fileSystem.directory(checkoutsParentDirectory)..createSync(recursive: true),
        platform: platform,
        processManager: processManager,
        stdio: stdio,
      );
      final CommandRunner<void> runner = createRunner(checkouts: checkouts);
      expect(
        () async => runner.run(<String>[
          'next',
          '--$kStateOption',
          stateFile,
        ]),
        throwsExceptionWith('This release is finished.'),
      );
    });
  }, onPlatform: <String, dynamic>{
    'windows': const Skip('Flutter Conductor only supported on macos/linux'),
  });

  group('prompt', () {
    test('can be overridden for different frontend implementations', () async {
      final FileSystem fileSystem = MemoryFileSystem.test();
      final Stdio stdio = _UnimplementedStdio.instance;
      final Checkouts checkouts = Checkouts(
        fileSystem: fileSystem,
        parentDirectory: fileSystem.directory('/'),
        platform: FakePlatform(),
        processManager: FakeProcessManager.empty(),
        stdio: stdio,
      );
      final _TestNextContext context = _TestNextContext(
        checkouts: checkouts,
        stateFile: fileSystem.file('/statefile.json'),
      );

      final bool response = await context.prompt(
        'A prompt that will immediately be agreed to',
      );
      expect(response, true);
    });

    test('throws if user inputs character that is not "y" or "n"', () {
      final FileSystem fileSystem = MemoryFileSystem.test();
      final TestStdio stdio = TestStdio(
        stdin: <String>['x'],
        verbose: true,
      );
      final Checkouts checkouts = Checkouts(
        fileSystem: fileSystem,
        parentDirectory: fileSystem.directory('/'),
        platform: FakePlatform(),
        processManager: FakeProcessManager.empty(),
        stdio: stdio,
      );
      final NextContext context = NextContext(
        autoAccept: false,
        force: false,
        checkouts: checkouts,
        stateFile: fileSystem.file('/statefile.json'),
      );

      expect(
        () => context.prompt('Asking a question?'),
        throwsExceptionWith('Unknown user input (expected "y" or "n")'),
      );
    });
  });

  group('.pushWorkingBranch()', () {
    late MemoryFileSystem fileSystem;
    late TestStdio stdio;
    late Platform platform;

    setUp(() {
      stdio = TestStdio();
      fileSystem = MemoryFileSystem.test();
      platform = FakePlatform();
    });

    test('catches GitException if the push was rejected and instead throws a helpful ConductorException', () async {
      const String gitPushErrorMessage = '''
 To github.com:user/engine.git

  ! [rejected]            HEAD -> cherrypicks-flutter-2.8-candidate.3 (non-fast-forward)
 error: failed to push some refs to 'github.com:user/engine.git'
 hint: Updates were rejected because the tip of your current branch is behind
 hint: its remote counterpart. Integrate the remote changes (e.g.
 hint: 'git pull ...') before pushing again.
 hint: See the 'Note about fast-forwards' in 'git push --help' for details.
''';
      final Checkouts checkouts = Checkouts(
        fileSystem: fileSystem,
        parentDirectory: fileSystem.directory(checkoutsParentDirectory)..createSync(recursive: true),
        platform: platform,
        processManager: FakeProcessManager.empty(),
        stdio: stdio,
      );
      final Repository testRepository = _TestRepository.fromCheckouts(checkouts);
      final pb.Repository testPbRepository = pb.Repository();
      (checkouts.processManager as FakeProcessManager).addCommands(<FakeCommand>[
        FakeCommand(
          command: <String>['git', 'clone', '--origin', 'upstream', '--', testRepository.upstreamRemote.url, '/flutter/dev/conductor/flutter_conductor_checkouts/test-repo/test-repo'],
        ),
        const FakeCommand(
          command: <String>['git', 'rev-parse', 'HEAD'],
          stdout: revision1,
        ),
        FakeCommand(
          command: const <String>['git', 'push', '', 'HEAD:refs/heads/'],
          exception: GitException(gitPushErrorMessage, <String>['git', 'push', '--force', '', 'HEAD:refs/heads/']),
        ),
      ]);
      final NextContext nextContext = NextContext(
        autoAccept: false,
        checkouts: checkouts,
        force: false,
        stateFile: fileSystem.file(stateFile),
      );

      expect(
        () => nextContext.pushWorkingBranch(testRepository, testPbRepository),
        throwsA(isA<ConductorException>().having(
          (ConductorException exception) => exception.message,
          'has correct message',
          contains('Re-run this command with --force to overwrite the remote branch'),
        )),
      );
    });
  });
}

/// A [Stdio] that will throw an exception if any of its methods are called.
class _UnimplementedStdio implements Stdio {
  const _UnimplementedStdio();

  static const _UnimplementedStdio _instance = _UnimplementedStdio();
  static _UnimplementedStdio get instance => _instance;

  Never _throw() => throw Exception('Unimplemented!');

  @override
  List<String> get logs => _throw();

  @override
  void printError(String message) => _throw();

  @override
  void printWarning(String message) => _throw();

  @override
  void printStatus(String message) => _throw();

  @override
  void printTrace(String message) => _throw();

  @override
  void write(String message) => _throw();

  @override
  String readLineSync() => _throw();
}

class _TestRepository extends Repository {
  _TestRepository.fromCheckouts(Checkouts checkouts, [String name = 'test-repo']) : super(
    fileSystem: checkouts.fileSystem,
    parentDirectory: checkouts.directory.childDirectory(name),
    platform: checkouts.platform,
    processManager: checkouts.processManager,
    name: name,
    requiredLocalBranches: <String>[],
    stdio: checkouts.stdio,
    upstreamRemote: const Remote(name: RemoteName.upstream, url: 'git@github.com:upstream/repo.git'),
  );

  @override
  Future<_TestRepository> cloneRepository(String? cloneName) async {
    throw Exception('Unimplemented!');
  }
}

class _TestNextContext extends NextContext {
  const _TestNextContext({
    required super.stateFile,
    required super.checkouts,
  }) : super(autoAccept: false, force: false);

  @override
  Future<bool> prompt(String message) {
    // always say yes
    return Future<bool>.value(true);
  }
}

void _initializeCiYamlFile(
  File file, {
  List<String>? enabledBranches,
}) {
  enabledBranches ??= <String>['master', 'beta', 'stable'];
  file.createSync(recursive: true);
  final StringBuffer buffer = StringBuffer('enabled_branches:\n');
  for (final String branch in enabledBranches) {
    buffer.writeln('  - $branch');
  }
  buffer.writeln('''

platform_properties:
  linux:
    properties:
    caches: ["name":"openjdk","path":"java"]

targets:
  - name: Linux analyze
    recipe: flutter/flutter
    timeout: 60
    properties:
      tags: >
        ["framework","hostonly"]
      validation: analyze
      validation_name: Analyze
    scheduler: luci
''');
  file.writeAsStringSync(buffer.toString());
}
