// Copyright 2019 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:io';

import 'package:args/args.dart';

const String cloudbuildDirectory = 'cloud_build';
const String workspaceDirectory = '../';

const String gcloudProjectIdFlag = 'project';
const String gcloudProjectIdAbbrFlag = 'p';

const String gcloudProjectVersionFlag = 'version';
const String gcloudProjectVersionAbbrFlag = 'v';

const String ignoreVersionFlag = 'ignore-version-check';
const String helpFlag = 'help';

String? _gcloudProjectId;
String? _gcloudProjectVersion;

late bool _ignoreVersion;

/// Check if [gcloudProjectIdFlag] and [gcloudProjectVersionFlag]
/// were passed as arguments. If they were, also set [_gcloudProjectId]
/// and [_gcloudProjectVersion] accordingly.
bool _getArgs(ArgParser argParser, List<String> arguments) {
  final args = argParser.parse(arguments);

  final printHelpMessage = args[helpFlag] as bool;
  if (printHelpMessage) {
    return false;
  }

  _gcloudProjectId = args[gcloudProjectIdFlag] as String?;
  _gcloudProjectVersion = args[gcloudProjectVersionFlag] as String?;
  _ignoreVersion = args[ignoreVersionFlag] as bool;

  if (_gcloudProjectId == null) {
    stderr.write('--$gcloudProjectIdFlag must be defined\n');
    return false;
  }

  if (_gcloudProjectVersion == null) {
    stderr.write('--$gcloudProjectVersionFlag must be defined\n');
    return false;
  }

  return true;
}

/// Check the Flutter version installed and make sure it is a recent version
/// from the past 21 days.
///
/// Flutter tools handles the rest of the checks (e.g. Dart version) when
/// building the project.
Future<bool> _checkDependencies() async {
  if (_ignoreVersion) {
    return true;
  }

  stdout.writeln('Checking Flutter version via flutter --version');
  final result = await Process.run('flutter', <String>['--version']);
  final flutterVersionOutput = result.stdout as String;

  // This makes an assumption that only the framework will have its version
  // printed out with the date in YYYY-MM-DD format.
  final dateRegExp = RegExp(
    r'([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))',
  );
  final flutterVersionDateRaw = dateRegExp
      .allMatches(flutterVersionOutput)
      .first
      .group(0)!;

  final flutterVersionDate = DateTime.parse(flutterVersionDateRaw);
  final now = DateTime.now();
  final lastUpdateToFlutter = now.difference(flutterVersionDate);

  return lastUpdateToFlutter.inDays < 21;
}

/// Run the Google Cloud CLI tool to deploy to [_gcloudProjectId] under
/// version [_gcloudProjectVersion].
Future<bool> _deployToAppEngine() async {
  stdout.writeln('Deploying to AppEngine');

  /// The Google Cloud deployment command is an interactive process. It will
  /// print out what it is about to do, and ask for confirmation (Y/n).
  final process = await Process.start('gcloud', <String>[
    'app',
    'deploy',
    '--project',
    _gcloudProjectId!,
    '--version',
    _gcloudProjectVersion!,
    '--no-promote',
    '--no-stop-previous-version',
    '--quiet',
  ]);

  /// Let this user confirm the details before Google Cloud sends for deployment.
  unawaited(stdin.pipe(process.stdin));

  await process.stderr.pipe(stderr);
  await process.stdout.pipe(stdout);

  return await process.exitCode == 0;
}

/// Run [args] in bash shell and validate it finshes with exit code 0.
Future<void> shellCommand(List<String> args) async {
  final result = await Process.run(
    'bash',
    args,
    workingDirectory: workspaceDirectory,
  );

  if (result.exitCode != 0) {
    print('$args failed with exit code ${result.exitCode}');
    print('stdout: ${result.stdout}');
    print('stderr: ${result.stderr}');
    exit(1);
  }
}

Future<void> main(List<String> arguments) async {
  final argParser = ArgParser()
    ..addOption(gcloudProjectIdFlag, abbr: gcloudProjectIdAbbrFlag)
    ..addOption(gcloudProjectVersionFlag, abbr: gcloudProjectVersionAbbrFlag)
    ..addFlag(ignoreVersionFlag)
    ..addFlag(helpFlag);

  if (!_getArgs(argParser, arguments)) {
    stdout.write(
      'Required flags:\n'
      '--$gcloudProjectIdFlag gcp-id\n'
      '--$gcloudProjectVersionFlag version\n\n'
      'Optional flags:\n'
      '--$ignoreVersionFlag\tForce deploy with current Flutter version\n',
    );
    exit(1);
  }

  if (!await _checkDependencies()) {
    stderr.writeln(
      'Update Flutter to a version on master from the past 3 weeks to deploy Cocoon',
    );
    exit(1);
  }

  await shellCommand(<String>['$cloudbuildDirectory/dashboard_build.sh']);

  if (!await _deployToAppEngine()) {
    stderr.writeln('Failed to deploy to AppEngine');
    exit(1);
  }
}
