// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:convert';

import 'package:collection/collection.dart' show IterableExtension;

import '../command.dart';
import '../command_runner.dart';
import '../entrypoint.dart';
import '../io.dart';
import '../lock_file.dart';
import '../log.dart' as log;
import '../log.dart';
import '../package.dart';
import '../package_name.dart';
import '../path.dart';
import '../pubspec.dart';
import '../pubspec_utils.dart';
import '../solver.dart';
import '../source/git.dart';
import '../source/hosted.dart';
import '../source/path.dart';
import '../source/sdk.dart' show SdkSource;
import '../system_cache.dart';
import '../utils.dart';

class OutdatedCommand extends PubCommand {
  @override
  String get name => 'outdated';
  @override
  String get description =>
      'Analyze your dependencies to find which ones can be upgraded.';
  @override
  String get argumentsDescription => '[options]';
  @override
  String get docUrl => 'https://dart.dev/tools/pub/cmd/pub-outdated';

  /// Avoid showing spinning progress messages when not in an ANSI-capable
  /// terminal, and when we are outputting machine-readable json.
  bool get _shouldShowSpinner =>
      terminalOutputForStdout && canUseAnsiCodes && !argResults.flag('json');

  @override
  bool get takesArguments => false;

  OutdatedCommand() {
    argParser.addFlag(
      'dependency-overrides',
      defaultsTo: true,
      help: 'Show resolutions with `dependency_overrides`.',
    );

    argParser.addFlag(
      'dev-dependencies',
      defaultsTo: true,
      help: 'Take dev dependencies into account.',
    );

    argParser.addFlag(
      'json',
      help: 'Output the results using a json format.',
      negatable: false,
    );

    argParser.addOption(
      'mode',
      help: '''
Highlight versions with PROPERTY.
Only packages currently missing that PROPERTY will be included unless 
--show-all.
''',
      valueHelp: 'PROPERTY',
      allowed: ['outdated', 'null-safety'],
      defaultsTo: 'outdated',
      hide: true,
    );

    argParser.addFlag(
      'prereleases',
      help: 'Include prereleases in latest version.',
    );

    // Preserve for backwards compatibility.
    argParser.addFlag(
      'pre-releases',
      help: 'Alias of prereleases.',
      hide: true,
    );

    argParser.addFlag(
      'show-all',
      help: 'Include dependencies that are already fulfilling --mode.',
    );

    // Preserve for backwards compatibility.
    argParser.addFlag(
      'up-to-date',
      hide: true,
      help:
          'Include dependencies that are already at the '
          'latest version. Alias of --show-all.',
    );
    argParser.addFlag(
      'transitive',
      help: 'Show transitive dependencies.',
      defaultsTo: true,
    );
    argParser.addOption(
      'directory',
      abbr: 'C',
      help: 'Run this in the directory <dir>.',
      valueHelp: 'dir',
    );
  }

  @override
  Future<void> runProtected() async {
    if (argResults.option('mode') == 'null-safety') {
      dataError('''The `--mode=null-safety` option is no longer supported.
Consider using the Dart 2.19 sdk to migrate to null safety.''');
    }
    final mode = _OutdatedMode();

    final includeDevDependencies = argResults.flag('dev-dependencies');
    final includeDependencyOverrides = argResults.flag('dependency-overrides');
    if (argResults.flag('json') && argResults.wasParsed('transitive')) {
      usageException(
        'Cannot specify both `--json` and `--transitive`\n'
        'The json report always includes transitive dependencies.',
      );
    }

    /// The workspace root with dependency overrides removed if requested.
    final baseWorkspace =
        includeDependencyOverrides
            ? entrypoint.workspaceRoot
            : entrypoint.workspaceRoot.transformWorkspace(
              (package) => stripDependencyOverrides(package.pubspec),
            );

    /// [baseWorkspace] with dev-dependencies removed if requested.
    final upgradableWorkspace =
        includeDevDependencies
            ? baseWorkspace
            : baseWorkspace.transformWorkspace(
              (package) => stripDevDependencies(package.pubspec),
            );

    /// [upgradableWorkspace] with upper bounds removed.
    final resolvableWorkspace = upgradableWorkspace.transformWorkspace(
      (package) => mode.resolvablePubspec(package.pubspec),
    );
    late List<PackageId> upgradablePackages;
    late List<PackageId> resolvablePackages;
    late bool hasUpgradableResolution;
    late bool hasResolvableResolution;

    await log.progress(
      'Resolving',
      () async {
        final upgradablePackagesResult = await _tryResolve(
          upgradableWorkspace,
          cache,
          lockFile: entrypoint.lockFile,
        );
        hasUpgradableResolution = upgradablePackagesResult != null;
        upgradablePackages = upgradablePackagesResult ?? [];

        final resolvablePackagesResult = await _tryResolve(
          resolvableWorkspace,
          cache,
          lockFile: entrypoint.lockFile,
        );
        hasResolvableResolution = resolvablePackagesResult != null;
        resolvablePackages = resolvablePackagesResult ?? [];
      },
      condition: _shouldShowSpinner,
      transient: true,
    );

    // This list will be empty if there is no lock file.
    final currentPackages = entrypoint.lockFile.packages.values;

    /// The set of all dependencies (direct and transitive) that are in the
    /// closure of the non-dev dependencies from the root in at least one of
    /// the current, upgradable and resolvable resolutions.
    final nonDevDependencies = <String>{
      ...await _nonDevDependencyClosure(
        entrypoint.workspaceRoot,
        currentPackages,
      ),
      ...await _nonDevDependencyClosure(
        entrypoint.workspaceRoot,
        upgradablePackages,
      ),
      ...await _nonDevDependencyClosure(
        entrypoint.workspaceRoot,
        resolvablePackages,
      ),
    };

    Future<_PackageDetails> analyzeDependency(PackageRef packageRef) async {
      final name = packageRef.name;
      final current = entrypoint.lockFile.packages[name];

      final upgradable = upgradablePackages.firstWhereOrNull(
        (id) => id.name == name,
      );
      final resolvable = resolvablePackages.firstWhereOrNull(
        (id) => id.name == name,
      );

      // Find the latest version, and if it's overridden.
      var latestIsOverridden = false;
      PackageId? latest;
      // If not overridden in current resolution we can use this
      if (!hasOverride(entrypoint.workspaceRoot, name)) {
        latest ??= await cache.getLatest(
          current?.toRef(),
          version: current?.version,
          allowPrereleases: prereleases,
        );
      }
      // If present as a dependency or dev_dependency we use this
      latest ??= await cache.getLatest(
        allDependencies(
          baseWorkspace,
        ).firstWhereOrNull((r) => r.name == name)?.toRef(),
        allowPrereleases: prereleases,
      );
      latest ??= await cache.getLatest(
        allDevDependencies(
          baseWorkspace,
        ).firstWhereOrNull((r) => r.name == name)?.toRef(),
        allowPrereleases: prereleases,
      );
      // If not overridden and present in either upgradable or resolvable we
      // use this reference to find the latest
      if (!hasOverride(upgradableWorkspace, name)) {
        latest ??= await cache.getLatest(
          upgradable?.toRef(),
          version: upgradable?.version,
          allowPrereleases: prereleases,
        );
      }
      if (!hasOverride(resolvableWorkspace, name)) {
        latest ??= await cache.getLatest(
          resolvable?.toRef(),
          version: resolvable?.version,
          allowPrereleases: prereleases,
        );
      }
      // Otherwise, we might simply not have a latest, when a transitive
      // dependency is overridden the source can depend on which versions we
      // are picking. This is not a problem on `pub.dev` because it does not
      // allow 3rd party pub servers, but other servers might. Hence, we choose
      // to fallback to using the overridden source for latest.
      if (latest == null) {
        final id = current ?? upgradable ?? resolvable;
        latest ??= await cache.getLatest(
          id?.toRef(),
          version: id?.version,
          allowPrereleases: prereleases,
        );
        latestIsOverridden = true;
      }

      final currentStatus = await current?.source.status(
        current.toRef(),
        current.version,
        cache,
      );

      final id = current ?? upgradable ?? resolvable ?? latest;
      var packageAdvisories =
          await id?.source.getAdvisoriesForPackage(
            id,
            cache,
            const Duration(days: 3),
          ) ??
          [];

      final discontinued =
          currentStatus == null ? false : currentStatus.isDiscontinued;
      final discontinuedReplacedBy = currentStatus?.discontinuedReplacedBy;
      final isCurrentRetracted =
          currentStatus == null ? false : currentStatus.isRetracted;

      final currentVersionDetails = await _describeVersion(
        current,
        entrypoint.workspaceRoot.pubspec.dependencyOverrides.containsKey(name),
      );

      final upgradableVersionDetails = await _describeVersion(
        upgradable,
        hasOverride(upgradableWorkspace, name),
      );

      final resolvableVersionDetails = await _describeVersion(
        resolvable,
        hasOverride(resolvableWorkspace, name),
      );

      final latestVersionDetails = await _describeVersion(
        latest,
        latestIsOverridden,
      );

      final isLatest = currentVersionDetails == latestVersionDetails;

      var isCurrentAffectedByAdvisory = false;
      if (currentVersionDetails != null) {
        // Filter out advisories added to `ignored_advisores` in the root
        // pubspec.
        packageAdvisories =
            packageAdvisories
                .where(
                  (adv) =>
                      entrypoint.workspaceRoot.pubspec.ignoredAdvisories
                          .intersection({...adv.aliases, adv.id})
                          .isEmpty,
                )
                .toList();
        for (final advisory in packageAdvisories) {
          if (advisory.affectedVersions.contains(
            currentVersionDetails._pubspec.version.canonicalizedVersion,
          )) {
            isCurrentAffectedByAdvisory = true;
          }
        }
      }

      return _PackageDetails(
        name: name,
        current: currentVersionDetails,
        upgradable: upgradableVersionDetails,
        resolvable: resolvableVersionDetails,
        latest: latestVersionDetails,
        kind: _kind(name, entrypoint, nonDevDependencies),
        isDiscontinued: discontinued,
        discontinuedReplacedBy: discontinuedReplacedBy,
        isCurrentRetracted: isCurrentRetracted,
        isLatest: isLatest,
        advisories: packageAdvisories,
        isCurrentAffectedBySecurityAdvisory: isCurrentAffectedByAdvisory,
      );
    }

    final rows = <_PackageDetails>[];

    final visited = {
      ...entrypoint.workspaceRoot.transitiveWorkspace.map(
        (package) => package.name,
      ),
    };
    // Add all dependencies from the lockfile.
    final idsToAnalyze = <PackageRef>[];
    for (final id in [
      ...currentPackages,
      ...upgradablePackages,
      ...resolvablePackages,
    ]) {
      if (!visited.add(id.name)) continue;
      idsToAnalyze.add(id.toRef());
    }
    await cache.prefetchAdvisoriesAndStatus([
      ...currentPackages,
      ...upgradablePackages,
      ...resolvablePackages,
    ]);

    rows.addAll(await Future.wait(idsToAnalyze.map(analyzeDependency)));

    if (!includeDevDependencies) {
      rows.removeWhere((r) => r.kind == _DependencyKind.dev);
    }

    rows.sort();

    final showAll =
        argResults.flag('show-all') || argResults.flag('up-to-date');
    if (argResults.flag('json')) {
      await _outputJson(
        rows,
        mode,
        showAll: showAll,
        includeDevDependencies: includeDevDependencies,
      );
    } else {
      bool isNotFromSdk(PackageRange range) => range.source is! SdkSource;
      await _outputHuman(
        rows,
        mode,
        useColors: canUseAnsiCodes,
        showAll: showAll,
        includeDevDependencies: includeDevDependencies,
        lockFileExists: fileExists(entrypoint.lockFilePath),
        hasDirectDependencies: allDependencies(baseWorkspace).any(
          // Test if it contains non-SDK dependencies
          isNotFromSdk,
        ),
        hasDevDependencies: allDevDependencies(baseWorkspace).any(
          // Test if it contains non-SDK dependencies
          isNotFromSdk,
        ),
        showTransitiveDependencies: showTransitiveDependencies,
        hasUpgradableResolution: hasUpgradableResolution,
        hasResolvableResolution: hasResolvableResolution,
        directory: p.normalize(directory),
      );
    }
  }

  bool get showTransitiveDependencies {
    return argResults.flag('transitive');
  }

  late final bool prereleases = () {
    // First check if 'prereleases' was passed as an argument.
    // If that was not the case, check for use of the legacy spelling
    // 'pre-releases'.
    // Otherwise fall back to the default implied by the mode.
    if (argResults.wasParsed('prereleases')) {
      return argResults.flag('prereleases');
    }
    if (argResults.wasParsed('pre-releases')) {
      return argResults.flag('pre-releases');
    }
    return false;
  }();

  /// Retrieves the pubspec of package [id] from its [PackageId.source].
  ///
  /// Returns `null`, if given `null` as a convinience.
  Future<_VersionDetails?> _describeVersion(
    PackageId? id,
    bool isOverridden,
  ) async {
    if (id == null) {
      return null;
    }
    return _VersionDetails(await cache.describe(id), id, isOverridden);
  }

  /// Computes the closure of the graph of dependencies (not including
  /// `dev_dependencies`) from all workspace packages in [workspaceRoot], given
  /// the package versions in [resolution].
  ///
  /// The [resolution] is allowed to be a partial (or empty) resolution not
  /// satisfying all the dependencies of [workspaceRoot].
  Future<Set<String>> _nonDevDependencyClosure(
    Package workspaceRoot,
    Iterable<PackageId> resolution,
  ) async {
    final nameToId = {for (final id in resolution) id.name: id};

    final result = <String>{
      for (final p in workspaceRoot.transitiveWorkspace) p.name,
    };
    final queue = [
      for (final p in workspaceRoot.transitiveWorkspace) ...p.dependencies.keys,
    ];

    while (queue.isNotEmpty) {
      final name = queue.removeLast();
      if (!result.add(name)) {
        continue;
      }

      final id = nameToId[name];
      if (id == null) {
        continue; // allow partial resolutions
      }
      final pubspec = await cache.describe(id);
      queue.addAll(pubspec.dependencies.keys);
    }

    return result;
  }
}

/// Try to resolve the pubspec of [package] return [PackageId]s in the
/// resolution or `null` if no resolution was found.
Future<List<PackageId>?> _tryResolve(
  Package package,
  SystemCache cache, {
  LockFile? lockFile,
}) async {
  final solveResult = await tryResolveVersions(
    SolveType.upgrade,
    cache,
    package,
    lockFile: lockFile,
  );

  return solveResult?.packages;
}

Future<void> _outputJson(
  List<_PackageDetails> rows,
  _Mode mode, {
  required bool showAll,
  required bool includeDevDependencies,
}) async {
  final markedRows = Map.fromIterables(
    rows,
    await mode.markVersionDetails(rows),
  );
  if (!showAll) {
    rows.removeWhere((row) => row.isLatest);
  }
  if (!includeDevDependencies) {
    rows.removeWhere(
      (element) =>
          element.kind == _DependencyKind.dev ||
          element.kind == _DependencyKind.devTransitive,
    );
  }

  String kindString(_DependencyKind kind) {
    return {
          _DependencyKind.direct: 'direct',
          _DependencyKind.dev: 'dev',
        }[kind] ??
        'transitive';
  }

  log.message(
    const JsonEncoder.withIndent('  ').convert({
      'packages': [
        ...(rows..sort((a, b) => a.name.compareTo(b.name))).map(
          (packageDetails) => {
            'package': packageDetails.name,
            'kind': kindString(packageDetails.kind),
            'isDiscontinued': packageDetails.isDiscontinued,
            'replacedBy': packageDetails.discontinuedReplacedBy,
            'isCurrentRetracted': packageDetails.isCurrentRetracted,
            'isCurrentAffectedByAdvisory':
                packageDetails.isCurrentAffectedBySecurityAdvisory,
            'current': markedRows[packageDetails]![0].toJson(),
            'upgradable': markedRows[packageDetails]![1].toJson(),
            'resolvable': markedRows[packageDetails]![2].toJson(),
            'latest': markedRows[packageDetails]![3].toJson(),
          },
        ),
      ],
    }),
  );
}

Future<void> _outputHuman(
  List<_PackageDetails> rows,
  _Mode mode, {
  required bool showAll,
  required bool useColors,
  required bool includeDevDependencies,
  required bool lockFileExists,
  required bool hasDirectDependencies,
  required bool hasDevDependencies,
  required bool showTransitiveDependencies,
  required bool hasUpgradableResolution,
  required bool hasResolvableResolution,
  required String directory,
}) async {
  final directoryDesc = directory == '.' ? '' : ' in $directory';
  log.message('${mode.explanation(directoryDesc)}\n');
  final markedRows = Map.fromIterables(
    rows,
    await mode.markVersionDetails(rows),
  );

  List<FormattedString> formatted(_PackageDetails package) {
    // Link to pub.dev only if the package is hosted on pub.dev.
    final isFromPubDev = _isHostedOnPubDev(package);

    return [
      FormattedString(
        package.name,
        format: isFromPubDev ? _linkToPubDev(package.name) : null,
      ),
      ...markedRows[package]!.map((m) => m.toHuman()),
    ];
  }

  if (!showAll) {
    rows.removeWhere((row) => row.isLatest);
  }
  if (rows.isEmpty) {
    log.message(mode.foundNoBadText);
    return;
  }

  bool Function(_PackageDetails) hasKind(_DependencyKind kind) =>
      (row) => row.kind == kind;

  final directRows = rows.where(hasKind(_DependencyKind.direct)).map(formatted);
  final devRows = rows.where(hasKind(_DependencyKind.dev)).map(formatted);
  final transitiveRows = rows
      .where(hasKind(_DependencyKind.transitive))
      .map(formatted);
  final devTransitiveRows = rows
      .where(hasKind(_DependencyKind.devTransitive))
      .map(formatted);

  final formattedRows = <List<FormattedString>>[
    [
      'Package Name',
      'Current',
      'Upgradable',
      'Resolvable',
      'Latest',
    ].map((s) => format(s, log.bold)).toList(),
    if (hasDirectDependencies) ...[
      [
        if (directRows.isEmpty)
          format('\ndirect dependencies: ${mode.allGood}', log.bold)
        else
          format('\ndirect dependencies:', log.bold),
      ],
      ...directRows,
    ],
    if (includeDevDependencies && hasDevDependencies) ...[
      [
        if (devRows.isEmpty)
          format('\ndev_dependencies: ${mode.allGood}', log.bold)
        else
          format('\ndev_dependencies:', log.bold),
      ],
      ...devRows,
    ],
    if (showTransitiveDependencies) ...[
      if (transitiveRows.isNotEmpty)
        [format('\ntransitive dependencies:', log.bold)],
      ...transitiveRows,
      if (includeDevDependencies) ...[
        if (devTransitiveRows.isNotEmpty)
          [format('\ntransitive dev_dependencies:', log.bold)],
        ...devTransitiveRows,
      ],
    ],
  ];

  for (final line in log.renderTable(formattedRows, useColors)) {
    log.message(line);
  }

  final upgradable =
      rows.where((row) {
        final current = row.current;
        final upgradable = row.upgradable;
        return current != null &&
            upgradable != null &&
            current < upgradable &&
            // Include transitive only, if we show them
            (showTransitiveDependencies ||
                hasKind(_DependencyKind.direct)(row) ||
                hasKind(_DependencyKind.dev)(row));
      }).length;

  final notAtResolvable =
      rows.where((row) {
        final current = row.current;
        final upgradable = row.upgradable;
        final resolvable = row.resolvable;
        return (current != null || !lockFileExists) &&
            resolvable != null &&
            upgradable != null &&
            upgradable < resolvable &&
            // Include transitive only, if we show them
            (showTransitiveDependencies ||
                hasKind(_DependencyKind.direct)(row) ||
                hasKind(_DependencyKind.dev)(row));
      }).length;

  if (!hasUpgradableResolution || !hasResolvableResolution) {
    log.message(mode.noResolutionText);
  } else if (lockFileExists) {
    if (upgradable != 0) {
      if (upgradable == 1) {
        log.message(
          '\n1 upgradable dependency is locked (in pubspec.lock) to '
          'an older version.\n'
          'To update it, use `$topLevelProgram pub upgrade`.',
        );
      } else {
        log.message(
          '\n$upgradable upgradable dependencies are locked '
          '(in pubspec.lock) to older versions.\n'
          'To update these dependencies, use `$topLevelProgram pub upgrade`.',
        );
      }
    }

    if (notAtResolvable == 0 &&
        upgradable == 0 &&
        rows.isNotEmpty &&
        (directRows.isNotEmpty || devRows.isNotEmpty)) {
      log.message(
        'You are already using the newest resolvable versions listed in the '
        "'Resolvable' column.\n"
        "Newer versions, listed in 'Latest', may not be mutually compatible.",
      );
    } else if (directRows.isEmpty && devRows.isEmpty) {
      log.message(mode.allSafe);
    }
  } else {
    log.message(
      '\nNo pubspec.lock found. There are no Current versions.\n'
      'Run `$topLevelProgram pub get` to create a pubspec.lock '
      'with versions matching your '
      'pubspec.yaml.',
    );
  }
  if (notAtResolvable != 0) {
    if (notAtResolvable == 1) {
      log.message(
        '\n1 dependency is constrained to a '
        'version that is older than a resolvable version.\n'
        'To update it, ${mode.upgradeConstrained}.',
      );
    } else {
      log.message(
        '\n$notAtResolvable  dependencies are constrained to '
        'versions that are older than a resolvable version.\n'
        'To update these dependencies, ${mode.upgradeConstrained}.',
      );
    }
  }

  List<Advisory> advisoriesWithAffectedVersions(_PackageDetails package) {
    return package.advisories
        .where(
          (advisory) =>
              advisory.affectedVersions
                  .intersection(
                    [
                          package.current,
                          package.upgradable,
                          package.resolvable,
                          package.latest,
                        ]
                        .map((e) => e?._pubspec.version.canonicalizedVersion)
                        .toSet(),
                  )
                  .isNotEmpty,
        )
        .toList();
  }

  final advisoriesToDisplay = <String, List<Advisory>>{};
  for (final package in rows) {
    advisoriesToDisplay[package.name] = advisoriesWithAffectedVersions(package);
  }
  bool displayExtraInfo(_PackageDetails package) =>
      package.isDiscontinued ||
      package.isCurrentRetracted ||
      (advisoriesToDisplay[package.name]!.isNotEmpty);

  if (rows.any(displayExtraInfo)) {
    log.message('\n');
    for (var package in rows.where(displayExtraInfo)) {
      log.message(log.bold(package.name));
      if (package.isDiscontinued) {
        final replacedByText =
            package.discontinuedReplacedBy != null
                ? ', replaced by ${package.discontinuedReplacedBy}.'
                : '.';
        log.message(
          '    Package ${package.name} has been discontinued$replacedByText '
          'See https://dart.dev/go/package-discontinue',
        );
      }
      if (package.isCurrentRetracted) {
        log.message(
          '    Version ${package.current!._id.version} is retracted. '
          'See https://dart.dev/go/package-retraction',
        );
      }
      final displayedAdvisories = advisoriesToDisplay[package.name]!;
      if (displayedAdvisories.isNotEmpty) {
        final advisoriesText =
            displayedAdvisories.length > 1
                ? 'security advisories'
                : 'a security advisory';
        log.message(
          '    Package ${package.name} is affected by $advisoriesText. '
          'See https://dart.dev//go/pub-security-advisories',
        );
        log.message('\n');

        for (final advisory in displayedAdvisories) {
          final displayedVersions = advisory.affectedVersions.intersection(
            [
              package.current,
              package.upgradable,
              package.resolvable,
              package.latest,
            ].map((e) => e?._pubspec.version.canonicalizedVersion).toSet(),
          );
          log.message('    - "${advisory.summary}"');
          log.message('      Affects: ${displayedVersions.join(', ')}');
          log.message('      ${advisory.displayHandle}');
        }
      }
    }
  }
}

bool _isHostedOnPubDev(_PackageDetails package) {
  final details =
      package.latest ??
      package.resolvable ??
      package.upgradable ??
      package.current;
  return details != null &&
      details._id.source is HostedSource &&
      HostedSource.isFromPubDev(details._id);
}

String Function(String) _linkToPubDev(String packageName) {
  return (String name) =>
      log.link(name, 'https://pub.dev/packages/$packageName');
}

abstract class _Mode {
  /// Analyzes the [_PackageDetails] according to a --mode and outputs a
  /// corresponding list of the versions
  /// [current, upgradable, resolvable, latest].
  Future<List<List<_Details>>> markVersionDetails(
    List<_PackageDetails> packageDetails,
  );

  String explanation(String directoryDescription);
  String get foundNoBadText;
  String get allGood;
  String get noResolutionText;
  String get upgradeConstrained;
  String get allSafe;

  Pubspec resolvablePubspec(Pubspec pubspec);
}

class _OutdatedMode implements _Mode {
  @override
  String explanation(String directoryDescription) => '''
Showing outdated packages$directoryDescription.
[${log.red('*')}] indicates versions that are not the latest available.
''';

  @override
  String get foundNoBadText => 'Found no outdated packages';

  @override
  String get allGood => 'all up-to-date.';

  @override
  String get noResolutionText =>
      '''No resolution was found. Try running `$topLevelProgram pub upgrade --dry-run` to explore why.''';

  @override
  String get upgradeConstrained =>
      'edit pubspec.yaml, or run '
      '`$topLevelProgram pub upgrade --major-versions`';

  @override
  String get allSafe => 'all dependencies are up-to-date.';

  @override
  Future<List<List<_Details>>> markVersionDetails(
    List<_PackageDetails> packages,
  ) async {
    final rows = <List<_Details>>[];
    for (final packageDetails in packages) {
      final cols = <_Details>[];
      _VersionDetails? previous;
      for (final versionDetails in [
        packageDetails.current,
        packageDetails.upgradable,
        packageDetails.resolvable,
        packageDetails.latest,
      ]) {
        String Function(String)? color;
        String? prefix;
        String? suffix;
        if (versionDetails != null) {
          final isLatest = versionDetails == packageDetails.latest;
          final isCurrent = versionDetails == packageDetails.current;
          if (isLatest) {
            color = versionDetails == previous ? color = log.gray : null;
          } else {
            color = log.red;
            if (isCurrent) {
              if (packageDetails.isCurrentRetracted) {
                suffix = ' (retracted)';
              }
            }
          }
          final advisories = packageDetails.advisories;
          final hasAdvisory =
              advisories
                  .where(
                    (advisory) => advisory.affectedVersions.contains(
                      versionDetails._pubspec.version.canonicalizedVersion,
                    ),
                  )
                  .isNotEmpty;
          if (hasAdvisory) {
            suffix = '${suffix ?? ''} (advisory)';
          }
          prefix = isLatest ? '' : '*';
        }
        cols.add(
          _MarkedVersionDetails(
            versionDetails,
            format: color,
            prefix: prefix,
            suffix: suffix,
          ),
        );
        previous = versionDetails;
      }
      if (packageDetails.isDiscontinued == true) {
        cols.add(_SimpleDetails('(discontinued)'));
      }
      rows.add(cols);
    }
    return rows;
  }

  @override
  Pubspec resolvablePubspec(Pubspec pubspec) {
    return stripVersionBounds(pubspec);
  }
}

/// Details about a single version of a package.
class _VersionDetails {
  final Pubspec _pubspec;

  /// True if this version is overridden.
  final bool _overridden;
  final PackageId _id;
  _VersionDetails(this._pubspec, this._id, this._overridden);

  /// A string representation of this version to include in the outdated report.
  String get describe {
    final version = _pubspec.version;
    var suffix = '';
    if (_overridden) {
      suffix = ' (overridden)';
    } else if (_id.source is SdkSource) {
      // Version is not relevant for sdk-packages.
      return '(sdk)';
    } else if (_id.source is GitSource) {
      suffix = ' (git)';
    } else if (_id.source is PathSource) {
      suffix = ' (path)';
    }
    return '$version$suffix';
  }

  Map<String, Object> toJson() => {
    'version': _pubspec.version.toString(),
    if (_overridden) 'overridden': true,
  };

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is _VersionDetails &&
          _overridden == other._overridden &&
          _id.source == other._id.source &&
          _pubspec.version == other._pubspec.version;

  bool operator <(_VersionDetails other) =>
      _overridden == other._overridden &&
      _id.source == other._id.source &&
      _pubspec.version < other._pubspec.version;

  @override
  int get hashCode => Object.hash(_pubspec.version, _id.source, _overridden);
}

class _PackageDetails implements Comparable<_PackageDetails> {
  final String name;
  final _VersionDetails? current;
  final _VersionDetails? upgradable;
  final _VersionDetails? resolvable;
  final _VersionDetails? latest;
  final _DependencyKind kind;
  final bool isDiscontinued;
  final String? discontinuedReplacedBy;
  final bool isCurrentRetracted;
  final bool isLatest;

  /// List of advisories affecting this package which are not present in the
  /// `ignored_advisories` list in the pubspec.
  final List<Advisory> advisories;
  final bool isCurrentAffectedBySecurityAdvisory;

  _PackageDetails({
    required this.name,
    required this.current,
    required this.upgradable,
    required this.resolvable,
    required this.latest,
    required this.kind,
    required this.isDiscontinued,
    required this.discontinuedReplacedBy,
    required this.isCurrentRetracted,
    required this.isLatest,
    required this.advisories,
    required this.isCurrentAffectedBySecurityAdvisory,
  });

  @override
  int compareTo(_PackageDetails other) {
    if (kind != other.kind) {
      return kind.index.compareTo(other.kind.index);
    }
    return name.compareTo(other.name);
  }
}

_DependencyKind _kind(
  String name,
  Entrypoint entrypoint,
  Set<String> nonDevTransitive,
) {
  if (hasDependency(entrypoint.workspaceRoot, name)) {
    return _DependencyKind.direct;
  } else if (hasDevDependency(entrypoint.workspaceRoot, name)) {
    return _DependencyKind.dev;
  } else {
    if (nonDevTransitive.contains(name)) {
      return _DependencyKind.transitive;
    } else {
      return _DependencyKind.devTransitive;
    }
  }
}

enum _DependencyKind {
  /// Direct non-dev dependencies.
  direct,

  /// Direct dev dependencies.
  dev,

  /// Transitive dependencies of direct dependencies.
  transitive,

  /// Transitive dependencies needed only by dev_dependencies.
  devTransitive,
}

abstract class _Details {
  FormattedString toHuman();
  Object? toJson();
}

class _SimpleDetails implements _Details {
  final String details;

  _SimpleDetails(this.details);

  @override
  FormattedString toHuman() => FormattedString(details);

  @override
  Object? toJson() => null;
}

class _MarkedVersionDetails implements _Details {
  final MapEntry<String, Object>? _jsonExplanation;
  final _VersionDetails? _versionDetails;
  final String Function(String)? _format;
  final String? _prefix;
  final String? _suffix;

  _MarkedVersionDetails(
    this._versionDetails, {
    String Function(String)? format,
    String? prefix = '',
    String? suffix = '',
    MapEntry<String, Object>? jsonExplanation,
  }) : _format = format,
       _prefix = prefix,
       _suffix = suffix,
       _jsonExplanation = jsonExplanation;

  @override
  FormattedString toHuman() => FormattedString(
    _versionDetails?.describe ?? '-',
    format: _format,
    prefix: _prefix,
    suffix: _suffix,
  );

  @override
  Object? toJson() {
    if (_versionDetails == null) return null;

    final jsonExplanation = _jsonExplanation;
    return jsonExplanation == null
        ? _versionDetails.toJson()
        : (_versionDetails.toJson()..addEntries([jsonExplanation]));
  }
}

/// Whether the package [name] is overridden anywhere in the workspace rooted at
/// [workspaceRoot].
bool hasOverride(Package workspaceRoot, String name) {
  return workspaceRoot.allOverridesInWorkspace.containsKey(name);
}

/// Whether the package [name] is depended on directly anywhere in the workspace
/// rooted at [workspaceRoot].
bool hasDependency(Package workspaceRoot, String name) {
  return workspaceRoot.transitiveWorkspace.any(
    (p) => p.dependencies.containsKey(name),
  );
}

/// Whether the package [name] is dev-depended on directly anywhere in the
/// workspace rooted at [workspaceRoot].
bool hasDevDependency(Package workspaceRoot, String name) {
  return workspaceRoot.transitiveWorkspace.any(
    (p) => p.devDependencies.containsKey(name),
  );
}

Iterable<PackageRange> allDependencies(Package workspaceRoot) =>
    workspaceRoot.transitiveWorkspace.expand((p) => p.dependencies.values);

Iterable<PackageRange> allDevDependencies(Package workspaceRoot) =>
    workspaceRoot.transitiveWorkspace.expand((p) => p.devDependencies.values);
