// 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 'dart:math';

import 'package:collection/collection.dart' show IterableExtension;
import 'package:path/path.dart' as p;

import '../command.dart';
import '../command_runner.dart';
import '../entrypoint.dart';
import '../io.dart';
import '../lock_file.dart';
import '../log.dart' as log;
import '../package.dart';
import '../package_name.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 a terminal, and
  /// when we are outputting machine-readable json.
  bool get _shouldShowSpinner =>
      terminalOutputForStdout && !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.\n'
          '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.',
    );
    argParser.addOption(
      'directory',
      abbr: 'C',
      help: 'Run this in the directory <dir>.',
      valueHelp: 'dir',
    );
  }

  @override
  Future<void> runProtected() async {
    if (argResults['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.');
    }

    final rootPubspec = includeDependencyOverrides
        ? entrypoint.workspaceRoot.pubspec
        : stripDependencyOverrides(entrypoint.workspaceRoot.pubspec);

    final upgradablePubspec = includeDevDependencies
        ? rootPubspec
        : stripDevDependencies(rootPubspec);

    final resolvablePubspec = await mode.resolvablePubspec(upgradablePubspec);

    late List<PackageId> upgradablePackages;
    late List<PackageId> resolvablePackages;
    late bool hasUpgradableResolution;
    late bool hasResolvableResolution;

    await log.spinner(
      'Resolving',
      () async {
        final upgradablePackagesResult = await _tryResolve(
          Package(
            upgradablePubspec,
            entrypoint.workspaceRoot.dir,
            entrypoint.workspaceRoot.workspaceChildren,
          ),
          cache,
          lockFile: entrypoint.lockFile,
        );
        hasUpgradableResolution = upgradablePackagesResult != null;
        upgradablePackages = upgradablePackagesResult ?? [];

        final resolvablePackagesResult = await _tryResolve(
          Package(
            resolvablePubspec,
            entrypoint.workspaceRoot.dir,
            entrypoint.workspaceRoot.workspaceChildren,
          ),
          cache,
          lockFile: entrypoint.lockFile,
        );
        hasResolvableResolution = resolvablePackagesResult != null;
        resolvablePackages = resolvablePackagesResult ?? [];
      },
      condition: _shouldShowSpinner,
    );

    // 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 (!entrypoint.workspaceRoot.pubspec.dependencyOverrides
          .containsKey(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(
        rootPubspec.dependencies[name]?.toRef(),
        allowPrereleases: prereleases,
      );
      latest ??= await cache.getLatest(
        rootPubspec.devDependencies[name]?.toRef(),
        allowPrereleases: prereleases,
      );
      // If not overridden and present in either upgradable or resolvable we
      // use this reference to find the latest
      if (!upgradablePubspec.dependencyOverrides.containsKey(name)) {
        latest ??= await cache.getLatest(
          upgradable?.toRef(),
          version: upgradable?.version,
          allowPrereleases: prereleases,
        );
      }
      if (!resolvablePubspec.dependencyOverrides.containsKey(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, 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,
        upgradablePubspec.dependencyOverrides.containsKey(name),
      );

      final resolvableVersionDetails = await _describeVersion(
        resolvable,
        resolvablePubspec.dependencyOverrides.containsKey(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 = <String>{
      entrypoint.workspaceRoot.name,
    };
    // Add all dependencies from the lockfile.
    for (final id in [
      ...currentPackages,
      ...upgradablePackages,
      ...resolvablePackages,
    ]) {
      if (!visited.add(id.name)) continue;
      rows.add(await analyzeDependency(id.toRef()));
    }

    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 {
      await _outputHuman(
        rows,
        mode,
        useColors: canUseAnsiCodes,
        showAll: showAll,
        includeDevDependencies: includeDevDependencies,
        lockFileExists: fileExists(entrypoint.lockFilePath),
        hasDirectDependencies: rootPubspec.dependencies.values.any(
          // Test if it contains non-SDK dependencies
          (c) => c.source is! SdkSource,
        ),
        hasDevDependencies: rootPubspec.devDependencies.values.any(
          // Test if it contains non-SDK dependencies
          (c) => c.source is! SdkSource,
        ),
        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 [name] in [version] from [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 [root], given the package versions
  /// in [resolution].
  ///
  /// The [resolution] is allowed to be a partial (or empty) resolution not
  /// satisfying all the dependencies of [root].
  Future<Set<String>> _nonDevDependencyClosure(
    Package root,
    Iterable<PackageId> resolution,
  ) async {
    final nameToId = {for (final id in resolution) id.name: id};

    final nonDevDependencies = <String>{root.name};
    final queue = [...root.dependencies.keys];

    while (queue.isNotEmpty) {
      final name = queue.removeLast();
      if (!nonDevDependencies.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 nonDevDependencies;
  }
}

/// Try to solve [pubspec] 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(
    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,
              '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) => [
        _FormattedString(package.name),
        ...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,
      ],
    ],
  ];

  final columnWidths = <int, int>{};
  for (var i = 0; i < formattedRows.length; i++) {
    if (formattedRows[i].length > 1) {
      for (var j = 0; j < formattedRows[i].length; j++) {
        final currentMaxWidth = columnWidths[j] ?? 0;
        columnWidths[j] = max(
          formattedRows[i][j].computeLength(useColors: useColors),
          currentMaxWidth,
        );
      }
    }
  }

  for (final row in formattedRows) {
    final b = StringBuffer();
    for (var j = 0; j < row.length; j++) {
      b.write(row[j].formatted(useColors: useColors));
      b.write(
        ' ' *
            ((columnWidths[j]! + 2) -
                row[j].computeLength(useColors: useColors)),
      );
    }
    log.message(b.toString());
  }

  var 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;

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

  var 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',
        );
      }
      var 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) {
          var 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}');
        }
      }
    }
  }
}

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;

  Future<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
  Future<Pubspec> resolvablePubspec(Pubspec? pubspec) async {
    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 (entrypoint.workspaceRoot.dependencies.containsKey(name)) {
    return _DependencyKind.direct;
  } else if (entrypoint.workspaceRoot.devDependencies.containsKey(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,
}

_FormattedString _format(
  String value,
  String Function(String) format, {
  String? prefix = '',
}) {
  return _FormattedString(value, format: format, prefix: prefix);
}

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;

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

class _FormattedString {
  final String value;

  /// Should apply the ansi codes to present this string.
  final String Function(String) _format;

  /// A prefix for marking this string if colors are not used.
  final String _prefix;

  final String _suffix;

  _FormattedString(
    this.value, {
    String Function(String)? format,
    String? prefix,
    String? suffix,
  })  : _format = format ?? _noFormat,
        _prefix = prefix ?? '',
        _suffix = suffix ?? '';

  String formatted({required bool useColors}) {
    return useColors
        ? _format(_prefix + value + _suffix)
        : _prefix + value + _suffix;
  }

  int computeLength({required bool? useColors}) {
    return _prefix.length + value.length + _suffix.length;
  }

  static String _noFormat(String x) => x;
}
