// 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 'package:file/file.dart';
import 'package:git/git.dart';
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';

import 'common/core.dart';
import 'common/git_version_finder.dart';
import 'common/plugin_command.dart';
import 'common/repository_package.dart';

const int _exitPackageNotFound = 3;
const int _exitCannotUpdatePubspec = 4;

enum _RewriteOutcome { changed, noChangesNeeded, alreadyChanged }

/// Converts all dependencies on target packages to path-based dependencies.
///
/// This is to allow for pre-publish testing of changes that could affect other
/// packages in the repository. For instance, this allows for catching cases
/// where a non-breaking change to a platform interface package of a federated
/// plugin would cause post-publish analyzer failures in another package of that
/// plugin.
class MakeDepsPathBasedCommand extends PluginCommand {
  /// Creates an instance of the command to convert selected dependencies to
  /// path-based.
  MakeDepsPathBasedCommand(
    Directory packagesDir, {
    GitDir? gitDir,
  }) : super(packagesDir, gitDir: gitDir) {
    argParser.addMultiOption(_targetDependenciesArg,
        help:
            'The names of the packages to convert to path-based dependencies.\n'
            'Ignored if --$_targetDependenciesWithNonBreakingUpdatesArg is '
            'passed.',
        valueHelp: 'some_package');
    argParser.addFlag(
      _targetDependenciesWithNonBreakingUpdatesArg,
      help: 'Causes all packages that have non-breaking version changes '
          'when compared against the git base to be treated as target '
          'packages.',
    );
  }

  static const String _targetDependenciesArg = 'target-dependencies';
  static const String _targetDependenciesWithNonBreakingUpdatesArg =
      'target-dependencies-with-non-breaking-updates';

  // The comment to add to temporary dependency overrides.
  static const String _dependencyOverrideWarningComment =
      '# FOR TESTING ONLY. DO NOT MERGE.';

  @override
  final String name = 'make-deps-path-based';

  @override
  final String description =
      'Converts package dependencies to path-based references.';

  @override
  Future<void> run() async {
    final Set<String> targetDependencies =
        getBoolArg(_targetDependenciesWithNonBreakingUpdatesArg)
            ? await _getNonBreakingUpdatePackages()
            : getStringListArg(_targetDependenciesArg).toSet();

    if (targetDependencies.isEmpty) {
      print('No target dependencies; nothing to do.');
      return;
    }
    print('Rewriting references to: ${targetDependencies.join(', ')}...');

    final Map<String, RepositoryPackage> localDependencyPackages =
        _findLocalPackages(targetDependencies);

    final String repoRootPath = (await gitDir).path;
    for (final File pubspec in await _getAllPubspecs()) {
      final String displayPath = p.posix.joinAll(
          path.split(path.relative(pubspec.absolute.path, from: repoRootPath)));
      final _RewriteOutcome outcome = await _addDependencyOverridesIfNecessary(
          pubspec, localDependencyPackages);
      switch (outcome) {
        case _RewriteOutcome.changed:
          print('  Modified $displayPath');
          break;
        case _RewriteOutcome.alreadyChanged:
          print('  Skipped $displayPath - Already rewritten');
          break;
        case _RewriteOutcome.noChangesNeeded:
          break;
      }
    }
  }

  Map<String, RepositoryPackage> _findLocalPackages(Set<String> packageNames) {
    final Map<String, RepositoryPackage> targets =
        <String, RepositoryPackage>{};
    for (final String packageName in packageNames) {
      final Directory topLevelCandidate =
          packagesDir.childDirectory(packageName);
      // If packages/<packageName>/ exists, then either that directory is the
      // package, or packages/<packageName>/<packageName>/ exists and is the
      // package (in the case of a federated plugin).
      if (topLevelCandidate.existsSync()) {
        final Directory appFacingCandidate =
            topLevelCandidate.childDirectory(packageName);
        targets[packageName] = RepositoryPackage(appFacingCandidate.existsSync()
            ? appFacingCandidate
            : topLevelCandidate);
        continue;
      }
      // If there is no packages/<packageName> directory, then either the
      // packages doesn't exist, or it is a sub-package of a federated plugin.
      // If it's the latter, it will be a directory whose name is a prefix.
      for (final FileSystemEntity entity in packagesDir.listSync()) {
        if (entity is Directory && packageName.startsWith(entity.basename)) {
          final Directory subPackageCandidate =
              entity.childDirectory(packageName);
          if (subPackageCandidate.existsSync()) {
            targets[packageName] = RepositoryPackage(subPackageCandidate);
            break;
          }
        }
      }

      if (!targets.containsKey(packageName)) {
        printError('Unable to find package "$packageName"');
        throw ToolExit(_exitPackageNotFound);
      }
    }
    return targets;
  }

  /// If [pubspecFile] has any dependencies on packages in [localDependencies],
  /// adds dependency_overrides entries to redirect them to the local version
  /// using path-based dependencies.
  Future<_RewriteOutcome> _addDependencyOverridesIfNecessary(File pubspecFile,
      Map<String, RepositoryPackage> localDependencies) async {
    final String pubspecContents = pubspecFile.readAsStringSync();
    final Pubspec pubspec = Pubspec.parse(pubspecContents);
    // Fail if there are any dependency overrides already, other than ones
    // created by this script. If support for that is needed at some point, it
    // can be added, but currently it's not and relying on that makes the logic
    // here much simpler.
    if (pubspec.dependencyOverrides.isNotEmpty) {
      if (pubspecContents.contains(_dependencyOverrideWarningComment)) {
        return _RewriteOutcome.alreadyChanged;
      }
      printError(
          'Plugins with dependency overrides are not currently supported.');
      throw ToolExit(_exitCannotUpdatePubspec);
    }

    final Iterable<String> packagesToOverride = pubspec.dependencies.keys.where(
        (String packageName) => localDependencies.containsKey(packageName));
    if (packagesToOverride.isNotEmpty) {
      final String commonBasePath = packagesDir.path;
      // Find the relative path to the common base.
      final int packageDepth = path
          .split(path.relative(pubspecFile.parent.absolute.path,
              from: commonBasePath))
          .length;
      final List<String> relativeBasePathComponents =
          List<String>.filled(packageDepth, '..');
      // This is done via strings rather than by manipulating the Pubspec and
      // then re-serialiazing so that it's a localized change, rather than
      // rewriting the whole file (e.g., destroying comments), which could be
      // more disruptive for local use.
      String newPubspecContents = pubspecContents +
          '''

$_dependencyOverrideWarningComment
dependency_overrides:
''';
      for (final String packageName in packagesToOverride) {
        // Find the relative path from the common base to the local package.
        final List<String> repoRelativePathComponents = path.split(
            path.relative(localDependencies[packageName]!.path,
                from: commonBasePath));
        newPubspecContents += '''
  $packageName:
    path: ${p.posix.joinAll(<String>[
              ...relativeBasePathComponents,
              ...repoRelativePathComponents,
            ])}
''';
      }
      pubspecFile.writeAsStringSync(newPubspecContents);
      return _RewriteOutcome.changed;
    }
    return _RewriteOutcome.noChangesNeeded;
  }

  /// Returns all pubspecs anywhere under the packages directory.
  Future<List<File>> _getAllPubspecs() => packagesDir.parent
      .list(recursive: true, followLinks: false)
      .where((FileSystemEntity entity) =>
          entity is File && p.basename(entity.path) == 'pubspec.yaml')
      .map((FileSystemEntity file) => file as File)
      .toList();

  /// Returns all packages that have non-breaking published changes (i.e., a
  /// minor or bugfix version change) relative to the git comparison base.
  ///
  /// Prints status information about what was checked for ease of auditing logs
  /// in CI.
  Future<Set<String>> _getNonBreakingUpdatePackages() async {
    final GitVersionFinder gitVersionFinder = await retrieveVersionFinder();
    final String baseSha = await gitVersionFinder.getBaseSha();
    print('Finding changed packages relative to "$baseSha"...');

    final Set<String> changedPackages = <String>{};
    for (final String changedPath in await gitVersionFinder.getChangedFiles()) {
      // Git output always uses Posix paths.
      final List<String> allComponents = p.posix.split(changedPath);
      // Only pubspec changes are potential publishing events.
      if (allComponents.last != 'pubspec.yaml' ||
          allComponents.contains('example')) {
        continue;
      }
      if (!allComponents.contains(packagesDir.basename)) {
        print('  Skipping $changedPath; not in packages directory.');
        continue;
      }
      final RepositoryPackage package =
          RepositoryPackage(packagesDir.fileSystem.file(changedPath).parent);
      // Ignored deleted packages, as they won't be published.
      if (!package.pubspecFile.existsSync()) {
        final String directoryName = p.posix.joinAll(path.split(path.relative(
            package.directory.absolute.path,
            from: packagesDir.path)));
        print('  Skipping $directoryName; deleted.');
        continue;
      }
      final String packageName = package.parsePubspec().name;
      if (!await _hasNonBreakingVersionChange(package)) {
        // Log packages that had pubspec changes but weren't included for ease
        // of auditing CI.
        print('  Skipping $packageName; no non-breaking version change.');
        continue;
      }
      changedPackages.add(packageName);
    }
    return changedPackages;
  }

  Future<bool> _hasNonBreakingVersionChange(RepositoryPackage package) async {
    final Pubspec pubspec = package.parsePubspec();
    if (pubspec.publishTo == 'none') {
      return false;
    }

    final String pubspecGitPath = p.posix.joinAll(path.split(path.relative(
        package.pubspecFile.absolute.path,
        from: (await gitDir).path)));
    final GitVersionFinder gitVersionFinder = await retrieveVersionFinder();
    final Version? previousVersion =
        await gitVersionFinder.getPackageVersion(pubspecGitPath);
    if (previousVersion == null) {
      // The plugin is new, so nothing can be depending on it yet.
      return false;
    }
    final Version newVersion = pubspec.version!;
    if ((newVersion.major > 0 && newVersion.major != previousVersion.major) ||
        (newVersion.major == 0 && newVersion.minor != previousVersion.minor)) {
      // Breaking changes aren't targetted since they won't be picked up
      // automatically.
      return false;
    }
    return newVersion != previousVersion;
  }
}
