// 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 'package:file/file.dart';
import 'package:meta/meta.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/output_utils.dart';
import 'common/package_looping_command.dart';
import 'common/repository_package.dart';
import 'common/tool_config.dart';
import 'validators/dependabot_validator.dart';
import 'validators/gradle_validator.dart';
import 'validators/pubspec_validator.dart';
import 'validators/readme_validator.dart';
import 'validators/repo_info_validator.dart';
import 'validators/version_and_changelog_validator.dart';

const int _missingMinSdkVersionExitCode = 3;
const int _unknownVersionMappingExitCode = 4;

/// The set of possible validators.
///
/// Exposed for testing so that unit tests can target a single validator's
/// behavior via the command without having to set everything required for
/// every other validator to pass.
///
/// This is done instead of testing validators directly to ensure that testing
/// includes things like command line parsing and run initialization.
@visibleForTesting
// ignore: public_member_api_docs
enum Validator { dependabot, gradle, pubspec, readme, repoInfo, version }

/// A command to validate that packages follow various team conventions,
/// guidelines, and best practices.
///
/// This includes:
/// - repository-level metadata about packages, such as repo README and
///   auto-label entries
/// - pubspec format and contents
/// - dependabot configuration coverage
/// - gradle configurations
class ValidateCommand extends PackageLoopingCommand {
  /// Creates Dependabot check command instance.
  ValidateCommand(
    super.packagesDir, {
    this.targetedValidators,
    super.processRunner,
    super.platform,
    super.gitDir,
  }) {
    argParser.addOption(
      _prLabelsArg,
      help:
          'A comma-separated list of labels associated with this PR, '
          'if applicable.\n\n'
          'If supplied, labels may override or disable some checks.',
      hide: true,
    );
    argParser.addFlag(
      _checkForMissingChanges,
      help:
          'Validates that changes to packages include CHANGELOG and '
          'version changes unless they meet an established exemption.\n\n'
          'If used with --$_prLabelsArg, this should only be used in '
          'pre-submit CI checks, to prevent post-submit breakage '
          'when labels are no longer applicable.',
    );
    argParser.addFlag(
      _ignorePlatformInterfaceBreaks,
      help:
          'Bypasses the check that platform interfaces do not contain '
          'breaking changes.\n\n'
          'This is only intended for use in post-submit CI checks, to '
          'prevent post-submit breakage when overriding the check with '
          'labels. Pre-submit checks should always use '
          '--$_prLabelsArg instead.',
      hide: true,
    );
  }

  static const String _prLabelsArg = 'pr-labels';
  static const String _checkForMissingChanges = 'check-for-missing-changes';
  static const String _ignorePlatformInterfaceBreaks = 'ignore-platform-interface-breaks';

  /// The validators to run.
  ///
  /// If null, all validators are run.
  final Set<Validator>? targetedValidators;

  late Directory _repoRoot;

  late final GitVersionFinder _gitVersionFinder;

  late final Set<String> _prLabels = _getPRLabels();

  /// Data from the root README.md table of packages.
  final Map<String, List<String>> _readmeTableEntries = <String, List<String>>{};

  /// Packages with entries in labeler.yml.
  final Set<String> _autoLabeledPackages = <String>{};

  /// The set of directories covered by the repo's Dependabot configuration.
  late DependabotCoverage _dependabotCoverage;

  /// The set of packages that are allowed as dependencies.
  final AllowPackageLists _allowedPackages = (
    local: <String>{},
    pinned: <String>{},
    unpinned: <String>{},
  );

  /// The minimum version of Flutter that is allowed for any package.
  Version? _minMinFlutterVersion;

  /// The minimum version of Dart that is allowed for any package.
  Version? _minMinDartVersion;

  @override
  final String name = 'validate';

  @override
  final String description = 'Checks that packages follow team guidelines.';

  @override
  final PackageLoopingType packageLoopingType = PackageLoopingType.includeAllSubpackages;

  @override
  final bool hasLongOutput = false;

  @override
  Future<void> initializeRun() async {
    _gitVersionFinder = await retrieveVersionFinder();
    _repoRoot = packagesDir.fileSystem.directory((await gitDir).path);

    if (_shouldRun(Validator.repoInfo)) {
      // Extract all of the repo-level README.md table entries.
      _readmeTableEntries.addAll(
        RepoInfoValidator.loadReadmeTableEntries(
          repoRoot: _repoRoot,
          packagesDir: packagesDir,
          thirdPartyPackagesDir: thirdPartyPackagesDir,
        ),
      );
      // Extract all of the labeler.yml package entries.
      _autoLabeledPackages.addAll(RepoInfoValidator.loadAutoLabeledPackages(repoRoot: _repoRoot));
    }
    if (_shouldRun(Validator.pubspec)) {
      await _loadAllowedDependencies();
      final (flutter: Version? minFlutter, dart: Version? minDart) = _loadMinMinSdkVersions();
      _minMinFlutterVersion = minFlutter;
      _minMinDartVersion =
          minDart ?? (minFlutter == null ? null : getDartSdkForFlutterSdk(minFlutter));
      if (_minMinDartVersion == null) {
        printError(
          'Dart SDK version for Flutter SDK version $_minMinFlutterVersion is unknown. '
          'Please update the map for getDartSdkForFlutterSdk with the '
          'corresponding Dart version.',
        );
        throw ToolExit(_unknownVersionMappingExitCode);
      }
    }
    if (_shouldRun(Validator.dependabot)) {
      _dependabotCoverage = DependabotValidator.loadConfig(repoRoot: _repoRoot);
    }
  }

  @override
  Future<PackageResult> runForPackage(RepositoryPackage package) async {
    final List<String> errors = [
      if (_shouldRun(Validator.repoInfo)) ...await _validateRepoInfo(package),
      if (_shouldRun(Validator.pubspec)) ...await _validatePubspec(package),
      if (_shouldRun(Validator.readme)) ...await _validateReadme(package),
      if (_shouldRun(Validator.dependabot)) ...await _validateDependabot(package),
      if (_shouldRun(Validator.gradle)) ...await _validateGradle(package),
      if (_shouldRun(Validator.version)) ...await _validateVersionAndChangelog(package),
    ];

    return errors.isEmpty ? PackageResult.success() : PackageResult.fail(errors);
  }

  bool _shouldRun(Validator validator) => targetedValidators?.contains(validator) ?? true;

  /// Runs repo-level checks.
  Future<List<String>> _validateRepoInfo(RepositoryPackage package) async {
    // Repo-level checks only apply to top-level packages.
    if (!package.isTopLevel) {
      return <String>[];
    }
    final validator = RepoInfoValidator(
      readmeTableEntries: _readmeTableEntries,
      autoLabeledPackages: _autoLabeledPackages,
      gitDir: await gitDir,
      repoRoot: _repoRoot,
      indentation: indentation,
    );
    return validator.validatePackage(package);
  }

  Future<List<String>> _validateDependabot(RepositoryPackage package) async {
    final validator = DependabotValidator(
      coverage: _dependabotCoverage,
      path: path,
      repoRoot: _repoRoot,
      indentation: indentation,
    );
    return validator.validateDependabotCoverage(package);
  }

  Future<List<String>> _validateGradle(RepositoryPackage package) async {
    if (!package.platformDirectory(FlutterPlatform.android).existsSync()) {
      return [];
    }

    final validator = GradleValidator(path: path, indentation: indentation);
    return validator.validateGradle(package);
  }

  Future<List<String>> _validatePubspec(RepositoryPackage package) async {
    final validator = PubspecValidator(
      path: path,
      indentation: indentation,
      warningLogger: printWarning,
      allowedPackages: _allowedPackages,
      repoRoot: rootDir,
      minMinFlutterVersion: _minMinFlutterVersion,
      minMinDartVersion: _minMinDartVersion,
    );
    return validator.validatePubspec(package);
  }

  Future<List<String>> _validateReadme(RepositoryPackage package) async {
    // TODO(stuartmorgan): Consider restructuring this to just check the
    //  current package's README for all packages, now that this is part of an
    //  includeAllSubpackages command. The current logic is from when it was
    //  its own top-level-only command.
    if (!package.isTopLevel) {
      return [];
    }

    final validator = ReadmeValidator(
      path: path,
      indentation: indentation,
      warningLogger: printWarning,
    );

    final List<String> errors = validator.validateReadme(
      package.readmeFile,
      mainPackage: package,
      isExample: false,
    );
    for (final RepositoryPackage packageToCheck in package.getExamples()) {
      errors.addAll(
        validator.validateReadme(packageToCheck.readmeFile, mainPackage: package, isExample: true),
      );
    }

    // If there's an example/README.md for a multi-example package, validate
    // that as well, as it will be shown on pub.dev.
    final Directory exampleDir = package.directory.childDirectory('example');
    final File exampleDirReadme = exampleDir.childFile('README.md');
    if (exampleDir.existsSync() && !isPackage(exampleDir)) {
      errors.addAll(
        validator.validateReadme(exampleDirReadme, mainPackage: package, isExample: true),
      );
    }

    return errors;
  }

  Future<List<String>> _validateVersionAndChangelog(RepositoryPackage package) async {
    if (!package.isTopLevel) {
      return [];
    }

    final Directory repoRoot = packagesDir.fileSystem.directory((await gitDir).path);

    final validator = VersionAndChangelogValidator(
      path: path,
      indentation: indentation,
      warningLogger: logWarning,
      gitVersionFinder: _gitVersionFinder,
      repoRoot: repoRoot,
      changedFiles: changedFiles,
      prLabels: _prLabels,
    );

    return validator.validateChangelogAndVersion(
      package,
      checkForMissingChanges: getBoolArg(_checkForMissingChanges),
      ignorePlatformInterfaceBreaks: getBoolArg(_ignorePlatformInterfaceBreaks),
    );
  }

  Stream<String> _findAllPublishedPackages() async* {
    for (final File pubspecFile
        in (await _repoRoot.list(recursive: true, followLinks: false).toList())
            .whereType<File>()
            .where((File entity) => p.basename(entity.path) == 'pubspec.yaml')) {
      final Pubspec? pubspec = _tryParsePubspec(pubspecFile.readAsStringSync());
      if (pubspec != null && pubspec.publishTo != 'none') {
        yield pubspec.name;
      }
    }
  }

  Future<void> _loadAllowedDependencies() async {
    // Find all local, published packages.
    _allowedPackages.local.addAll(await _findAllPublishedPackages().toList());

    final ({List<String> pinned, List<String> unpinned}) allowedDeps = getAllowedDependencies(
      _repoRoot,
    );
    _allowedPackages.unpinned.addAll(allowedDeps.unpinned);
    _allowedPackages.pinned.addAll(allowedDeps.pinned);
  }

  ({Version? flutter, Version? dart}) _loadMinMinSdkVersions() {
    final String? minFlutter = getMinFlutterVersion(_repoRoot);
    final String? minDart = getMinDartVersion(_repoRoot);
    if (minFlutter == null && minDart == null) {
      printError(
        'Either min_flutter or min_dart must be provided '
        'in the repo tool configuration.',
      );
      throw ToolExit(_missingMinSdkVersionExitCode);
    }
    return (
      flutter: minFlutter == null ? null : Version.parse(minFlutter),
      dart: minDart == null ? null : Version.parse(minDart),
    );
  }

  Pubspec? _tryParsePubspec(String pubspecContents) {
    try {
      return Pubspec.parse(pubspecContents);
    } on Exception catch (exception) {
      print('  Cannot parse pubspec.yaml: $exception');
    }
    return null;
  }

  /// Returns the labels associated with this PR, if any, or an empty set
  /// if that flag is not provided.
  Set<String> _getPRLabels() {
    final String labels = getStringArg(_prLabelsArg);
    if (labels.isEmpty) {
      return <String>{};
    }
    return labels.split(',').map((String label) => label.trim()).toSet();
  }
}
