// 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/git_version_finder.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;

import 'repository_package.dart';

/// The state of a package on disk relative to git state.
@immutable
class PackageChangeState {
  /// Creates a new immutable state instance.
  const PackageChangeState({
    required this.hasChanges,
    required this.hasChangelogChange,
    required this.needsChangelogChange,
    required this.needsVersionChange,
  });

  /// True if there are any changes to files in the package.
  final bool hasChanges;

  /// True if the package's CHANGELOG.md has been changed.
  final bool hasChangelogChange;

  /// True if any changes in the package require a version change according
  /// to repository policy.
  final bool needsVersionChange;

  /// True if any changes in the package require a CHANGELOG change according
  /// to repository policy.
  final bool needsChangelogChange;
}

/// Checks [package] against [changedPaths] to determine what changes it has
/// and how those changes relate to repository policy about CHANGELOG and
/// version updates.
///
/// [changedPaths] should be a list of POSIX-style paths from a common root,
/// and [relativePackagePath] should be the path to [package] from that same
/// root. Commonly these will come from `gitVersionFinder.getChangedFiles()`
/// and `getRelativePosixPath(package.directory, gitDir.path)` respectively;
/// they are arguments mainly to allow for caching the changed paths for an
/// entire command run.
///
/// If [git] is provided, [changedPaths] must be repository-relative
/// paths, and change type detection can use file diffs in addition to paths.
Future<PackageChangeState> checkPackageChangeState(
  RepositoryPackage package, {
  required List<String> changedPaths,
  required String relativePackagePath,
  GitVersionFinder? git,
}) async {
  final String packagePrefix = relativePackagePath.endsWith('/')
      ? relativePackagePath
      : '$relativePackagePath/';

  bool hasChanges = false;
  bool hasChangelogChange = false;
  bool needsVersionChange = false;
  bool needsChangelogChange = false;
  for (final String path in changedPaths) {
    // Only consider files within the package.
    if (!path.startsWith(packagePrefix)) {
      continue;
    }
    final String packageRelativePath = path.substring(packagePrefix.length);
    hasChanges = true;

    final List<String> components = p.posix.split(packageRelativePath);
    if (components.isEmpty) {
      continue;
    }

    if (components.first == 'CHANGELOG.md') {
      hasChangelogChange = true;
      continue;
    }

    if (!needsVersionChange) {
      // Developer-only changes don't need version changes or changelog changes.
      if (await _isDevChange(components, git: git, repoPath: path)) {
        continue;
      }

      // Some other changes don't need version changes, but might benefit from
      // changelog changes.
      needsChangelogChange = true;
      if (
          // One of a few special files example will be shown on pub.dev, but
          // for anything else in the example publishing has no purpose.
          !_isUnpublishedExampleChange(components, package)) {
        needsVersionChange = true;
      }
    }
  }

  return PackageChangeState(
      hasChanges: hasChanges,
      hasChangelogChange: hasChangelogChange,
      needsChangelogChange: needsChangelogChange,
      needsVersionChange: needsVersionChange);
}

bool _isTestChange(List<String> pathComponents) {
  return pathComponents.contains('test') ||
      pathComponents.contains('androidTest') ||
      pathComponents.contains('RunnerTests') ||
      pathComponents.contains('RunnerUITests');
}

// True if the given file is an example file other than the one that will be
// published according to https://dart.dev/tools/pub/package-layout#examples.
//
// This is not exhastive; it currently only handles variations we actually have
// in our repositories.
bool _isUnpublishedExampleChange(
    List<String> pathComponents, RepositoryPackage package) {
  if (pathComponents.first != 'example') {
    return false;
  }
  final List<String> exampleComponents = pathComponents.sublist(1);
  if (exampleComponents.isEmpty) {
    return false;
  }

  final Directory exampleDirectory =
      package.directory.childDirectory('example');

  // Check for example.md/EXAMPLE.md first, as that has priority. If it's
  // present, any other example file is unpublished.
  final bool hasExampleMd =
      exampleDirectory.childFile('example.md').existsSync() ||
          exampleDirectory.childFile('EXAMPLE.md').existsSync();
  if (hasExampleMd) {
    return !(exampleComponents.length == 1 &&
        exampleComponents.first.toLowerCase() == 'example.md');
  }

  // Most packages have an example/lib/main.dart (or occasionally
  // example/main.dart), so check for that. The other naming variations aren't
  // currently used.
  const String mainName = 'main.dart';
  final bool hasExampleCode =
      exampleDirectory.childDirectory('lib').childFile(mainName).existsSync() ||
          exampleDirectory.childFile(mainName).existsSync();
  if (hasExampleCode) {
    // If there is an example main, only that example file is published.
    return !((exampleComponents.length == 1 &&
            exampleComponents.first == mainName) ||
        (exampleComponents.length == 2 &&
            exampleComponents.first == 'lib' &&
            exampleComponents[1] == mainName));
  }

  // If there's no example code either, the example README.md, if any, is the
  // file that will be published.
  return exampleComponents.first.toLowerCase() != 'readme.md';
}

// True if the change is only relevant to people working on the plugin.
Future<bool> _isDevChange(List<String> pathComponents,
    {GitVersionFinder? git, String? repoPath}) async {
  return _isTestChange(pathComponents) ||
      // The top-level "tool" directory is for non-client-facing utility
      // code, such as test scripts.
      pathComponents.first == 'tool' ||
      // Ignoring lints doesn't affect clients.
      pathComponents.contains('lint-baseline.xml') ||
      await _isGradleTestDependencyChange(pathComponents,
          git: git, repoPath: repoPath);
}

Future<bool> _isGradleTestDependencyChange(List<String> pathComponents,
    {GitVersionFinder? git, String? repoPath}) async {
  if (git == null) {
    return false;
  }
  if (pathComponents.last != 'build.gradle') {
    return false;
  }
  final List<String> diff = await git.getDiffContents(targetPath: repoPath);
  final RegExp changeLine = RegExp(r'[+-] ');
  final RegExp testDependencyLine =
      RegExp(r'[+-]\s*(?:androidT|t)estImplementation\s');
  bool foundTestDependencyChange = false;
  for (final String line in diff) {
    if (!changeLine.hasMatch(line) ||
        line.startsWith('--- ') ||
        line.startsWith('+++ ')) {
      continue;
    }
    if (!testDependencyLine.hasMatch(line)) {
      return false;
    }
    foundTestDependencyChange = true;
  }
  // Only return true if a test dependency change was found, as a failsafe
  // against having the wrong (e.g., incorrectly empty) diff output.
  return foundTestDependencyChange;
}
