// 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();
  }
}
