// Copyright (c) 2018, 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 'dart:io';

import 'package:http/http.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:pubspec_parse/pubspec_parse.dart';
import 'package:yaml/yaml.dart';

import 'util.dart';
import 'version.dart';

class PackageException implements Exception {
  final List<PackageExceptionDetails> details;

  final String? unsupportedArgument;

  PackageException(this.details, {this.unsupportedArgument});
}

class PackageExceptionDetails {
  final String error;
  final String? description;
  final bool _missingDependency;

  const PackageExceptionDetails._(this.error,
      {this.description, bool missingDependency = false})
      : _missingDependency = missingDependency;

  static const noPubspecLock =
      PackageExceptionDetails._('`pubspec.lock` does not exist.',
          description: 'Run `$appName` in a Dart package directory. '
              'Run `dart pub get` first.',
          missingDependency: true);

  static PackageExceptionDetails missingDep(
          String pkgName, VersionConstraint constraint) =>
      PackageExceptionDetails._(
          'You must have a dependency on `$pkgName` in `pubspec.yaml`.',
          description: '''
# pubspec.yaml
dev_dependencies:
  $pkgName: $constraint''',
          missingDependency: true);

  @override
  String toString() => [error, description].join('\n');
}

Future _runPubDeps() async {
  var result = Process.runSync(dartPath, ['pub', 'deps']);

  if (result.exitCode == 65 || result.exitCode == 66) {
    throw PackageException(
        [PackageExceptionDetails._((result.stderr as String).trim())]);
  }

  if (result.exitCode != 0) {
    throw ProcessException(
        dartPath,
        ['pub', 'deps'],
        '***OUT***\n${result.stdout}\n***ERR***\n${result.stderr}\n***',
        exitCode);
  }
}

class PubspecLock {
  final YamlMap? _packages;

  PubspecLock(this._packages);

  static Future<PubspecLock> read() async {
    await _runPubDeps();

    var pubspecLock =
        loadYaml(await File('pubspec.lock').readAsString()) as YamlMap;

    var packages = pubspecLock['packages'] as YamlMap?;
    return PubspecLock(packages);
  }

  List<PackageExceptionDetails> checkPackage(
      String pkgName, VersionConstraint constraint,
      {String? forArgument, bool requireDirect = true}) {
    var issues = <PackageExceptionDetails>[];
    var missingDetails =
        PackageExceptionDetails.missingDep(pkgName, constraint);

    var pkgDataMap =
        (_packages == null) ? null : _packages![pkgName] as YamlMap?;
    if (pkgDataMap == null) {
      issues.add(missingDetails);
    } else {
      var dependency = pkgDataMap['dependency'] as String?;
      if (requireDirect &&
          dependency != null &&
          !dependency.startsWith('direct ')) {
        issues.add(missingDetails);
      }

      var source = pkgDataMap['source'] as String?;
      if (source == 'hosted') {
        // NOTE: pkgDataMap['description'] should be:
        //           `{url: https://pub.dartlang.org, name: [pkgName]}`
        //       If a user is playing around here, they are on their own.

        var version = pkgDataMap['version'] as String;
        var pkgVersion = Version.parse(version);
        if (!constraint.allows(pkgVersion)) {
          var error = 'The `$pkgName` version – $pkgVersion – is not '
              'within the allowed constraint – $constraint.';
          issues.add(PackageExceptionDetails._(error));
        }
      } else {
        // NOTE: Intentionally not checking non-hosted dependencies: git, path
        //       If a user is playing around here, they are on their own.
      }
    }
    return issues;
  }
}

Future<List<PackageExceptionDetails>> _validateBuildDaemonVersion(
    PubspecLock pubspecLock) async {
  var buildDaemonConstraint = '>=2.0.0 <4.0.0';

  var issues = <PackageExceptionDetails>[];

  var buildDaemonIssues = pubspecLock.checkPackage(
    'build_daemon',
    VersionConstraint.parse(buildDaemonConstraint),
    requireDirect: false,
  );

  // Only warn of build_daemon issues if they have a dependency on the package.
  if (buildDaemonIssues.any((issue) => !issue._missingDependency)) {
    var info = await _latestPackageInfo();
    var issuePreamble =
        'This version of webdev does not support the `build_daemon` '
        'protocol used by your version of `build_runner`.';
    // Check if the newer version supports the `build_daemon` transitive version
    // used by their application.
    if (info.isNewer &&
        pubspecLock
            .checkPackage('build_daemon', info.buildDaemonConstraint,
                requireDirect: false)
            .isEmpty) {
      issues.add(PackageExceptionDetails._('$issuePreamble\n'
          'A newer version of webdev is available which supports '
          'your version of the `build_daemon`. Please update.'));
    } else {
      issues.add(PackageExceptionDetails._('$issuePreamble\n'
          'Please add a dev dependency on `build_daemon` with constraint: '
          '$buildDaemonConstraint'));
    }
  }
  return issues;
}

final buildRunnerConstraint = VersionConstraint.parse('>=1.6.2 <3.0.0');
final buildWebCompilersConstraint = VersionConstraint.parse('>=2.12.0 <4.0.0');

// Note the minimum versions should never be dev versions as users will not
// get them by default.
Future<void> checkPubspecLock(PubspecLock pubspecLock,
    {required bool requireBuildWebCompilers}) async {
  var issues = <PackageExceptionDetails>[];

  var buildRunnerIssues =
      pubspecLock.checkPackage('build_runner', buildRunnerConstraint);

  issues.addAll(buildRunnerIssues);

  if (requireBuildWebCompilers) {
    issues.addAll(pubspecLock.checkPackage(
        'build_web_compilers', buildWebCompilersConstraint));
  }

  if (buildRunnerIssues.isEmpty) {
    issues.addAll(await _validateBuildDaemonVersion(pubspecLock));
  }

  if (issues.isNotEmpty) {
    throw PackageException(issues);
  }
}

class _PackageInfo {
  final Version? version;
  final VersionConstraint buildDaemonConstraint;
  final bool isNewer;
  _PackageInfo(this.version, this.buildDaemonConstraint, this.isNewer);
}

/// Returns the package info for the latest webdev release.
Future<_PackageInfo> _latestPackageInfo() async {
  var response = await get(
      Uri.parse('https://pub.dartlang.org/api/packages/webdev'),
      headers: {HttpHeaders.userAgentHeader: 'webdev $packageVersion'});
  var responseObj = json.decode(response.body);
  var pubspec = Pubspec.fromJson(
      responseObj['latest']['pubspec'] as Map<String, dynamic>);
  var buildDaemonDependency = pubspec.dependencies['build_daemon'];
  // This should never be satisfied.
  var buildDaemonConstraint = VersionConstraint.parse('0.0.0');
  if (buildDaemonDependency is HostedDependency) {
    buildDaemonConstraint = buildDaemonDependency.version;
  }
  var currentVersion = Version.parse(packageVersion);
  var pubspecVersion = pubspec.version;
  var isNewer = (pubspecVersion == null)
      ? true
      : currentVersion.compareTo(pubspecVersion) < 0;
  return _PackageInfo(pubspec.version, buildDaemonConstraint, isNewer);
}
