// Copyright 2013 The Flutter Authors
// 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:file/file.dart';
import 'package:git/git.dart';
import 'package:http/http.dart' as http;
import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
import 'package:platform/platform.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart';

import 'common/core.dart';
import 'common/file_utils.dart';
import 'common/output_utils.dart';
import 'common/package_command.dart';
import 'common/package_looping_command.dart';
import 'common/pub_utils.dart';
import 'common/pub_version_finder.dart';
import 'common/repository_package.dart';

@immutable
class _RemoteInfo {
  const _RemoteInfo({required this.name, required this.url});

  /// The git name for the remote.
  final String name;

  /// The remote's URL.
  final String url;
}

/// Wraps pub publish with a few niceties used by the flutter/plugin team.
///
/// 1. Checks for any modified files in git and refuses to publish if there's an
///    issue.
/// 2. Tags the release with the format `<package-name>-v<package-version>`.
/// 3. Pushes the release to a remote.
///
/// Both 2 and 3 are optional, see `plugin_tools help publish` for full
/// usage information.
///
/// [processRunner], [print], and [stdin] can be overriden for easier testing.
class PublishCommand extends PackageLoopingCommand {
  /// Creates an instance of the publish command.
  PublishCommand(
    super.packagesDir, {
    super.processRunner,
    super.platform,
    io.Stdin? stdinput,
    super.gitDir,
    http.Client? httpClient,
  }) : _pubVersionFinder = PubVersionFinder(httpClient: httpClient ?? http.Client()),
       _stdin = stdinput ?? io.stdin {
    argParser.addFlag(
      _alreadyTaggedFlag,
      help:
          'Instead of tagging, validates that the current checkout is already tagged with the expected version.\n'
          'This is primarily intended for use in CI publish steps triggered by tagging.',
      negatable: false,
    );
    argParser.addMultiOption(
      _pubFlagsOption,
      help:
          'A list of options that will be forwarded on to pub. Separate multiple flags with commas.',
    );
    argParser.addOption(
      _remoteOption,
      help: 'The name of the remote to push the tags to.',
      // Flutter convention is to use "upstream" for the single source of truth, and "origin" for personal forks.
      defaultsTo: 'upstream',
    );
    argParser.addFlag(
      _allChangedFlag,
      help:
          'Release all packages that contains pubspec changes at the current commit compares to the base-sha.\n'
          'The --packages option is ignored if this is on.',
    );
    argParser.addOption(
      _batchReleaseBranchOption,
      help: 'batch release a package from its release branch',
    );
    argParser.addFlag(
      _dryRunFlag,
      help:
          'Skips the real `pub publish` and `git tag` commands and assumes both commands are successful.\n'
          'This does not run `pub publish --dry-run`.\n'
          'If you want to run the command with `pub publish --dry-run`, use `pub-publish-flags=--dry-run`',
    );
    argParser.addFlag(
      _skipConfirmationFlag,
      help:
          'Run the command without asking for Y/N inputs.\n'
          'This command will add a `--force` flag to the `pub publish` command if it is not added with $_pubFlagsOption\n',
    );
    argParser.addFlag(
      _tagForAutoPublishFlag,
      help:
          'Runs the dry-run publish, and tags if it succeeds, but does not actually publish.\n'
          'This is intended for use with a separate publish step that is based on tag push events.',
      negatable: false,
    );
  }

  static const String _alreadyTaggedFlag = 'already-tagged';
  static const String _pubFlagsOption = 'pub-publish-flags';
  static const String _remoteOption = 'remote';
  static const String _allChangedFlag = 'all-changed';
  static const String _batchReleaseBranchOption = 'batch-release-branch';
  static const String _dryRunFlag = 'dry-run';
  static const String _skipConfirmationFlag = 'skip-confirmation';
  static const String _tagForAutoPublishFlag = 'tag-for-auto-publish';

  static const String _pubCredentialName = 'PUB_CREDENTIALS';

  // Version tags should follow <package-name>-v<semantic-version>. For example,
  // `flutter_plugin_tools-v0.0.24`.
  static const String _tagFormat = '%PACKAGE%-v%VERSION%';

  /// Returns the correct path where the pub credential is stored.
  @visibleForTesting
  late final String credentialsPath = _getCredentialsPath(platform: platform, path: path);

  @override
  final String name = 'publish';

  @override
  final String description =
      'Attempts to publish the given packages and tag the release(s) on GitHub.\n'
      'If running this on CI, an environment variable named $_pubCredentialName must be set to a String that represents the pub credential JSON.\n'
      'WARNING: Do not check in the content of pub credential JSON, it should only come from secure sources.';

  final io.Stdin _stdin;
  StreamSubscription<String>? _stdinSubscription;
  final PubVersionFinder _pubVersionFinder;

  // Tags that already exist in the repository.
  List<String> _existingGitTags = <String>[];
  // The remote to push tags to.
  late _RemoteInfo _remote;
  // Flags to pass to `pub publish`.
  late List<String> _publishFlags;

  @override
  String get successSummaryMessage => 'published';

  @override
  String get failureListHeader => 'The following packages had failures during publishing:';

  @override
  Future<void> initializeRun() async {
    print('Checking local repo...');

    // Ensure that the requested remote is present.
    final String remoteName = getStringArg(_remoteOption);
    final String? remoteUrl = await _verifyRemote(remoteName);
    if (remoteUrl == null) {
      printError('Unable to find URL for remote $remoteName; cannot push tags');
      throw ToolExit(1);
    }
    _remote = _RemoteInfo(name: remoteName, url: remoteUrl);

    // Pre-fetch all the repository's tags, to check against when publishing.
    final GitDir repository = await gitDir;
    final io.ProcessResult existingTagsResult = await repository.runCommand(<String>[
      'tag',
      '--sort=-committerdate',
    ]);
    _existingGitTags = (existingTagsResult.stdout as String).split('\n')
      ..removeWhere((String element) => element.isEmpty);

    _publishFlags = <String>[
      ...getStringListArg(_pubFlagsOption),
      if (getBoolArg(_skipConfirmationFlag)) '--force',
    ];

    if (getBoolArg(_dryRunFlag)) {
      print('=============== DRY RUN ===============');
    }
  }

  @override
  Stream<PackageEnumerationEntry> getPackagesToProcess() async* {
    final String batchReleaseBranchName = getStringArg(_batchReleaseBranchOption);
    if (getBoolArg(_allChangedFlag)) {
      print('Publishing all packages that have changed relative to "$baseSha"\n');

      final List<String> changedPubspecs = changedFiles
          .where((String file) => file.trim().endsWith('pubspec.yaml'))
          .toList();

      for (final pubspecPath in changedPubspecs) {
        // Read the ci_config.yaml file if it exists
        final String packageName = p.basename(p.dirname(pubspecPath));
        final bool isBatchReleasePackage;
        try {
          final File ciConfigFile = RepositoryPackage(
            packagesDir.fileSystem.file(pubspecPath).parent,
          ).ciConfigFile;

          if (!ciConfigFile.existsSync()) {
            isBatchReleasePackage = false;
          } else {
            final ciConfig = CIConfig.parse(ciConfigFile.readAsStringSync());
            isBatchReleasePackage = ciConfig.isBatchRelease;
          }
        } catch (e) {
          printError('Could not parse ci_config.yaml for $packageName: $e');
          throw ToolExit(exitCommandFoundErrors);
        }

        // When releasing from the main branch, skip the batch release packages.
        if (batchReleaseBranchName.isEmpty) {
          if (isBatchReleasePackage) {
            continue;
          }
        } else {
          // When releasing from a batch release branch, verify the package has
          // the opt-in flag and that the package name matches the branch suffix.
          // Example: branch "release-go_router" matches package "go_router".
          if (!isBatchReleasePackage ||
              !batchReleaseBranchName.startsWith('release-$packageName-')) {
            continue;
          }
        }

        // git outputs a relativa, Posix-style path.
        final File pubspecFile = childFileWithSubcomponents(
          packagesDir.fileSystem.directory((await gitDir).path),
          p.posix.split(pubspecPath),
        );
        yield PackageEnumerationEntry(RepositoryPackage(pubspecFile.parent), excluded: false);
      }
    } else {
      yield* getTargetPackages(filterExcluded: false);
    }
  }

  @override
  Future<PackageResult> runForPackage(RepositoryPackage package) async {
    final PackageResult? checkResult = await _checkNeedsRelease(package);
    if (checkResult != null) {
      return checkResult;
    }

    if (!await _runPrePublishScript(package)) {
      return PackageResult.fail(<String>['pre-publish failed']);
    }

    if (!await _checkGitStatus(package)) {
      return PackageResult.fail(<String>['uncommitted changes']);
    }

    final bool tagOnly = getBoolArg(_tagForAutoPublishFlag);
    if (!tagOnly) {
      if (!await _publish(package)) {
        return PackageResult.fail(<String>['publish failed']);
      }
    }

    final String tag = _getTag(package);
    if (getBoolArg(_alreadyTaggedFlag)) {
      if (!(await _getCurrentTags()).contains(tag)) {
        printError('The current checkout is not already tagged "$tag"');
        return PackageResult.fail(<String>['missing tag']);
      }
    } else {
      if (!await _tagRelease(package, tag)) {
        return PackageResult.fail(<String>['tagging failed']);
      }
    }

    final action = tagOnly ? 'Tagged' : 'Published';
    print('\n$action ${package.directory.basename} successfully!');
    return PackageResult.success();
  }

  @override
  Future<void> completeRun() async {
    _pubVersionFinder.httpClient.close();
    await _stdinSubscription?.cancel();
    _stdinSubscription = null;
  }

  /// Checks whether [package] needs to be released, printing check status and
  /// returning one of:
  /// - PackageResult.fail if the check could not be completed
  /// - PackageResult.skip if no release is necessary
  /// - null if releasing should proceed
  ///
  /// In cases where a non-null result is returned, that should be returned
  /// as the final result for the package, without further processing.
  Future<PackageResult?> _checkNeedsRelease(RepositoryPackage package) async {
    if (!package.pubspecFile.existsSync()) {
      logWarning('''
The pubspec file for ${package.displayName} does not exist, so no publishing will happen.
Safe to ignore if the package is deleted in this commit.
''');
      return PackageResult.skip('package deleted');
    }

    final Pubspec pubspec = package.parsePubspec();

    if (pubspec.name == 'flutter_plugin_tools') {
      // Ignore flutter_plugin_tools package when running publishing through flutter_plugin_tools.
      // TODO(cyanglaz): Make the tool also auto publish flutter_plugin_tools package.
      // https://github.com/flutter/flutter/issues/85430
      return PackageResult.skip('publishing flutter_plugin_tools via the tool is not supported');
    }

    if (pubspec.publishTo == 'none') {
      return PackageResult.skip('publish_to: none');
    }

    if (pubspec.version == null) {
      printError(
        'No version found. A package that intentionally has no version should be marked "publish_to: none"',
      );
      return PackageResult.fail(<String>['no version']);
    }

    // Check if the package named `packageName` with `version` has already
    // been published.
    final Version version = pubspec.version!;
    final PubVersionFinderResponse pubVersionFinderResponse = await _pubVersionFinder
        .getPackageVersion(packageName: pubspec.name);
    if (pubVersionFinderResponse.versions.contains(version)) {
      final String tagsForPackageWithSameVersion = _existingGitTags.firstWhere(
        (String tag) =>
            tag.split('-v').first == pubspec.name && tag.split('-v').last == version.toString(),
        orElse: () => '',
      );
      if (tagsForPackageWithSameVersion.isEmpty) {
        printError(
          '${pubspec.name} $version has already been published, however '
          'the git release tag (${pubspec.name}-v$version) was not found. '
          'Please manually fix the tag then run the command again.',
        );
        return PackageResult.fail(<String>['published but untagged']);
      } else {
        print('${pubspec.name} $version has already been published.');
        return PackageResult.skip('already published');
      }
    }
    return null;
  }

  // Tag the release with <package-name>-v<version>, and push it to the remote.
  //
  // Return `true` if successful, `false` otherwise.
  Future<bool> _tagRelease(RepositoryPackage package, String tag) async {
    print('Tagging release $tag...');
    if (!getBoolArg(_dryRunFlag)) {
      final io.ProcessResult result = await (await gitDir).runCommand(<String>[
        'tag',
        tag,
      ], throwOnError: false);
      if (result.exitCode != 0) {
        return false;
      }
    }

    print('Pushing tag to ${_remote.name}...');
    final bool success = await _pushTagToRemote(tag: tag, remote: _remote);
    if (success) {
      print('Release tagged!');
    }
    return success;
  }

  Future<Iterable<String>> _getCurrentTags() async {
    // git tag --points-at HEAD
    final io.ProcessResult tagsResult = await (await gitDir).runCommand(<String>[
      'tag',
      '--points-at',
      'HEAD',
    ], throwOnError: false);
    if (tagsResult.exitCode != 0) {
      return <String>[];
    }

    return (tagsResult.stdout as String)
        .split('\n')
        .map((String line) => line.trim())
        .where((String line) => line.isNotEmpty);
  }

  Future<bool> _checkGitStatus(RepositoryPackage package) async {
    final io.ProcessResult statusResult = await (await gitDir).runCommand(<String>[
      'status',
      '--porcelain',
      package.directory.absolute.path,
    ], throwOnError: false);
    if (statusResult.exitCode != 0) {
      return false;
    }

    final statusOutput = statusResult.stdout as String;
    if (statusOutput.isNotEmpty) {
      printError(
        "There are files in the package directory that haven't been saved in git. Refusing to publish these files:\n\n"
        '$statusOutput\n'
        'If the directory should be clean, you can run `git clean -xdf && git reset --hard HEAD` to wipe all local changes.',
      );
    }
    return statusOutput.isEmpty;
  }

  Future<String?> _verifyRemote(String remote) async {
    final io.ProcessResult getRemoteUrlResult = await (await gitDir).runCommand(<String>[
      'remote',
      'get-url',
      remote,
    ], throwOnError: false);
    if (getRemoteUrlResult.exitCode != 0) {
      return null;
    }
    return getRemoteUrlResult.stdout as String?;
  }

  Future<bool> _runPrePublishScript(RepositoryPackage package) async {
    final File script = package.prePublishScript;
    if (!script.existsSync()) {
      return true;
    }
    final String relativeScriptPath = getRelativePosixPath(script, from: package.directory);
    print('Running pre-publish hook $relativeScriptPath...');

    // Ensure that dependencies are available.
    if (!await runPubGet(package, processRunner, platform)) {
      printError('Failed to get depenedencies');
      return false;
    }

    final int exitCode = await processRunner.runAndStream('dart', <String>[
      'run',
      relativeScriptPath,
    ], workingDir: package.directory);
    if (exitCode != 0) {
      printError('Pre-publish script failed.');
      return false;
    }
    return true;
  }

  Future<bool> _publish(RepositoryPackage package) async {
    print('Publishing...');
    print(
      'Running `pub publish ${_publishFlags.join(' ')}` in '
      '${package.directory.absolute.path}...\n',
    );
    if (getBoolArg(_dryRunFlag)) {
      return true;
    }

    if (_publishFlags.contains('--force')) {
      _ensureValidPubCredential();
    }

    final io.Process publish = await startPubCommand(
      <String>['publish', ..._publishFlags],
      package,
      processRunner,
      platform,
    );
    publish.stdout.transform(utf8.decoder).listen((String data) => print(data));
    publish.stderr.transform(utf8.decoder).listen((String data) => print(data));
    _stdinSubscription ??= _stdin
        .transform(utf8.decoder)
        .listen((String data) => publish.stdin.writeln(data));
    final int result = await publish.exitCode;
    if (result != 0) {
      printError('Publishing ${package.directory.basename} failed.');
      return false;
    }

    print('Package published!');
    return true;
  }

  String _getTag(RepositoryPackage package) {
    final File pubspecFile = package.pubspecFile;
    final pubspecYaml = loadYaml(pubspecFile.readAsStringSync()) as YamlMap;
    final name = pubspecYaml['name'] as String;
    final version = pubspecYaml['version'] as String;
    // We should have failed to publish if these were unset.
    assert(name.isNotEmpty && version.isNotEmpty);
    return _tagFormat.replaceAll('%PACKAGE%', name).replaceAll('%VERSION%', version);
  }

  // Pushes the `tag` to `remote`
  //
  // Return `true` if successful, `false` otherwise.
  Future<bool> _pushTagToRemote({required String tag, required _RemoteInfo remote}) async {
    if (!getBoolArg(_dryRunFlag)) {
      final io.ProcessResult result = await (await gitDir).runCommand(<String>[
        'push',
        remote.name,
        tag,
      ], throwOnError: false);
      if (result.exitCode != 0) {
        return false;
      }
    }
    return true;
  }

  void _ensureValidPubCredential() {
    final File credentialFile = packagesDir.fileSystem.file(credentialsPath);
    if (credentialFile.existsSync() && credentialFile.readAsStringSync().isNotEmpty) {
      return;
    }
    final String? credential = platform.environment[_pubCredentialName];
    if (credential == null) {
      printError('''
No pub credential available. Please check if `$credentialsPath` is valid.
If running this command on CI, you can set the pub credential content in the $_pubCredentialName environment variable.
''');
      throw ToolExit(1);
    }
    credentialFile.createSync(recursive: true);
    credentialFile.openSync(mode: FileMode.writeOnlyAppend)
      ..writeStringSync(credential)
      ..closeSync();
  }
}

/// The path in which pub expects to find its credentials file.
String _getCredentialsPath({required NativePlatform platform, required p.Context path}) {
  // See https://github.com/dart-lang/pub/blob/master/doc/cache_layout.md#layout
  String? configDir;
  if (platform.isLinux) {
    String? configHome = platform.environment['XDG_CONFIG_HOME'];
    if (configHome == null) {
      final String? home = platform.environment['HOME'];
      if (home == null) {
        printError('"HOME" environment variable is not set.');
      } else {
        configHome = path.join(home, '.config');
      }
    }
    if (configHome != null) {
      configDir = path.join(configHome, 'dart');
    }
  } else if (platform.isWindows) {
    final String? appData = platform.environment['APPDATA'];
    if (appData == null) {
      printError('"APPDATA" environment variable is not set.');
    } else {
      configDir = path.join(appData, 'dart');
    }
  } else if (platform.isMacOS) {
    final String? home = platform.environment['HOME'];
    if (home == null) {
      printError('"HOME" environment variable is not set.');
    } else {
      configDir = path.join(home, 'Library', 'Application Support', 'dart');
    }
  }

  if (configDir == null) {
    printError('Unable to determine pub con location');
    throw ToolExit(1);
  }

  return path.join(configDir, 'pub-credentials.json');
}
