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

import '../command.dart';
import '../command_runner.dart';
import '../entrypoint.dart';
import '../io.dart';
import '../log.dart' as log;
import '../package_name.dart';
import '../path.dart';
import '../pubspec.dart';
import '../sdk.dart';
import '../solver/type.dart';
import '../source/hosted.dart';
import '../source/root.dart';
import '../utils.dart';

class UnpackCommand extends PubCommand {
  @override
  String get name => 'unpack';

  @override
  String get description => '''
Downloads a package and unpacks it in place.

For example:

  $topLevelProgram pub unpack foo

Downloads and extracts the latest stable version of package:foo from pub.dev
in a directory `foo-<version>`.

  $topLevelProgram pub unpack foo@1.2.3-pre --no-resolve

Downloads and extracts package:foo version 1.2.3-pre in a directory
`foo-1.2.3-pre` without running implicit `pub get`.

  $topLevelProgram pub unpack foo --output=archives

Downloads and extracts the latest stable version of package:foo in a directory
`archives/foo-<version>`.

  $topLevelProgram pub unpack 'foo@{hosted:"https://my_repo.org"}'

Downloads and extracts the latest stable version of package:foo from my_repo.org
in a directory `foo-<version>`.
''';

  @override
  String get argumentsDescription => 'package-name[@<descriptor>]';

  @override
  String get docUrl => 'https://dart.dev/tools/pub/cmd/pub-unpack';

  @override
  bool get takesArguments => true;

  UnpackCommand() {
    argParser.addFlag(
      'resolve',
      help: 'Whether to run pub get in the downloaded folder.',
      defaultsTo: true,
      hide: log.verbosity != log.Verbosity.all,
    );
    argParser.addFlag(
      'force',
      abbr: 'f',
      help: 'Overwrite the target directory if it already exists.',
    );
    argParser.addOption(
      'output',
      abbr: 'o',
      help: 'Download and extract the package in the specified directory.',
      defaultsTo: '.',
    );
  }

  static final _argRegExp = RegExp(
    r'^(?<name>[a-zA-Z0-9_.]+)'
    r'(?:[:@](?<descriptor>.*))?$',
  );

  @override
  Future<void> runProtected() async {
    if (argResults.rest.isEmpty) {
      usageException('Provide a package name.');
    }
    if (argResults.rest.length > 1) {
      usageException('Provide only a single package name.');
    }
    final arg = argResults.rest[0];
    final match = _argRegExp.firstMatch(arg);
    if (match == null) {
      usageException('Use the form package@descriptor to specify the package.');
    }
    final parseResult = _parseDescriptor(
      match.namedGroup('name')!,
      match.namedGroup('descriptor'),
    );

    if (parseResult.description is! HostedDescription) {
      fail('Can only fetch hosted packages.');
    }
    final versions = await parseResult.source.doGetVersions(
      parseResult.toRef(),
      null,
      cache,
    );
    final constraint = parseResult.constraint;
    versions.removeWhere((id) => !constraint.allows(id.version));
    if (versions.isEmpty) {
      fail('No matching versions of ${parseResult.name}.');
    }
    versions.sort((id1, id2) => id1.version.compareTo(id2.version));

    final id = versions.last;
    final name = id.name;

    final outputArg = argResults.optionWithDefault('output');
    final destinationDir = p.join(outputArg, '$name-${id.version}');
    if (entryExists(destinationDir)) {
      if (argResults.flag('force')) {
        deleteEntry(destinationDir);
      } else {
        fail(
          'Target directory `$destinationDir` already exists. '
          'Use --force to overwrite.',
        );
      }
    }
    await log.progress(
      'Downloading $name ${id.version} to `$destinationDir`',
      () async {
        await cache.hosted.downloadInto(id, destinationDir, cache);
      },
    );

    if (argResults.flag('resolve')) {
      try {
        final pubspec = Pubspec.load(
          destinationDir,
          cache.sources,
          containingDescription: ResolvedRootDescription.fromDir(
            destinationDir,
          ),
        );
        final buffer = StringBuffer();
        if (pubspec.resolution != Resolution.none) {
          log.message('''
This package was developed as part of a workspace.

Creating `pubspec_overrides.yaml` to resolve it alone.''');
          buffer.writeln('resolution:');
        }
        if (pubspec.dependencyOverrides.isNotEmpty) {
          log.message('''
This package was developed with dependency_overrides.

Creating `pubspec_overrides.yaml` to resolve it without those overrides.''');
          buffer.writeln('dependency_overrides:');
        }
        if (buffer.isNotEmpty) {
          writeTextFile(
            p.join(destinationDir, 'pubspec_overrides.yaml'),
            buffer.toString(),
          );
        }
        final e = Entrypoint(destinationDir, cache);
        await e.acquireDependencies(SolveType.get);
      } finally {
        log.message('To explore type: cd $destinationDir');
        final exampleDir = p.join(destinationDir, 'example');
        if (dirExists(exampleDir)) {
          log.message('To explore the example type: cd $exampleDir');
        }
      }
    }
  }

  PackageRange _parseDescriptor(String packageName, String? descriptor) {
    late final defaultDescription = HostedDescription(
      packageName,
      cache.hosted.defaultUrl,
    );
    if (descriptor == null) {
      return PackageRange(
        PackageRef(packageName, defaultDescription),
        VersionConstraint.any,
      );
    }
    try {
      // An unquoted version constraint is not always valid yaml.
      // But we want to allow it here anyways.
      final constraint = VersionConstraint.parse(descriptor);
      return PackageRange(
        PackageRef(packageName, defaultDescription),
        constraint,
      );
    } on FormatException {
      final parsedDescriptor = loadYaml(descriptor);
      // Use the pubspec parsing mechanism for parsing the descriptor.
      final Pubspec dummyPubspec;
      try {
        dummyPubspec = Pubspec.fromMap(
          {
            'dependencies': {packageName: parsedDescriptor},
            'environment': {'sdk': sdk.version.toString()},
          },
          cache.sources,
          // Resolve relative paths relative to current, not where the
          // pubspec.yaml is.
          location: p.toUri(p.join(p.current, 'descriptor')),
          containingDescription: ResolvedRootDescription.fromDir('.'),
        );
      } on FormatException catch (e) {
        usageException('Failed parsing package specification: ${e.message}');
      }
      return dummyPubspec.dependencies[packageName]!;
    }
  }
}
