// 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:file/file.dart' show File;
import 'package:meta/meta.dart' show visibleForTesting, visibleForOverriding;
import './globals.dart';
import './proto/conductor_state.pb.dart' as pb;
import './proto/conductor_state.pbenum.dart';
import './repository.dart';
import './state.dart' as state_import;
import './stdio.dart';

const String kStateOption = 'state-file';
const String kYesFlag = 'yes';
const String kForceFlag = 'force';

/// Command to proceed from one [pb.ReleasePhase] to the next.
class NextCommand extends Command<void> {
  NextCommand({
    required this.checkouts,
  }) {
    final String defaultPath = state_import.defaultStateFilePath(checkouts.platform);
    argParser.addOption(
      kStateOption,
      defaultsTo: defaultPath,
      help: 'Path to persistent state file. Defaults to $defaultPath',
    );
    argParser.addFlag(
      kYesFlag,
      help: 'Auto-accept any confirmation prompts.',
      hide: true, // primarily for integration testing
    );
    argParser.addFlag(
      kForceFlag,
      help: 'Force push when updating remote git branches.',
    );
  }

  final Checkouts checkouts;

  @override
  String get name => 'next';

  @override
  String get description => 'Proceed to the next release phase.';

  @override
  Future<void> run() async {
    await NextContext(
      autoAccept: argResults![kYesFlag] as bool,
      checkouts: checkouts,
      force: argResults![kForceFlag] as bool,
      stateFile: checkouts.fileSystem.file(argResults![kStateOption]),
    ).run();
  }
}

/// Utility class for proceeding to the next step in a release.
///
/// Any calls to functions that cause side effects are wrapped in methods to
/// allow overriding in unit tests.
class NextContext {
  NextContext({
    required this.autoAccept,
    required this.force,
    required this.checkouts,
    required this.stateFile,
  });

  final bool autoAccept;
  final bool force;
  final Checkouts checkouts;
  final File stateFile;

  Future<void> run() async {
    final Stdio stdio = checkouts.stdio;
    const List<CherrypickState> finishedStates = <CherrypickState>[
      CherrypickState.COMPLETED,
      CherrypickState.ABANDONED,
    ];
    if (!stateFile.existsSync()) {
      throw ConductorException(
          'No persistent state file found at ${stateFile.path}.',
      );
    }

    final pb.ConductorState state = readStateFromFile(stateFile);

    switch (state.currentPhase) {
      case pb.ReleasePhase.APPLY_ENGINE_CHERRYPICKS:
        final Remote upstream = Remote(
            name: RemoteName.upstream,
            url: state.engine.upstream.url,
        );
        final EngineRepository engine = EngineRepository(
            checkouts,
            initialRef: state.engine.workingBranch,
            upstreamRemote: upstream,
            previousCheckoutLocation: state.engine.checkoutPath,
        );
        // check if the candidate branch is enabled in .ci.yaml
        final CiYaml engineCiYaml = await engine.ciYaml;
        if (!engineCiYaml.enabledBranches.contains(state.engine.candidateBranch)) {
          engineCiYaml.enableBranch(state.engine.candidateBranch);
          // commit
          final String revision = await engine.commit(
              'add branch ${state.engine.candidateBranch} to enabled_branches in .ci.yaml',
              addFirst: true,
          );
          // append to list of cherrypicks so we know a PR is required
          state.engine.cherrypicks.add(pb.Cherrypick(
                  appliedRevision: revision,
                  state: pb.CherrypickState.COMPLETED,
          ));
        }

        if (!state_import.requiresEnginePR(state)) {
          stdio.printStatus(
              'This release has no engine cherrypicks. No Engine PR is necessary.\n',
          );
          break;
        }

        final List<pb.Cherrypick> unappliedCherrypicks = <pb.Cherrypick>[];
        for (final pb.Cherrypick cherrypick in state.engine.cherrypicks) {
          if (!finishedStates.contains(cherrypick.state)) {
            unappliedCherrypicks.add(cherrypick);
          }
        }

        if (unappliedCherrypicks.isEmpty) {
          stdio.printStatus('All engine cherrypicks have been auto-applied by the conductor.\n');
        } else {
          if (unappliedCherrypicks.length == 1) {
            stdio.printStatus('There was ${unappliedCherrypicks.length} cherrypick that was not auto-applied.');
          } else {
            stdio.printStatus('There were ${unappliedCherrypicks.length} cherrypicks that were not auto-applied.');
          }
          stdio.printStatus('These must be applied manually in the directory '
              '${state.engine.checkoutPath} before proceeding.\n');
        }
        if (autoAccept == false) {
          final bool response = prompt(
              'Are you ready to push your engine branch to the repository '
              '${state.engine.mirror.url}?',
              stdio,
          );
          if (!response) {
            stdio.printError('Aborting command.');
            writeStateToFile(stateFile, state, stdio.logs);
            return;
          }
        }

        await engine.pushRef(
            fromRef: 'HEAD',
            // Explicitly create new branch
            toRef: 'refs/heads/${state.engine.workingBranch}',
            remote: state.engine.mirror.name,
        );

        break;
      case pb.ReleasePhase.CODESIGN_ENGINE_BINARIES:
        stdio.printStatus(<String>[
          'You must validate pre-submit CI for your engine PR, merge it, and codesign',
          'binaries before proceeding.\n',
        ].join('\n'));
        if (autoAccept == false) {
          // TODO(fujino): actually test if binaries have been codesigned on macOS
          final bool response = prompt(
              'Has CI passed for the engine PR and binaries been codesigned?',
              stdio,
          );
          if (!response) {
            stdio.printError('Aborting command.');
            writeStateToFile(stateFile, state, stdio.logs);
            return;
          }
        }
        break;
      case pb.ReleasePhase.APPLY_FRAMEWORK_CHERRYPICKS:
        if (state.engine.cherrypicks.isEmpty && state.engine.dartRevision.isEmpty) {
          stdio.printStatus(
              'This release has no engine cherrypicks, and thus the engine.version file\n'
              'in the framework does not need to be updated.',
          );

          if (state.framework.cherrypicks.isEmpty) {
            stdio.printStatus(
                'This release also has no framework cherrypicks. Therefore, a framework\n'
                'pull request is not required.',
            );
            break;
          }
        }
        final Remote engineUpstreamRemote = Remote(
            name: RemoteName.upstream,
            url: state.engine.upstream.url,
        );
        final EngineRepository engine = EngineRepository(
            checkouts,
            // We explicitly want to check out the merged version from upstream
            initialRef: '${engineUpstreamRemote.name}/${state.engine.candidateBranch}',
            upstreamRemote: engineUpstreamRemote,
            previousCheckoutLocation: state.engine.checkoutPath,
        );

        final String engineRevision = await engine.reverseParse('HEAD');

        final Remote upstream = Remote(
            name: RemoteName.upstream,
            url: state.framework.upstream.url,
        );
        final FrameworkRepository framework = FrameworkRepository(
            checkouts,
            initialRef: state.framework.workingBranch,
            upstreamRemote: upstream,
            previousCheckoutLocation: state.framework.checkoutPath,
        );

        // Check if the current candidate branch is enabled
        if (!(await framework.ciYaml).enabledBranches.contains(state.framework.candidateBranch)) {
          (await framework.ciYaml).enableBranch(state.framework.candidateBranch);
          // commit
          final String revision = await framework.commit(
              'add branch ${state.framework.candidateBranch} to enabled_branches in .ci.yaml',
              addFirst: true,
          );
          // append to list of cherrypicks so we know a PR is required
          state.framework.cherrypicks.add(pb.Cherrypick(
                  appliedRevision: revision,
                  state: pb.CherrypickState.COMPLETED,
          ));
        }

        stdio.printStatus('Rolling new engine hash $engineRevision to framework checkout...');
        final bool needsCommit = await framework.updateEngineRevision(engineRevision);
        if (needsCommit) {
          final String revision = await framework.commit(
              'Update Engine revision to $engineRevision for ${state.releaseChannel} release ${state.releaseVersion}',
              addFirst: true,
          );
          // append to list of cherrypicks so we know a PR is required
          state.framework.cherrypicks.add(pb.Cherrypick(
                  appliedRevision: revision,
                  state: pb.CherrypickState.COMPLETED,
          ));
        }

        final List<pb.Cherrypick> unappliedCherrypicks = <pb.Cherrypick>[];
        for (final pb.Cherrypick cherrypick in state.framework.cherrypicks) {
          if (!finishedStates.contains(cherrypick.state)) {
            unappliedCherrypicks.add(cherrypick);
          }
        }

        if (state.framework.cherrypicks.isEmpty) {
          stdio.printStatus(
              'This release has no framework cherrypicks. However, a framework PR is still\n'
              'required to roll engine cherrypicks.',
          );
        } else if (unappliedCherrypicks.isEmpty) {
          stdio.printStatus('All framework cherrypicks were auto-applied by the conductor.');
        } else {
          if (unappliedCherrypicks.length == 1) {
            stdio.printStatus('There was ${unappliedCherrypicks.length} cherrypick that was not auto-applied.',);
          }
          else {
            stdio.printStatus('There were ${unappliedCherrypicks.length} cherrypicks that were not auto-applied.',);
          }
          stdio.printStatus(
              'These must be applied manually in the directory '
              '${state.framework.checkoutPath} before proceeding.\n',
          );
        }

        if (autoAccept == false) {
          final bool response = prompt(
              'Are you ready to push your framework branch to the repository '
              '${state.framework.mirror.url}?',
              stdio,
          );
          if (!response) {
            stdio.printError('Aborting command.');
            writeStateToFile(stateFile, state, stdio.logs);
            return;
          }
        }

        await framework.pushRef(
            fromRef: 'HEAD',
            // Explicitly create new branch
            toRef: 'refs/heads/${state.framework.workingBranch}',
            remote: state.framework.mirror.name,
        );
        break;
      case pb.ReleasePhase.PUBLISH_VERSION:
        stdio.printStatus('Please ensure that you have merged your framework PR and that');
        stdio.printStatus('post-submit CI has finished successfully.\n');
        final Remote upstream = Remote(
            name: RemoteName.upstream,
            url: state.framework.upstream.url,
        );
        final FrameworkRepository framework = FrameworkRepository(
            checkouts,
            // We explicitly want to check out the merged version from upstream
            initialRef: '${upstream.name}/${state.framework.candidateBranch}',
            upstreamRemote: upstream,
            previousCheckoutLocation: state.framework.checkoutPath,
        );
        final String headRevision = await framework.reverseParse('HEAD');
        if (autoAccept == false) {
          final bool response = prompt(
              'Are you ready to tag commit $headRevision as ${state.releaseVersion}\n'
              'and push to remote ${state.framework.upstream.url}?',
              stdio,
          );
          if (!response) {
            stdio.printError('Aborting command.');
            writeStateToFile(stateFile, state, stdio.logs);
            return;
          }
        }
        await framework.tag(headRevision, state.releaseVersion, upstream.name);
        break;
      case pb.ReleasePhase.PUBLISH_CHANNEL:
        final Remote upstream = Remote(
            name: RemoteName.upstream,
            url: state.framework.upstream.url,
        );
        final FrameworkRepository framework = FrameworkRepository(
            checkouts,
            // We explicitly want to check out the merged version from upstream
            initialRef: '${upstream.name}/${state.framework.candidateBranch}',
            upstreamRemote: upstream,
            previousCheckoutLocation: state.framework.checkoutPath,
        );
        final String headRevision = await framework.reverseParse('HEAD');
        if (autoAccept == false) {
          // dryRun: true means print out git command
          await framework.pushRef(
              fromRef: headRevision,
              toRef: state.releaseChannel,
              remote: state.framework.upstream.url,
              force: force,
              dryRun: true,
          );

          final bool response = prompt(
              'Are you ready to publish this release?',
              stdio,
          );
          if (!response) {
            stdio.printError('Aborting command.');
            writeStateToFile(stateFile, state, stdio.logs);
            return;
          }
        }
        await framework.pushRef(
            fromRef: headRevision,
            toRef: state.releaseChannel,
            remote: state.framework.upstream.url,
            force: force,
        );
        break;
      case pb.ReleasePhase.VERIFY_RELEASE:
        stdio.printStatus(
            'The current status of packaging builds can be seen at:\n'
            '\t$kLuciPackagingConsoleLink',
        );
        if (autoAccept == false) {
          final bool response = prompt(
              'Have all packaging builds finished successfully?',
              stdio,
          );
          if (!response) {
            stdio.printError('Aborting command.');
            writeStateToFile(stateFile, state, stdio.logs);
            return;
          }
        }
        break;
      case pb.ReleasePhase.RELEASE_COMPLETED:
        throw ConductorException('This release is finished.');
    }
    final ReleasePhase nextPhase = state_import.getNextPhase(state.currentPhase);
    stdio.printStatus('\nUpdating phase from ${state.currentPhase} to $nextPhase...\n');
    state.currentPhase = nextPhase;
    stdio.printStatus(state_import.phaseInstructions(state));

    writeStateToFile(stateFile, state, stdio.logs);
  }

  /// Persist the state to a file.
  @visibleForOverriding
  void writeStateToFile(File file, pb.ConductorState state, [List<String> logs = const <String>[]]) {
    state_import.writeStateToFile(file, state, logs);
  }

  @visibleForTesting
  bool prompt(String message, Stdio stdio) {
    stdio.write('${message.trim()} (y/n) ');
    final String response = stdio.readLineSync().trim();
    final String firstChar = response[0].toUpperCase();
    if (firstChar == 'Y') {
      return true;
    }
    if (firstChar == 'N') {
      return false;
    }
    throw ConductorException(
      'Unknown user input (expected "y" or "n"): $response',
    );
  }

  /// Read the state from a file.
  @visibleForOverriding
  pb.ConductorState readStateFromFile(File file) => state_import.readStateFromFile(file);
}
