// 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:flutter_plugin_tools/src/common/plugin_utils.dart';
import 'package:git/git.dart';
import 'package:path/path.dart' as p;
import 'package:platform/platform.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:pubspec_parse/pubspec_parse.dart';

import 'common/core.dart';
import 'common/file_utils.dart';
import 'common/git_version_finder.dart';
import 'common/package_looping_command.dart';
import 'common/process_runner.dart';
import 'common/repository_package.dart';

/// A command to check that PRs don't violate repository best practices that
/// have been established to avoid breakages that building and testing won't
/// catch.
class FederationSafetyCheckCommand extends PackageLoopingCommand {
  /// Creates an instance of the safety check command.
  FederationSafetyCheckCommand(
    Directory packagesDir, {
    ProcessRunner processRunner = const ProcessRunner(),
    Platform platform = const LocalPlatform(),
    GitDir? gitDir,
  }) : super(
          packagesDir,
          processRunner: processRunner,
          platform: platform,
          gitDir: gitDir,
        );

  // A map of package name (as defined by the directory name of the package)
  // to a list of changed Dart files in that package, as Posix paths relative to
  // the package root.
  //
  // This only considers top-level packages, not subpackages such as example/.
  final Map<String, List<String>> _changedDartFiles = <String, List<String>>{};

  // The set of *_platform_interface packages that will have public code changes
  // published.
  final Set<String> _modifiedAndPublishedPlatformInterfacePackages = <String>{};

  // The set of conceptual plugins (not packages) that have changes.
  final Set<String> _changedPlugins = <String>{};

  static const String _platformInterfaceSuffix = '_platform_interface';

  @override
  final String name = 'federation-safety-check';

  @override
  final String description =
      'Checks that the change does not violate repository rules around changes '
      'to federated plugin packages.';

  @override
  bool get hasLongOutput => false;

  @override
  Future<void> initializeRun() async {
    final GitVersionFinder gitVersionFinder = await retrieveVersionFinder();
    final String baseSha = await gitVersionFinder.getBaseSha();
    print('Validating changes relative to "$baseSha"\n');
    for (final String path in await gitVersionFinder.getChangedFiles()) {
      // Git output always uses Posix paths.
      final List<String> allComponents = p.posix.split(path);
      final int packageIndex = allComponents.indexOf('packages');
      if (packageIndex == -1) {
        continue;
      }
      final List<String> relativeComponents =
          allComponents.sublist(packageIndex + 1);
      // The package name is either the directory directly under packages/, or
      // the directory under that in the case of a federated plugin.
      String packageName = relativeComponents.removeAt(0);
      // Count the top-level plugin as changed.
      _changedPlugins.add(packageName);
      if (relativeComponents[0] == packageName ||
          relativeComponents[0].startsWith('${packageName}_')) {
        packageName = relativeComponents.removeAt(0);
      }

      if (relativeComponents.last.endsWith('.dart')) {
        _changedDartFiles[packageName] ??= <String>[];
        _changedDartFiles[packageName]!
            .add(p.posix.joinAll(relativeComponents));
      }

      if (packageName.endsWith(_platformInterfaceSuffix) &&
          relativeComponents.first == 'pubspec.yaml' &&
          await _packageWillBePublished(path)) {
        _modifiedAndPublishedPlatformInterfacePackages.add(packageName);
      }
    }
  }

  @override
  Future<PackageResult> runForPackage(RepositoryPackage package) async {
    if (!isFlutterPlugin(package)) {
      return PackageResult.skip('Not a plugin.');
    }

    if (!package.isFederated) {
      return PackageResult.skip('Not a federated plugin.');
    }

    if (package.isPlatformInterface) {
      // As the leaf nodes in the graph, a published package interface change is
      // assumed to be correct, and other changes are validated against that.
      return PackageResult.skip(
          'Platform interface changes are not validated.');
    }

    // Uses basename to match _changedPackageFiles.
    final String basePackageName = package.directory.parent.basename;
    final String platformInterfacePackageName =
        '$basePackageName$_platformInterfaceSuffix';
    final List<String> changedPlatformInterfaceFiles =
        _changedDartFiles[platformInterfacePackageName] ?? <String>[];

    if (!_modifiedAndPublishedPlatformInterfacePackages
        .contains(platformInterfacePackageName)) {
      print('No published changes for $platformInterfacePackageName.');
      return PackageResult.success();
    }

    if (!changedPlatformInterfaceFiles
        .any((String path) => path.startsWith('lib/'))) {
      print('No public code changes for $platformInterfacePackageName.');
      return PackageResult.success();
    }

    final List<String> changedPackageFiles =
        _changedDartFiles[package.directory.basename] ?? <String>[];
    if (changedPackageFiles.isEmpty) {
      print('No Dart changes.');
      return PackageResult.success();
    }

    // If the change would be flagged, but it appears to be a mass change
    // rather than a plugin-specific change, allow it with a warning.
    //
    // This is a tradeoff between safety and convenience; forcing mass changes
    // to be split apart is not ideal, and the assumption is that reviewers are
    // unlikely to accidentally approve a PR that is supposed to be changing a
    // single plugin, but touches other plugins (vs accidentally approving a
    // PR that changes multiple parts of a single plugin, which is a relatively
    // easy mistake to make).
    //
    // 3 is chosen to minimize the chances of accidentally letting something
    // through (vs 2, which could be a single-plugin change with one stray
    // change to another file accidentally included), while not setting too
    // high a bar for detecting mass changes. This can be tuned if there are
    // issues with false positives or false negatives.
    const int massChangePluginThreshold = 3;
    if (_changedPlugins.length >= massChangePluginThreshold) {
      logWarning('Ignoring potentially dangerous change, as this appears '
          'to be a mass change.');
      return PackageResult.success();
    }

    printError('Dart changes are not allowed to other packages in '
        '$basePackageName in the same PR as changes to public Dart code in '
        '$platformInterfacePackageName, as this can cause accidental breaking '
        'changes to be missed by automated checks. Please split the changes to '
        'these two packages into separate PRs.\n\n'
        'If you believe that this is a false positive, please file a bug.');
    return PackageResult.fail(
        <String>['$platformInterfacePackageName changed.']);
  }

  Future<bool> _packageWillBePublished(
      String pubspecRepoRelativePosixPath) async {
    final File pubspecFile = childFileWithSubcomponents(
        packagesDir.parent, p.posix.split(pubspecRepoRelativePosixPath));
    final Pubspec pubspec = Pubspec.parse(pubspecFile.readAsStringSync());
    if (pubspec.publishTo == 'none') {
      return false;
    }

    final GitVersionFinder gitVersionFinder = await retrieveVersionFinder();
    final Version? previousVersion =
        await gitVersionFinder.getPackageVersion(pubspecRepoRelativePosixPath);
    if (previousVersion == null) {
      // The plugin is new, so it will be published.
      return true;
    }
    return pubspec.version != previousVersion;
  }
}
