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

import 'package:crypto/crypto.dart';
import 'package:path/path.dart' as p;
import 'package:pub/src/crc32c.dart';
import 'package:pub/src/source/hosted.dart';
import 'package:pub/src/utils.dart' show hexEncode;
import 'package:pub_semver/pub_semver.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:test/test.dart';
import 'package:test/test.dart' as test show expect;

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

class PackageServer {
  /// The inner [IOServer] that this uses to serve its descriptors.
  final shelf_io.IOServer _inner;

  /// Handlers of requests. Last matching handler will be used.
  final List<_PatternAndHandler> _handlers = [];

  // A list of all the requests received up till now.
  final List<String> requestedPaths = <String>[];

  // Setting this to false will disable automatic calculation of content-hashes.
  bool serveContentHashes = true;

  /// Whether the [IOServer] should compress the content, if possible.
  /// The default value is `false` (compression disabled).
  /// See [HttpServer.autoCompress] for details.
  bool get autoCompress => _inner.server.autoCompress;
  set autoCompress(bool shouldAutoCompress) =>
      _inner.server.autoCompress = shouldAutoCompress;

  // Setting this to false will disable automatic calculation of checksums.
  bool serveChecksums = true;

  PackageServer._(this._inner) {
    final outerZone = Zone.current;
    _inner.mount((request) {
      try {
        final path = request.url.path;
        requestedPaths.add(path);
        final pathWithInitialSlash = '/$path';
        for (final entry in _handlers.reversed) {
          final match = entry.pattern.matchAsPrefix(pathWithInitialSlash);
          if (match != null && match.end == pathWithInitialSlash.length) {
            final a = entry.handler(request);
            return a;
          }
        }
        return shelf.Response.notFound('Could not find ${request.url}');
      } catch (e, st) {
        // Because shelf swallows all errors we catch here and redirect to the
        // zone error handler.
        outerZone.handleUncaughtError(e, st);
        _inner.close();
        rethrow;
      }
    });
  }

  static final _versionInfoPattern = RegExp(r'/api/packages/([a-zA-Z_0-9]*)');
  static final _advisoriesPattern =
      RegExp(r'/api/packages/([a-zA-Z_0-9]*)/advisories');

  static final _downloadPattern =
      RegExp(r'/packages/([^/]*)/versions/([^/]*).tar.gz');

  static Future<PackageServer> start() async {
    final server = PackageServer._(
      await shelf_io.IOServer.bind(InternetAddress.loopbackIPv4, 0),
    );
    server.handle(
      _versionInfoPattern,
      (shelf.Request request) async {
        final parts = request.url.pathSegments;
        assert(parts[0] == 'api');
        assert(parts[1] == 'packages');
        final name = parts[2];

        final package = server._packages[name];
        if (package == null) {
          return shelf.Response.notFound('No package named $name');
        }

        return shelf.Response.ok(
          jsonEncode({
            'name': name,
            'uploaders': ['nweiz@google.com'],
            'versions': [
              for (final version in package.versions.values)
                {
                  'pubspec': version.pubspec,
                  'version': version.version.toString(),
                  'archive_url':
                      '${server.url}/packages/$name/versions/${version.version}.tar.gz',
                  if (version.isRetracted) 'retracted': true,
                  if (version.sha256 != null || server.serveContentHashes)
                    'archive_sha256': version.sha256 ??
                        hexEncode(
                          (await sha256.bind(version.contents()).first).bytes,
                        ),
                },
            ],
            if (package.isDiscontinued) 'isDiscontinued': true,
            if (package.advisoriesUpdated != null)
              'advisoriesUpdated': package.advisoriesUpdated!.toIso8601String(),
            if (package.discontinuedReplacementText != null)
              'replacedBy': package.discontinuedReplacementText,
          }),
          headers: {
            HttpHeaders.contentTypeHeader: 'application/vnd.pub.v2+json',
          },
        );
      },
    );

    server.handle(
      _advisoriesPattern,
      (shelf.Request request) async {
        final parts = request.url.pathSegments;
        assert(parts[0] == 'api');
        assert(parts[1] == 'packages');
        final name = parts[2];
        assert(parts[3] == 'advisories');

        final package = server._packages[name];
        if (package == null) {
          return shelf.Response.notFound('No package named $name');
        }

        return shelf.Response.ok(
          jsonEncode({
            'advisoriesUpdated': defaultAdvisoriesUpdated.toIso8601String(),
            'advisories': [
              for (final advisory in package.advisories.values)
                {
                  'id': advisory.id,
                  'summary': 'Example',
                  'aliases': [...advisory.aliases],
                  'details': 'This is a dummy example.',
                  'modified': defaultAdvisoriesUpdated.toIso8601String(),
                  'published': defaultAdvisoriesUpdated.toIso8601String(),
                  'affected': [
                    for (final package in advisory.affectedPackages)
                      {
                        'package': {
                          'name': package.name,
                          'ecosystem': package.ecosystem,
                        },
                        'versions': [...package.versions],
                      },
                  ],
                  if (advisory.displayUrl != null)
                    'database_specific': {
                      'pub_display_url': advisory.displayUrl,
                    },
                },
            ],
          }),
          headers: {
            HttpHeaders.contentTypeHeader: 'application/vnd.pub.v2+json',
          },
        );
      },
    );

    server.handle(
      _downloadPattern,
      (shelf.Request request) async {
        final parts = request.url.pathSegments;
        assert(parts[0] == 'packages');
        final name = parts[1];
        assert(parts[2] == 'versions');
        final package = server._packages[name];
        if (package == null) {
          return shelf.Response.notFound('No package $name');
        }

        final version = Version.parse(
          parts[3].substring(0, parts[3].length - '.tar.gz'.length),
        );
        assert(parts[3].endsWith('.tar.gz'));

        for (final packageVersion in package.versions.values) {
          if (packageVersion.version == version) {
            final headers = packageVersion.headers ?? {};
            headers[HttpHeaders.contentTypeHeader] ??= [
              'application/octet-stream',
            ];

            // This gate enables tests to validate the CRC32C parser by
            // passing in arbitrary values for the checksum header.
            if (server.serveChecksums &&
                !headers.containsKey(checksumHeaderName)) {
              headers[checksumHeaderName] = composeChecksumHeader(
                crc32c: await packageVersion.computeArchiveCrc32c(),
              );
            }

            return shelf.Response.ok(
              packageVersion.contents(),
              headers: headers,
            );
          }
        }
        return shelf.Response.notFound('No version $version of $name');
      },
    );
    return server;
  }

  Future<void> close() async {
    await _inner.close();
  }

  /// The port used for the server.
  int get port => _inner.url.port;

  /// The URL for the server.
  String get url => _inner.url.toString();

  /// From now on report errors on any request.
  void serveErrors() => _handlers
    ..clear()
    ..add(
      _PatternAndHandler(
        RegExp('.*'),
        (request) {
          fail('The HTTP server received an unexpected request:\n'
              '${request.method} ${request.requestedUri}');
        },
      ),
    );

  void handle(Pattern pattern, shelf.Handler handler) {
    _handlers.add(
      _PatternAndHandler(
        pattern,
        handler,
      ),
    );
  }

  // Installs a handler at [pattern] that expects to be called exactly once with
  // the given [method].
  //
  // The handler is installed as the start to give it priority over more general
  // handlers.
  void expect(String method, Pattern pattern, shelf.Handler handler) {
    handle(
      pattern,
      expectAsync1(
        (request) {
          test.expect(request.method, method);
          return handler(request);
        },
      ),
    );
  }

  /// Returns the path of [package] at [version], installed from this server, in
  /// the pub cache.
  String pathInCache(String package, String version) =>
      p.join(cachingPath, '$package-$version');

  /// The location where pub will store the cache for this server.
  String get cachingPath =>
      p.join(d.sandbox, cachePath, 'hosted', 'localhost%58$port');

  String get hashesCachingPath =>
      p.join(d.sandbox, cachePath, 'hosted-hashes', 'localhost%58$port');

  /// A map from package names to the concrete packages to serve.
  final _packages = <String, _ServedPackage>{};

  /// Specifies that a package named [name] with [version] should be served.
  ///
  /// If [deps] is passed, it's used as the "dependencies" field of the pubspec.
  /// If [pubspec] is passed, it's used as the rest of the pubspec.
  ///
  /// If [contents] is passed, it's used as the contents of the package. By
  /// default, a package just contains a dummy lib directory.
  void serve(
    String name,
    String version, {
    Map<String, dynamic>? deps,
    Map<String, dynamic>? pubspec,
    List<d.Descriptor>? contents,
    String? sdk,
    Map<String, List<String>>? headers,
  }) {
    final pubspecFields = <String, dynamic>{
      'name': name,
      'version': version,
      'environment': {'sdk': sdk ?? '^3.0.0'},
    };
    if (pubspec != null) pubspecFields.addAll(pubspec);
    if (deps != null) pubspecFields['dependencies'] = deps;

    contents ??= [d.libDir(name, '$name $version')];
    contents = [d.file('pubspec.yaml', yaml(pubspecFields)), ...contents];

    final package = _packages.putIfAbsent(name, _ServedPackage.new);
    package.versions[version] = _ServedPackageVersion(
      pubspecFields,
      headers: headers,
      contents: () => tarFromDescriptors(contents ?? []),
    );
  }

  // Mark a package discontinued.
  void discontinue(
    String name, {
    bool isDiscontinued = true,
    String? replacementText,
  }) {
    _packages[name]!
      ..isDiscontinued = isDiscontinued
      ..discontinuedReplacementText = replacementText;
  }

  static final defaultAdvisoriesUpdated =
      DateTime.fromMicrosecondsSinceEpoch(0);

  /// Add a security advisory which affects [affectedVersions] versions of
  /// package [packageName].
  void addAdvisory({
    required String advisoryId,
    String? displayUrl,
    DateTime? advisoriesUpdated,
    List<String> aliases = const <String>[],
    required List<AffectedPackage> affectedPackages,
  }) {
    for (final package in affectedPackages) {
      _packages[package.name]!.advisoriesUpdated =
          advisoriesUpdated ?? defaultAdvisoriesUpdated;
      _packages[package.name]!.advisories.putIfAbsent(
            advisoryId,
            () => _ServedAdvisory(
              advisoryId,
              affectedPackages,
              aliases,
              displayUrl,
            ),
          );
    }
  }

  /// Clears all existing packages from this builder.
  void clearPackages() {
    _packages.clear();
  }

  void retractPackageVersion(String name, String version) {
    _packages[name]!.versions[version]!.isRetracted = true;
  }

  /// Useful for testing handling of a wrong hash.
  void overrideArchiveSha256(String name, String version, String sha256) {
    _packages[name]!.versions[version]!.sha256 = sha256;
  }

  Future<String> peekArchiveSha256(String name, String version) async {
    final v = _packages[name]!.versions[version]!;
    return v.sha256 ?? hexEncode((await sha256.bind(v.contents()).first).bytes);
  }

  Future<String?> peekArchiveChecksumHeader(String name, String version) async {
    final v = _packages[name]!.versions[version]!;

    // If the test configured an overriding header value.
    var checksumHeader = v.headers?[checksumHeaderName];

    // Otherwise, compute from package contents.
    if (serveChecksums) {
      checksumHeader ??=
          composeChecksumHeader(crc32c: await v.computeArchiveCrc32c());
    }

    return checksumHeader?.join(',');
  }

  static List<String> composeChecksumHeader({
    int? crc32c,
    String? md5 = '5f4dcc3b5aa765d61d8327deb882cf99',
  }) {
    final header = <String>[];

    if (crc32c != null) {
      final bytes = Uint8List(4)..buffer.asByteData().setUint32(0, crc32c);
      header.add('crc32c=${base64.encode(bytes)}');
    }

    if (md5 != null) {
      header.add('md5=${base64.encode(utf8.encode(md5))}');
    }

    return header;
  }
}

class _ServedPackage {
  final versions = <String, _ServedPackageVersion>{};
  bool isDiscontinued = false;
  String? discontinuedReplacementText;
  DateTime? advisoriesUpdated;
  final advisories = <String, _ServedAdvisory>{};
}

/// A package that's intended to be served.
class _ServedPackageVersion {
  final Map pubspec;
  final Stream<List<int>> Function() contents;
  final Map<String, List<String>>? headers;
  bool isRetracted = false;
  // Overrides the calculated sha256.
  String? sha256;

  Version get version => Version.parse(pubspec['version'] as String);

  _ServedPackageVersion(this.pubspec, {required this.contents, this.headers});

  Future<int> computeArchiveCrc32c() async {
    return await Crc32c.computeByConsumingStream(contents());
  }
}

class _ServedAdvisory {
  String id;
  List<String> aliases;
  String? displayUrl;
  List<AffectedPackage> affectedPackages;

  _ServedAdvisory(
    this.id,
    this.affectedPackages,
    this.aliases,
    this.displayUrl,
  );
}

class AffectedPackage {
  String name;
  String ecosystem;
  List<String> versions;

  AffectedPackage({
    required this.name,
    this.ecosystem = 'Pub',
    required this.versions,
  });
}

class _PatternAndHandler {
  Pattern pattern;
  shelf.Handler handler;

  _PatternAndHandler(this.pattern, this.handler);
}
