// Copyright (c) 2015, 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.

// TODO(sigurdm): This should ideally be a separate _test.dart file, however to
// share the compiled snapshot for the embedded test-runner this is included by
// embedding_test.dart

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

import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';

import '../descriptor.dart' as d;
import '../test_pub.dart';
import 'embedding_test.dart';

late PackageServer server;

void testEnsurePubspecResolved() {
  group('ensurePubspecResolved', () {
    setUp(() async {
      server = await servePackages();

      server.serve('foo', '1.0.0');
      server.serve('foo', '2.0.0');

      await d.dir(appPath, [
        d.appPubspec(),
        d.dir('web', []),
        d.dir('bin', [d.file('script.dart', "main() => print('hello!');")]),
      ]).create();

      await pubGet();
    });

    test(
        'does not require a pub get '
        'if a `flutter_gen` package is injected into package_config.json',
        () async {
      await d.dir('bar', [
        d.pubspec({'name': 'bar'}),
      ]).create();
      await d.dir(appPath, [
        d.appPubspec(
          dependencies: {
            'bar': {'path': '../bar'},
          },
        ),
      ]).create();

      await pubGet();

      final packageConfig =
          p.join(d.sandbox, 'myapp', '.dart_tool', 'package_config.json');
      final contents =
          json.decode(File(packageConfig).readAsStringSync()) as Map;
      (contents['packages'] as List).add({
        'name': 'flutter_gen',
        'rootUri': 'flutter_gen',
        'languageVersion': '2.8',
      });
      writeTextFile(packageConfig, json.encode(contents));

      await runPub(
        args: ['run', 'bin/script.dart'],
        output: endsWith('hello!'),
      );
    });

    group('Does an implicit pub get if', () {
      test("there's no lockfile", () async {
        File(p.join(d.sandbox, 'myapp/pubspec.lock')).deleteSync();
        await _implicitPubGet('No pubspec.lock file found');
      });

      test("there's no package_config.json", () async {
        File(p.join(d.sandbox, 'myapp/.dart_tool/package_config.json'))
            .deleteSync();

        await _implicitPubGet(
          '`./pubspec.yaml` exists without corresponding `./pubspec.yaml` or `.dart_tool/pub/workspace_ref.json`.',
        );
      });

      test('the pubspec has a new dependency', () async {
        await d.dir('foo', [d.libPubspec('foo', '1.0.0')]).create();

        await d.dir(appPath, [
          d.appPubspec(
            dependencies: {
              'foo': {'path': '../foo'},
            },
          ),
        ]).create();

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.yaml');

        await _implicitPubGet('The pubspec.yaml file has changed since the '
            'pubspec.lock file was generated');
      });

      test('the lockfile has a dependency from the wrong source', () async {
        await d.dir(appPath, [
          d.appPubspec(dependencies: {'foo': '1.0.0'}),
        ]).create();

        await pubGet();

        await createLockFile(appPath, dependenciesInSandBox: ['foo']);

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.yaml');

        await _implicitPubGet('The pubspec.yaml file has changed since the '
            'pubspec.lock file was generated');
      });

      test('the lockfile has a dependency from an unknown source', () async {
        await d.dir(appPath, [
          d.appPubspec(dependencies: {'foo': '1.0.0'}),
        ]).create();

        await pubGet();

        await d.dir(appPath, [
          d.file(
            'pubspec.lock',
            yaml({
              'packages': {
                'foo': {
                  'description': 'foo',
                  'version': '1.0.0',
                  'source': 'sdk',
                },
              },
            }),
          ),
        ]).create();

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.yaml');

        await _implicitPubGet('The pubspec.yaml file has changed since the '
            'pubspec.lock file was generated.');
      });

      test('the lockfile has a dependency with the wrong description',
          () async {
        await d.dir('bar', [d.libPubspec('foo', '1.0.0')]).create();

        await d.dir(appPath, [
          d.appPubspec(
            dependencies: {
              'foo': {'path': '../bar'},
            },
          ),
        ]).create();

        await pubGet();

        await createLockFile(appPath, dependenciesInSandBox: ['foo']);

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.yaml');

        await _implicitPubGet('The pubspec.yaml file has changed since the '
            'pubspec.lock file was generated');
      });

      test('the pubspec has an incompatible version of a dependency', () async {
        await d.dir(appPath, [
          d.appPubspec(dependencies: {'foo': '1.0.0'}),
        ]).create();

        await pubGet();

        await d.dir(appPath, [
          d.appPubspec(dependencies: {'foo': '2.0.0'}),
        ]).create();

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.yaml');

        await _implicitPubGet('The pubspec.yaml file has changed since the '
            'pubspec.lock file was generated');
      });

      test(
          'the lockfile is pointing to an unavailable package with a newer '
          'pubspec', () async {
        await d.dir(appPath, [
          d.appPubspec(dependencies: {'foo': '1.0.0'}),
        ]).create();

        await pubGet();

        deleteEntry(p.join(d.sandbox, cachePath));

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.yaml');

        await _implicitPubGet('`pubspec.yaml` is newer than `pubspec.lock`');
      });

      test('the package_config.json file points to the wrong place', () async {
        await d.dir('bar', [d.libPubspec('foo', '1.0.0')]).create();

        await d.dir(appPath, [
          d.appPubspec(
            dependencies: {
              'foo': {'path': '../bar'},
            },
          ),
        ]).create();

        await pubGet();

        await d.dir(appPath, [
          d.packageConfigFile([
            d.packageConfigEntry(
              name: 'foo',
              path: '../foo', // this is the wrong path
            ),
            d.packageConfigEntry(
              name: 'myapp',
              path: '.',
            ),
          ]),
        ]).create();

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.lock');

        await _implicitPubGet('Could not find `../foo/pubspec.yaml`');
      });

      test("the lock file's SDK constraint doesn't match the current SDK",
          () async {
        // Avoid using a path dependency because it triggers the full validation
        // logic. We want to be sure SDK-validation works without that logic.
        server.serve(
          'foo',
          '1.0.0',
          pubspec: {
            'environment': {'sdk': '>=3.0.0 <3.1.0'},
          },
        );

        await d.dir(appPath, [
          d.pubspec({
            'name': 'myapp',
            'environment': {'sdk': '^3.0.0'},
            'dependencies': {'foo': '^1.0.0'},
          }),
        ]).create();

        await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '3.0.0'});

        server.serve(
          'foo',
          '1.0.1',
          pubspec: {
            'environment': {'sdk': '^3.0.0'},
          },
        );

        await _implicitPubGet(
          'The Dart SDK was updated since last package resolution.',
        );
      });

      test(
          "the lock file's Flutter SDK constraint doesn't match the "
          'current Flutter SDK', () async {
        // Avoid using a path dependency because it triggers the full validation
        // logic. We want to be sure SDK-validation works without that logic.
        server.serve(
          'foo',
          '3.0.0',
          pubspec: {
            'environment': {
              'flutter': '>=1.0.0 <2.0.0',
              'sdk': defaultSdkConstraint,
            },
          },
        );

        await d.dir('flutter', [d.flutterVersion('1.2.3')]).create();

        await d.dir(appPath, [
          d.appPubspec(dependencies: {'foo': '^3.0.0'}),
        ]).create();

        await pubGet(
          environment: {'FLUTTER_ROOT': p.join(d.sandbox, 'flutter')},
        );
        await _noImplicitPubGet(
          environment: {'FLUTTER_ROOT': p.join(d.sandbox, 'flutter')},
        );
        await d.dir('flutter', [d.flutterVersion('0.9.0')]).create();

        server.serve(
          'foo',
          '3.0.1',
          pubspec: {
            'environment': {
              'flutter': '>=0.1.0 <2.0.0',
              'sdk': defaultSdkConstraint,
            },
          },
        );

        await _implicitPubGet(
          'Flutter has updated since last invocation.',
          environment: {'FLUTTER_ROOT': p.join(d.sandbox, 'flutter')},
        );
      });

      test("a path dependency's dependency doesn't match the lockfile",
          () async {
        await d.dir('bar', [
          d.libPubspec('bar', '1.0.0', deps: {'foo': '1.0.0'}),
        ]).create();

        await d.dir(appPath, [
          d.appPubspec(
            dependencies: {
              'bar': {'path': '../bar'},
            },
          ),
        ]).create();

        await pubGet();

        // Update bar's pubspec without touching the app's.
        await d.dir('bar', [
          d.libPubspec('bar', '1.0.0', deps: {'foo': '2.0.0'}),
        ]).create();

        // To ensure the timestamp is strictly later we need to touch again
        // here.
        await _touch(p.join(d.sandbox, 'bar', 'pubspec.yaml'));

        await _implicitPubGet('../bar/pubspec.yaml has changed '
            'since the pubspec.lock file was generated.');
      });

      test(
          "a path dependency's language version "
          "doesn't match the package_config.json", () async {
        await d.dir('bar', [
          d.libPubspec(
            'bar',
            '1.0.0',
            deps: {'foo': '1.0.0'},
            // Creates language version requirement 2.99
            sdk: '>= 2.99.0 <=4.0.0', // tests runs with '3.1.2+3'
          ),
        ]).create();

        await d.dir(appPath, [
          d.appPubspec(
            dependencies: {
              'bar': {'path': '../bar'},
            },
          ),
        ]).create();

        await pubGet();

        // Update bar's pubspec without touching the app's.
        await d.dir('bar', [
          d.libPubspec(
            'bar',
            '1.0.0',
            deps: {'foo': '1.0.0'},
            // Creates language version requirement 2.100
            sdk: '>= 2.100.0 <=4.0.0', // tests runs with '3.1.2+3'
          ),
        ]).create();
        // To ensure the timestamp is strictly later we need to touch again
        // here.
        await _touch(p.join(d.sandbox, 'bar', 'pubspec.yaml'));

        await _implicitPubGet('../bar/pubspec.yaml has changed '
            'since the pubspec.lock file was generated.');
      });
    });

    group("doesn't require the user to run pub get first if", () {
      test(
          'the pubspec is older than the lockfile which is older than the '
          'package-config, even if the contents are wrong', () async {
        await d.dir(appPath, [
          d.appPubspec(dependencies: {'foo': '1.0.0'}),
        ]).create();
        // Ensure we get a new mtime (mtime is only reported with 1s precision)
        await _touch('pubspec.yaml');

        await _touch('pubspec.lock');
        await _touch('.dart_tool/package_config.json');

        await _noImplicitPubGet();
      });

      test("the pubspec is newer than the lockfile, but they're up-to-date",
          () async {
        await d.dir(appPath, [
          d.appPubspec(dependencies: {'foo': '1.0.0'}),
        ]).create();

        await pubGet();

        await _touch('pubspec.yaml');

        await _noImplicitPubGet();
      });

      // Regression test for #1416
      test('a path dependency has a dependency on the root package', () async {
        await d.dir('foo', [
          d.libPubspec('foo', '1.0.0', deps: {'myapp': 'any'}),
        ]).create();

        await d.dir(appPath, [
          d.appPubspec(
            dependencies: {
              'foo': {'path': '../foo'},
            },
          ),
        ]).create();

        await pubGet();

        await _touch('pubspec.lock');

        await _noImplicitPubGet();
      });

      test('has a path dependency, and nothing changed', () async {
        await d.dir('foo', [
          d.libPubspec(
            'foo',
            '1.0.0',
          ),
        ]).create();

        await d.dir(appPath, [
          d.appPubspec(
            dependencies: {
              'foo': {'path': '../foo'},
            },
          ),
        ]).create();

        await pubGet();
        // package_config.json should not be touched as nothing changed.
        final packageConfig = File(
          p.join(d.sandbox, appPath, '.dart_tool', 'package_config.json'),
        );
        final beforeStamp = packageConfig.statSync().modified;

        await _noImplicitPubGet();

        expect(packageConfig.statSync().modified, beforeStamp);
      });

      test(
          "the lockfile is newer than package_config.json, but it's up-to-date",
          () async {
        await d.dir(appPath, [
          d.appPubspec(dependencies: {'foo': '1.0.0'}),
        ]).create();

        await pubGet();

        await _touch('pubspec.lock');

        await _noImplicitPubGet();
      });

      test("an overridden dependency's SDK constraint is unmatched", () async {
        server.serve(
          'bar',
          '1.0.0',
          pubspec: {
            'environment': {'sdk': '0.0.0-fake'},
          },
        );

        await d.dir(appPath, [
          d.pubspec({
            'name': 'myapp',
            'dependency_overrides': {'bar': '1.0.0'},
          }),
        ]).create();

        await pubGet();

        await _touch('pubspec.lock');

        await _noImplicitPubGet();
      });
    });
  });
}

/// Runs every command that care about the world being up-to-date, and asserts
/// that it prints [message] as part of its silent output.
Future<void> _implicitPubGet(
  String message, {
  Map<String, String?>? environment,
}) async {
  final buffer = StringBuffer();
  await runEmbeddingToBuffer(
    ['pub', 'ensure-pubspec-resolved', '--verbose'],
    buffer,
    workingDirectory: d.path(appPath),
    environment: environment,
  );
  final output = buffer.toString();
  expect(output, contains('FINE: $message'));
  expect(output, contains('Resolving dependencies'));
}

/// Ensures that pub doesn't require "dart pub get" for the current package.
Future<void> _noImplicitPubGet({
  Map<String, String?>? environment,
}) async {
  final buffer = StringBuffer();
  await runEmbeddingToBuffer(
    ['pub', 'ensure-pubspec-resolved', '--verbose'],
    buffer,
    workingDirectory: d.path(appPath),
    environment: environment,
  );
  final output = buffer.toString();
  expect(output, contains('FINE: Package Config up to date.'));
  expect(output, isNot(contains('Resolving dependencies')));
  // If pub determines that everything is up-to-date, it should set the
  // mtimes to indicate that.
  final pubspecModified =
      File(p.join(d.sandbox, 'myapp/pubspec.yaml')).lastModifiedSync();
  final lockFileModified =
      File(p.join(d.sandbox, 'myapp/pubspec.lock')).lastModifiedSync();
  final packageConfigModified =
      File(p.join(d.sandbox, 'myapp/.dart_tool/package_config.json'))
          .lastModifiedSync();

  expect(!pubspecModified.isAfter(lockFileModified), isTrue);
  expect(!lockFileModified.isAfter(packageConfigModified), isTrue);
}

/// Schedules a non-semantic modification to [path].
Future _touch(String path) async {
  // Delay a bit to make sure the modification times are noticeably different.
  // 1s seems to be the finest granularity that dart:io reports.
  await Future<void>.delayed(const Duration(seconds: 1));

  path = p.join(d.sandbox, 'myapp', path);
  touch(path);
}
