// Copyright 2019 The Flutter Authors. 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:convert';
import 'dart:io';

import 'package:appengine/appengine.dart';
import 'package:cocoon_service/src/foundation/providers.dart';
import 'package:cocoon_service/src/service/buildbucket.dart';
import 'package:cocoon_service/src/service/github_status_service.dart';
import 'package:cocoon_service/src/service/luci_build_service.dart';
import 'package:github/github.dart';
import 'package:googleapis/oauth2/v2.dart';
import 'package:http/http.dart' as http;
import 'package:meta/meta.dart';

import '../datastore/cocoon_config.dart';
import '../foundation/typedefs.dart';
import '../model/appengine/service_account_info.dart';
import '../model/luci/push_message.dart';
import '../request_handling/body.dart';
import '../request_handling/exceptions.dart';
import '../request_handling/request_handler.dart';

/// An endpoint for listening to LUCI status updates for scheduled builds.
///
/// The [ScheduleBuildRequest.notify] property is set to tell LUCI to use our
/// PubSub topic. LUCI then publishes updates about build status to that topic,
/// which we listen to on the github-updater subscription. When new messages
/// arrive, they are posted to this web service.
///
/// The PubSub subscription is set up here:
/// https://console.cloud.google.com/cloudpubsub/subscription/detail/github-updater?project=flutter-dashboard
///
/// This endpoing is responsible for updating GitHub with the status of
/// completed builds.
///
/// This currently uses the GitHub Status API, but could be refactored at some
/// point to use the Checks API, which may offer some more knobs to turn
/// on the GitHub page. In particular, it might offer a nice way to retry a
/// failed build - which right now would require removing and re-applying the
/// label, or pushing a new commit.
@immutable
class LuciStatusHandler extends RequestHandler<Body> {
  /// Creates an endpoint for listening to LUCI status updates.
  const LuciStatusHandler(
    Config config,
    this.buildBucketClient, {
    LoggingProvider loggingProvider,
  })  : assert(buildBucketClient != null),
        loggingProvider = loggingProvider ?? Providers.serviceScopeLogger,
        super(config: config);

  final BuildBucketClient buildBucketClient;
  final LoggingProvider loggingProvider;

  @override
  Future<Body> post() async {
    final ServiceAccountInfo serviceAccountInfo =
        await config.deviceLabServiceAccount;
    final LuciBuildService luciBuildService =
        LuciBuildService(config, buildBucketClient, serviceAccountInfo);
    final Logging log = loggingProvider();
    final GithubStatusService githubStatusService =
        GithubStatusService(config, luciBuildService);

    if (!await _authenticateRequest(request.headers)) {
      throw const Unauthorized();
    }
    final String requestString = await utf8.decodeStream(request);
    final PushMessageEnvelope envelope = PushMessageEnvelope.fromJson(
      json.decode(requestString) as Map<String, dynamic>,
    );
    final BuildPushMessage buildPushMessage = BuildPushMessage.fromJson(
        json.decode(envelope.message.data) as Map<String, dynamic>);
    final Build build = buildPushMessage.build;
    final String builderName = build.tagsByName('builder').single;
    final RepositorySlug slug = await config.repoNameForBuilder(builderName);

    const String shaPrefix = 'sha/git/';
    log.debug('Available tags: ${build.tags.toString()}');
    // Skip status update if we can not get the sha tag.
    if (build.tagsByName('buildset').isEmpty) {
      log.warning('Buildset tag not included, skipping Status Updates');
      return Body.empty;
    }
    final String sha = build
        .tagsByName('buildset')
        .firstWhere((String tag) => tag.startsWith(shaPrefix))
        .substring(shaPrefix.length);
    log.debug('Setting status: ${buildPushMessage.toJson()} for $builderName');
    switch (buildPushMessage.build.status) {
      case Status.completed:
        await _markCompleted(
          sha: sha,
          builderName: builderName,
          build: build,
          githubStatusService: githubStatusService,
          slug: slug,
        );
        break;
      case Status.scheduled:
      case Status.started:
        final bool success = await githubStatusService.setPendingStatus(
          ref: sha,
          builderName: builderName,
          buildUrl: build.url,
          slug: slug,
        );
        if (!success) {
          log.warning('Failed to set status for $builderName');
        }
        break;
    }
    return Body.empty;
  }

  /// Updates the github status using the push_message [build] sent by LUCI
  /// as a pub/sub message.
  Future<void> _markCompleted({
    @required String sha,
    @required String builderName,
    @required Build build,
    @required GithubStatusService githubStatusService,
    @required RepositorySlug slug,
  }) async {
    assert(sha != null);
    assert(builderName != null);
    assert(build != null);
    await githubStatusService.setCompletedStatus(
      ref: sha,
      builderName: builderName,
      buildUrl: build.url,
      result: build.result,
      slug: slug,
    );
  }

  Future<bool> _authenticateRequest(HttpHeaders headers) async {
    final http.Client client = httpClient;
    final Oauth2Api oauth2api = Oauth2Api(client);
    final String idToken = headers.value(HttpHeaders.authorizationHeader);
    if (idToken == null || !idToken.startsWith('Bearer ')) {
      return false;
    }
    final Tokeninfo info = await oauth2api.tokeninfo(
      idToken: idToken.substring('Bearer '.length),
    );
    if (info.expiresIn == null || info.expiresIn < 1) {
      return false;
    }
    final ServiceAccountInfo devicelabServiceAccount =
        await config.deviceLabServiceAccount;
    return info.email == devicelabServiceAccount.email;
  }
}
