// 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 '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 '../log.dart';
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.
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.spinner('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);

    // 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.
    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 {
      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,
            '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);
