// Copyright (c) 2012, 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 'package:args/command_runner.dart';
import 'package:pub_semver/pub_semver.dart';

import '../command.dart';
import '../command_runner.dart';
import '../entrypoint.dart';
import '../io.dart';
import '../log.dart' as log;
import '../package.dart';
import '../package_name.dart';
import '../pubspec.dart';
import '../pubspec_utils.dart';
import '../solver.dart';
import '../utils.dart';

/// Handles the `upgrade` pub command.
class UpgradeCommand extends PubCommand {
  @override
  String get name => 'upgrade';
  @override
  String get description =>
      "Upgrade the current package's dependencies to latest versions.";
  @override
  String get argumentsDescription => '[dependencies...]';
  @override
  String get docUrl => 'https://dart.dev/tools/pub/cmd/pub-upgrade';

  @override
  bool get isOffline => argResults.flag('offline');

  UpgradeCommand() {
    argParser.addFlag(
      'offline',
      help: 'Use cached packages instead of accessing the network.',
    );

    argParser.addFlag(
      'dry-run',
      abbr: 'n',
      negatable: false,
      help: "Report what dependencies would change but don't change any.",
    );

    argParser.addFlag(
      'precompile',
      help: 'Precompile executables in immediate dependencies.',
    );

    argParser.addFlag(
      'null-safety',
      hide: true,
      negatable: false,
      help: 'Upgrade constraints in pubspec.yaml to null-safety versions',
    );
    argParser.addFlag('nullsafety', negatable: false, hide: true);

    argParser.addFlag('packages-dir', hide: true);

    argParser.addFlag(
      'tighten',
      help:
          'Updates lower bounds in pubspec.yaml to match the resolved version.',
      negatable: false,
    );

    argParser.addFlag(
      'unlock-transitive',
      help:
          'Also upgrades the transitive dependencies '
          'of the listed [dependencies]',
      negatable: false,
    );

    argParser.addFlag(
      'major-versions',
      help:
          'Upgrades packages to their latest resolvable versions, '
          'and updates pubspec.yaml.',
      negatable: false,
    );

    argParser.addFlag(
      'example',
      defaultsTo: true,
      help: 'Also run in `example/` (if it exists).',
      hide: true,
    );

    argParser.addOption(
      'directory',
      abbr: 'C',
      help: 'Run this in the directory <dir>.',
      valueHelp: 'dir',
    );
  }

  /// Avoid showing spinning progress messages when not in a terminal.
  bool get _shouldShowSpinner => terminalOutputForStdout;

  bool get _dryRun => argResults.flag('dry-run');

  bool get _tighten => argResults.flag('tighten');

  bool get _precompile => argResults.flag('precompile');

  late final Future<List<String>> _packagesToUpgrade =
      _computePackagesToUpgrade();

  /// List of package names to upgrade, if empty then upgrade all packages.
  ///
  /// This allows the user to specify list of names that they want the
  /// upgrade command to affect.
  Future<List<String>> _computePackagesToUpgrade() async {
    if (argResults.flag('unlock-transitive')) {
      final graph = await entrypoint.packageGraph;
      return argResults.rest
          .expand(
            (package) =>
                graph.transitiveDependencies(package).map((p) => p.name),
          )
          .toSet()
          .toList();
    } else {
      return argResults.rest;
    }
  }

  bool get _upgradeNullSafety =>
      argResults.flag('nullsafety') || argResults.flag('null-safety');

  bool get _upgradeMajorVersions => argResults.flag('major-versions');

  @override
  Future<void> runProtected() async {
    if (_upgradeNullSafety) {
      dataError('''The `--null-safety` flag is no longer supported.
Consider using the Dart 2.19 sdk to migrate to null safety.''');
    }
    if (argResults.wasParsed('packages-dir')) {
      log.warning(
        log.yellow(
          'The --packages-dir flag is no longer used and does nothing.',
        ),
      );
    }

    if (_upgradeMajorVersions) {
      if (argResults.flag('example') && entrypoint.example != null) {
        log.warning(
          'Running `upgrade --major-versions` only in `${entrypoint.workspaceRoot.dir}`. Run `$topLevelProgram pub upgrade --major-versions --directory example/` separately.',
        );
      }
      await _runUpgradeMajorVersions();
    } else {
      await _runUpgrade(entrypoint);
      if (_tighten) {
        if (argResults.flag('example') && entrypoint.example != null) {
          log.warning(
            'Running `upgrade --tighten` only in `${entrypoint.workspaceRoot.dir}`. Run `$topLevelProgram pub upgrade --tighten --directory example/` separately.',
          );
        }
        final changes = entrypoint.tighten(
          packagesToUpgrade: await _packagesToUpgrade,
        );
        entrypoint.applyChanges(changes, _dryRun);
      }
    }
    if (argResults.flag('example') && entrypoint.example != null) {
      // Reload the entrypoint to ensure we pick up potential changes that has
      // been made.
      final exampleEntrypoint = Entrypoint(directory, cache).example!;
      await _runUpgrade(exampleEntrypoint, onlySummary: true);
    }
  }

  Future<void> _runUpgrade(Entrypoint e, {bool onlySummary = false}) async {
    await e.acquireDependencies(
      SolveType.upgrade,
      unlock: await _packagesToUpgrade,
      dryRun: _dryRun,
      precompile: _precompile,
      summaryOnly: onlySummary,
    );

    _showOfflineWarning();
  }

  /// Return names of packages to be upgraded, and throws [UsageException] if
  /// any package names not in the direct dependencies or dev_dependencies are
  /// given.
  ///
  /// This assumes that `--major-versions` was passed.
  Future<List<String>> _directDependenciesToUpgrade() async {
    assert(_upgradeMajorVersions);

    final directDeps =
        {
          for (final package
              in entrypoint.workspaceRoot.transitiveWorkspace) ...[
            ...package.dependencies.keys,
            ...package.devDependencies.keys,
          ],
        }.toList();
    final packagesToUpgrade = await _packagesToUpgrade;
    final toUpgrade =
        packagesToUpgrade.isEmpty ? directDeps : packagesToUpgrade;

    // Check that all package names in upgradeOnly are direct-dependencies
    final notInDeps = toUpgrade.where((n) => !directDeps.contains(n));
    if (argResults.rest.any(notInDeps.contains)) {
      usageException('''
Dependencies specified in `$topLevelProgram pub upgrade --major-versions <dependencies>` must
be direct 'dependencies' or 'dev_dependencies', following packages are not:
 - ${notInDeps.join('\n - ')}

''');
    }

    return toUpgrade;
  }

  Future<void> _runUpgradeMajorVersions() async {
    final toUpgrade = await _directDependenciesToUpgrade();
    // Solve [resolvablePubspec] in-memory and consolidate the resolved
    // versions of the packages into a map for quick searching.
    final resolvedPackages = <String, PackageId>{};
    final solveResult = await log.spinner('Resolving dependencies', () async {
      return await resolveVersions(
        SolveType.upgrade,
        cache,
        entrypoint.workspaceRoot.transformWorkspace(
          (package) => stripVersionBounds(package.pubspec),
        ),
      );
    }, condition: _shouldShowSpinner);
    for (final resolvedPackage in solveResult.packages) {
      resolvedPackages[resolvedPackage.name] = resolvedPackage;
    }
    final dependencyOverriddenDeps = <String>[];
    // Changes to be made to `pubspec.yaml` of each package.
    // Mapping from original to changed value.
    var changes = <Package, Map<PackageRange, PackageRange>>{};
    for (final package in entrypoint.workspaceRoot.transitiveWorkspace) {
      final declaredUpgradableDependencies = [
        ...package.dependencies.values,
        ...package.devDependencies.values,
      ].where((dep) => dep.description.hasMultipleVersions);
      for (final dep in declaredUpgradableDependencies) {
        final resolvedPackage = resolvedPackages[dep.name]!;
        if (!toUpgrade.contains(dep.name)) {
          // If we're not trying to upgrade this package, or it wasn't in the
          // resolution somehow, then we ignore it.
          continue;
        }

        // Skip [dep] if it has a dependency_override.
        if (entrypoint.workspaceRoot.pubspec.dependencyOverrides.containsKey(
          dep.name,
        )) {
          dependencyOverriddenDeps.add(dep.name);
          continue;
        }

        if (dep.constraint.allowsAll(resolvedPackage.version)) {
          // If constraint allows the resolvable version we found, then there is
          // no need to update the `pubspec.yaml`
          continue;
        }

        (changes[package] ??= {})[dep] = dep.toRef().withConstraint(
          VersionConstraint.compatibleWith(resolvedPackage.version),
        );
      }
    }

    if (_tighten) {
      // Do another solve with the updated constraints to obtain the correct
      // versions to tighten to. This should be fast (everything is cached, and
      // no backtracking needed) so we don't show a spinner.

      final solveResult = await resolveVersions(
        SolveType.upgrade,
        cache,
        entrypoint.workspaceRoot.transformWorkspace((package) {
          return applyChanges(package.pubspec, changes[package] ?? {});
        }),
      );
      changes = entrypoint.tighten(
        packagesToUpgrade: await _packagesToUpgrade,
        existingChanges: changes,
        packageVersions: solveResult.packages,
      );
    }

    // When doing '--majorVersions' for specific packages we try to update other
    // packages as little as possible to make a focused change (SolveType.get).
    //
    // But without a specific package we want to get as many non-major updates
    // as possible (SolveType.upgrade).
    final solveType =
        (await _packagesToUpgrade).isEmpty ? SolveType.upgrade : SolveType.get;

    entrypoint.applyChanges(changes, _dryRun);
    await entrypoint
        .withUpdatedRootPubspecs({
          for (final MapEntry(key: package, value: changesForPackage)
              in changes.entries)
            package: applyChanges(package.pubspec, changesForPackage),
        })
        .acquireDependencies(
          solveType,
          dryRun: _dryRun,
          precompile: !_dryRun && _precompile,
          unlock: await _packagesToUpgrade,
        );

    // If any of the packages to upgrade are dependency overrides, then we
    // show a warning.
    final toUpgradeOverrides = toUpgrade.where(
      entrypoint.workspaceRoot.allOverridesInWorkspace.containsKey,
    );
    if (toUpgradeOverrides.isNotEmpty) {
      log.warning(
        'Warning: dependency_overrides prevents upgrades for: '
        '${toUpgradeOverrides.join(', ')}',
      );
    }

    _showOfflineWarning();
  }

  Pubspec applyChanges(
    Pubspec original,
    Map<PackageRange, PackageRange> changes,
  ) {
    final dependencies = {...original.dependencies};
    final devDependencies = {...original.devDependencies};

    for (final change in changes.values) {
      if (dependencies[change.name] != null) {
        dependencies[change.name] = change;
      } else {
        devDependencies[change.name] = change;
      }
    }
    return original.copyWith(
      dependencies: dependencies.values,
      devDependencies: devDependencies.values,
    );
  }

  void _showOfflineWarning() {
    if (isOffline) {
      log.warning(
        'Warning: Upgrading when offline may not update you to the '
        'latest versions of your dependencies.',
      );
    }
  }
}
