// Copyright (c) 2013, 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:path/path.dart' as p;

import 'package:pub/src/exit_codes.dart';
import 'package:test/test.dart';

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

d.DirectoryDescriptor package({
  String version = '1.0.0',
  Map<String, Object?>? deps,
  String? sdk,
}) {
  return d.dir(appPath, [
    d.libPubspec(
      'test_pkg',
      version,
      sdk: sdk ?? defaultSdkConstraint,
      deps: deps,
    ),
    d.file('LICENSE', 'Eh, do what you want.'),
    d.file('README.md', "This package isn't real."),
    d.file('CHANGELOG.md', '# $version\nFirst version\n'),
    d.dir('lib', [d.file('test_pkg.dart', 'int i = 1;')]),
  ]);
}

Future<void> expectValidation({
  Object? message,
  int exitCode = 0,
  Map<String, String> environment = const {},
}) async {
  await runPub(
    output: message ?? contains('Package has 0 warnings.'),
    args: ['publish', '--dry-run'],
    // workingDirectory: d.path(appPath),
    exitCode: exitCode,
    environment: environment,
  );
}

Future<void> expectValidationWarning(
  Object? message, {
  int count = 1,
  Map<String, String> environment = const {},
}) async {
  if (message is String) message = contains(message);
  await expectValidation(
    message: allOf([message, contains('Package has $count warning')]),
    exitCode: DATA,
    environment: environment,
  );
}

Future<void> expectValidationError(
  String message, {
  Map<String, String> environment = const {},
}) async {
  await expectValidation(
    message: allOf([
      contains(message),
      contains('Package validation found the following error:'),
    ]),
    exitCode: DATA,
    environment: environment,
  );
}

Future<void> setUpDependency(
  Map<String, String> dep, {
  String? sdk,
  List<String> hostedVersions = const [],
}) async {
  final server = await servePackages();
  for (final version in hostedVersions) {
    server.serve('foo', version);
  }

  await package(deps: {'foo': dep}, sdk: sdk).create();
}

void main() {
  group('should consider a package valid if it', () {
    test('looks normal', () async {
      await package().create();
      await expectValidation();
    });

    test('with a dependency on a pre-release while being one', () async {
      (await servePackages()).serve('foo', '1.2.3-dev');
      await package(version: '1.0.0-dev', deps: {'foo': '^1.2.3-dev'}).create();
      await expectValidation();
    });

    test('has a git path dependency with an appropriate SDK constraint',
        () async {
      await servePackages();
      await d.git('foo', [
        d.dir('subdir', [d.libPubspec('foo', '1.0.0')]),
      ]).create();
      await package(
        deps: {
          'foo': {
            'git': {'url': '../foo', 'path': 'subdir'},
          },
        },
      ).create();

      // We should get a warning for using a git dependency, but not an error.
      await expectValidationWarning(
        allOf([
          contains('  foo: any'),
          contains("Publishable packages can't have 'git' dependencies"),
        ]),
        count: 2,
      );
    });

    test('depends on Flutter from an SDK source', () async {
      await d.dir('flutter', [d.flutterVersion('1.2.3')]).create();
      await flutterPackage('flutter').create();
      await package(
        deps: {
          'flutter': {'sdk': 'flutter'},
        },
      ).create();

      await expectValidation(
        environment: {'FLUTTER_ROOT': p.join(d.sandbox, 'flutter')},
      );
    });

    test(
      'depends on a package from Flutter '
      'with an appropriate Dart SDK constraint',
      () async {
        await d.dir('flutter', [d.flutterVersion('1.2.3')]).create();
        await flutterPackage('foo').create();
        await package(
          deps: {
            'foo': {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'},
          },
        ).create();

        await expectValidation(
          environment: {
            'FLUTTER_ROOT': p.join(d.sandbox, 'flutter'),
          },
        );
      },
    );

    test(
      'depends on a package from Fuchsia '
      'with an appropriate Dart SDK constraint',
      () async {
        await fuchsiaPackage('foo', sdk: '^3.0.0').create();
        await package(
          deps: {
            'foo': {'sdk': 'fuchsia', 'version': '>=1.2.3 <2.0.0'},
          },
        ).create();

        await expectValidation(
          environment: {
            'FUCHSIA_DART_SDK_ROOT': p.join(d.sandbox, 'fuchsia'),
          },
        );
      },
    );
  });

  group('should consider a package invalid if it', () {
    setUp(package().create);

    group('has a path dependency', () {
      group('where a hosted version exists', () {
        test('and should suggest the hosted primary version', () async {
          await d.dir('foo', [
            d.libPubspec('foo', '1.2.3'),
          ]).create();
          await setUpDependency(
            {'path': p.join(d.sandbox, 'foo')},
            hostedVersions: ['3.0.0-pre', '2.0.0', '1.0.0'],
          );
          await expectValidationError(
            '  foo: ^2.0.0',
          );
        });

        test(
            'and should suggest the hosted prerelease version '
            "if it's the only version available", () async {
          await d.dir('foo', [
            d.libPubspec('foo', '1.2.3'),
          ]).create();
          await setUpDependency(
            {'path': p.join(d.sandbox, 'foo')},
            hostedVersions: ['3.0.0-pre', '2.0.0-pre'],
          );
          await expectValidationError(
            '  foo: ^3.0.0-pre',
          );
        });

        test('and should suggest a tighter constraint if primary is pre-1.0.0',
            () async {
          await d.dir('foo', [
            d.libPubspec('foo', '1.2.3'),
          ]).create();
          await setUpDependency(
            {'path': p.join(d.sandbox, 'foo')},
            hostedVersions: ['0.0.1', '0.0.2'],
          );
          await expectValidationError(
            '  foo: ^0.0.2',
          );
        });
      });

      group('where no hosted version exists', () {
        test("and should use the other source's version", () async {
          await d.dir('foo', [
            d.libPubspec('foo', '1.2.3'),
          ]).create();
          await setUpDependency({
            'path': p.join(d.sandbox, 'foo'),
            'version': '>=1.0.0 <2.0.0',
          });
          await expectValidationError(
            '  foo: ">=1.0.0 <2.0.0"',
          );
        });

        test(
            "and should use the other source's unquoted version if "
            'concrete', () async {
          await d.dir('foo', [
            d.libPubspec('foo', '0.2.3'),
          ]).create();
          await setUpDependency(
            {'path': p.join(d.sandbox, 'foo'), 'version': '0.2.3'},
          );
          await expectValidationError(
            '  foo: 0.2.3',
          );
        });
      });
    });

    group('has an unconstrained dependency', () {
      group('with a lockfile', () {
        test('and it should suggest a constraint based on the locked version',
            () async {
          (await servePackages()).serve('foo', '1.2.3');
          await d.dir(appPath, [
            d.libPubspec('test_pkg', '1.0.0', deps: {'foo': 'any'}),
          ]).create();

          await expectValidationWarning('  foo: ^1.2.3');
        });

        test(
            'and it should suggest a concrete constraint '
            'if the locked version is pre-1.0.0', () async {
          (await servePackages()).serve('foo', '0.1.2');

          await d.dir(appPath, [
            d.libPubspec('test_pkg', '1.0.0', deps: {'foo': 'any'}),
            d.file(
              'pubspec.lock',
              jsonEncode({
                'packages': {
                  'foo': {
                    'version': '0.1.2',
                    'source': 'hosted',
                    'description': {'name': 'foo', 'url': 'https://pub.dev'},
                  },
                },
              }),
            ),
          ]).create();

          await expectValidationWarning('  foo: ^0.1.2');
        });
      });
    });

    test('with a dependency on a pre-release without being one', () async {
      (await servePackages()).serve('foo', '1.2.3-dev');

      await d.dir(appPath, [
        d.libPubspec(
          'test_pkg',
          '1.0.0',
          deps: {'foo': '^1.2.3-dev'},
        ),
      ]).create();

      await expectValidationWarning(
        'Packages dependent on a pre-release',
      );
    });
    test(
        'with a single-version dependency and it should suggest a '
        'constraint based on the version', () async {
      (await servePackages()).serve('foo', '1.2.3');
      await d.dir(appPath, [
        d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '1.2.3'}),
      ]).create();

      await expectValidationWarning('  foo: ^1.2.3');
    });

    group('has a dependency without a lower bound', () {
      test(
          'and it should suggest a constraint based on the locked '
          'version', () async {
        (await servePackages()).serve('foo', '1.2.3');

        await d.dir(appPath, [
          d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '<3.0.0'}),
          d.file(
            'pubspec.lock',
          ),
        ]).create();

        await expectValidationWarning('  foo: ">=1.2.3 <3.0.0"');
      });

      test('and it should preserve the upper-bound operator', () async {
        (await servePackages()).serve('foo', '1.2.3');
        await d.dir(appPath, [
          d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '<=3.0.0'}),
          d.file(
            'pubspec.lock',
            jsonEncode({
              'packages': {
                'foo': {
                  'version': '1.2.3',
                  'source': 'hosted',
                  'description': {'name': 'foo', 'url': 'https://pub.dev'},
                },
              },
            }),
          ),
        ]).create();

        await expectValidationWarning('  foo: ">=1.2.3 <=3.0.0"');
      });

      test(
          'and it should expand the suggested constraint if the '
          'locked version matches the upper bound', () async {
        (await servePackages()).serve('foo', '1.2.3');

        await d.dir(appPath, [
          d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '<=1.2.3'}),
          d.file(
            'pubspec.lock',
            jsonEncode({
              'packages': {
                'foo': {
                  'version': '1.2.3',
                  'source': 'hosted',
                  'description': {'name': 'foo', 'url': 'https://pub.dev'},
                },
              },
            }),
          ),
        ]).create();

        await expectValidationWarning('  foo: ^1.2.3');
      });
    });

    group('with a dependency without an upper bound', () {
      test('and it should suggest a constraint based on the lower bound',
          () async {
        (await servePackages()).serve('foo', '1.2.3');
        await d.dir(appPath, [
          d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '>=1.2.3'}),
        ]).create();

        await expectValidationWarning('  foo: ^1.2.3');
      });

      test('and it should preserve the lower-bound operator', () async {
        (await servePackages()).serve('foo', '1.2.4');
        await d.dir(appPath, [
          d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '>1.2.3'}),
        ]).create();

        await expectValidationWarning('  foo: ">1.2.3 <2.0.0"');
      });
    });
  });
}

d.Descriptor fuchsiaPackage(
  String name, {
  Map<String, String> deps = const {},
  String? sdk,
}) {
  return d.dir('fuchsia', [
    d.dir('packages', [
      d.dir(name, [
        d.libDir(name, 'f(x) => 2 * x;'),
        d.libPubspec(name, '1.5.0', deps: deps, sdk: sdk),
      ]),
    ]),
  ]);
}

d.Descriptor flutterPackage(
  String name, {
  Map<String, String> deps = const {},
}) {
  return d.dir('flutter', [
    d.dir('packages', [
      d.dir(name, [
        d.libDir(name, 'f(x) => 2 * x;'),
        d.libPubspec(name, '1.5.0', deps: deps),
      ]),
    ]),
  ]);
}
