// Copyright (c) 2021, 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:analyzer/instrumentation/service.dart';
import 'package:http/http.dart' as http;
import 'package:meta/meta.dart';

/// A class for interacting with the Pub API.
///
/// https://github.com/dart-lang/pub/blob/master/doc/repository-spec-v2.md
///
/// Failed requests will automatically be retried.
class PubApi {
  static const packageNameListPath = '/api/package-name-completion-data';
  static const packageInfoPath = '/api/packages';

  /// Maximum number of retries if requests fail.
  static const maxFailedRequests = 5;

  /// Initial wait period between retries. Doubled for each failure (but restarts
  /// from this value for each new request).
  static int _failedRetryInitialDelaySeconds = 1;

  @visibleForTesting
  static set failedRetryInitialDelaySeconds(int value) {
    _failedRetryInitialDelaySeconds = value;
  }

  final InstrumentationService instrumentationService;
  final http.Client httpClient;
  final String _pubHostedUrl;
  final _headers = {
    'Accept': 'application/vnd.pub.v2+json',
    'Accept-Encoding': 'gzip',
    'User-Agent': 'Dart Analysis Server/${Platform.version.split(' ').first}'
        ' (+https://github.com/dart-lang/sdk)',
  };

  PubApi(this.instrumentationService, http.Client? httpClient,
      String? envPubHostedUrl)
      : httpClient =
            httpClient != null ? _NoCloseHttpClient(httpClient) : http.Client(),
        _pubHostedUrl = _validPubHostedUrl(envPubHostedUrl);

  /// Fetches a list of package names from the Pub API.
  ///
  /// Failed requests will be retried a number of times. If no successful response
  /// is received, will return null.
  Future<List<PubApiPackage>?> allPackages() async {
    final json = await _getJson('$_pubHostedUrl$packageNameListPath');
    if (json == null) {
      return null;
    }

    final packageNames = json['packages'];
    return packageNames is List
        ? packageNames.map((name) => PubApiPackage(name)).toList()
        : null;
  }

  void close() {
    httpClient.close();
  }

  /// Fetches package details from the Pub API.
  ///
  /// Failed requests will be retried a number of times. If no successful response
  /// is received, will return null.
  Future<PubApiPackageDetails?> packageInfo(String packageName) async {
    final json = await _getJson('$_pubHostedUrl$packageInfoPath/$packageName');
    if (json == null) {
      return null;
    }

    final latest = json['latest'] as Map<String, Object?>?;
    if (latest == null) {
      return null;
    }

    final pubspec = latest['pubspec'] as Map<String, Object?>?;
    final description =
        pubspec != null ? pubspec['description'] as String? : null;
    final version = latest['version'] as String?;
    return PubApiPackageDetails(packageName, description, version);
  }

  /// Calls a pub API and decodes the resulting JSON.
  ///
  /// Automatically retries the request for specific types of failures after
  /// [_failedRetryInitialDelaySeconds] doubling each time. After [maxFailedRequests]
  /// requests or upon a 4XX response, will return `null` and not retry.
  Future<Map<String, Object?>?> _getJson(String url) async {
    var requestCount = 0;
    var retryAfterSeconds = _failedRetryInitialDelaySeconds;
    while (requestCount++ < maxFailedRequests) {
      try {
        final response =
            await httpClient.get(Uri.parse(url), headers: _headers);
        if (response.statusCode == 200) {
          instrumentationService.logInfo('Pub API request successful for $url');
          return jsonDecode(response.body);
        } else if (response.statusCode >= 400 && response.statusCode < 500) {
          // Do not retry 4xx responses.
          instrumentationService.logError(
              'Pub API returned ${response.statusCode} ${response.reasonPhrase} '
              'for $url. Not retrying.');
          return null;
        }
        instrumentationService.logError(
            'Pub API returned ${response.statusCode} ${response.reasonPhrase} '
            'for $url on attempt $requestCount');
      } catch (e) {
        if (e is! IOException && e is! FormatException) {
          instrumentationService
              .logError('Error calling pub API for $url. Not retrying. $e');
          return null;
        }
        instrumentationService.logError('Error calling pub API for $url: $e');
      }
      if (requestCount >= maxFailedRequests) {
        instrumentationService
            .logInfo('Pub API request failed after $requestCount requests');
      } else {
        // Sleep before the next try.
        await Future.delayed(Duration(seconds: retryAfterSeconds));
        retryAfterSeconds *= 2;
      }
    }
    return null;
  }

  /// Returns a valid Pub base URL from [envPubHostedUrl] if valid, otherwise using
  /// the default 'https://pub.dartlang.org'.
  static String _validPubHostedUrl(String? envPubHostedUrl) {
    final validUrl = envPubHostedUrl != null &&
            (Uri.tryParse(envPubHostedUrl)?.isAbsolute ?? false)
        ? envPubHostedUrl
        : 'https://pub.dartlang.org';

    // Discard any trailing slashes, as all API paths start with them.
    return validUrl.endsWith('/')
        ? validUrl.substring(0, validUrl.length - 1)
        : validUrl;
  }
}

class PubApiPackage {
  final String packageName;

  PubApiPackage(this.packageName);
}

class PubApiPackageDetails {
  final String packageName;
  final String? description;
  final String? latestVersion;

  PubApiPackageDetails(this.packageName, this.description, this.latestVersion);
}

/// A wrapper over a package:http Client that does not pass on calls to [close].
///
/// This is used to prevent the server closing a client that may be provided to
/// it (while still allowing it to close any client it creates itself).
class _NoCloseHttpClient extends http.BaseClient {
  final http.Client client;

  _NoCloseHttpClient(this.client);

  @override
  Future<http.StreamedResponse> send(http.BaseRequest request) =>
      client.send(request);
}
