// Copyright 2020 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 'package:github/github.dart';
import 'package:meta/meta.dart';

import '../datastore/cocoon_config.dart';
import '../model/luci/buildbucket.dart' as bb;
import '../model/luci/push_message.dart';
import 'luci_build_service.dart';

/// Github status api pending state constant.
const String PENDING_STATE = 'pending';

class GithubStatusService {
  const GithubStatusService(this.config, this.luciBuildService);

  /// The global configuration of this AppEngine server.
  final Config config;
  final LuciBuildService luciBuildService;

  Future<void> setBuildsPendingStatus(
    int prNumber,
    String commitSha,
    RepositorySlug slug,
  ) async {
    final GitHub gitHubClient =
        await config.createGitHubClient(slug.owner, slug.name);
    final Map<String, bb.Build> builds = await luciBuildService
        .buildsForRepositoryAndPr(slug, prNumber, commitSha);
    final List<String> builderNames = config.luciTryBuilders
        .map((Map<String, dynamic> entry) => entry['name'] as String)
        .toList();
    for (bb.Build build in builds.values) {
      // LUCI configuration contain more builders than the ones we would like to run.
      // We need to ensure we are adding checks for the builders that will return a
      // status to prevent status blocking PRs forever.
      if (!builderNames.contains(build.builderId.builder)) {
        continue;
      }
      final CreateStatus status = CreateStatus(PENDING_STATE)
        ..context = build.builderId.builder
        ..description = 'Flutter LUCI Build: ${build.builderId.builder}'
        ..targetUrl = '';
      await gitHubClient.repositories.createStatus(slug, commitSha, status);
    }
  }

  Future<bool> setPendingStatus({
    @required String ref,
    @required String builderName,
    @required String buildUrl,
    @required RepositorySlug slug,
  }) async {
    // No builderName configuration, nothing to do here.
    if (await config.repoNameForBuilder(builderName) == null) {
      return false;
    }
    final GitHub gitHubClient =
        await config.createGitHubClient(slug.owner, slug.name);
    // GitHub "only" allows setting a status for a context/ref pair 1000 times.
    // We should avoid unnecessarily setting a pending status, e.g. if we get
    // started and pending messages close together.
    // We have to check for both because sometimes one or the other might come
    // in.
    // However, we should keep going if the _most recent_ status is not pending.
    await for (RepositoryStatus status
        in gitHubClient.repositories.listStatuses(slug, ref)) {
      if (status.context == builderName) {
        if (status.state == PENDING_STATE &&
            status.targetUrl.startsWith(buildUrl)) {
          return false;
        }
        break;
      }
    }

    String updatedBuildUrl = '';
    if (buildUrl.isNotEmpty) {
      // If buildUrl is not empty then append a query parameter to refresh the page
      // content every 30 seconds. A resulting updatedBuild url will look like:
      // https://ci.chromium.org/p/flutter/builders/try/Linux%20Web%20Engine/5275?reload=30
      updatedBuildUrl =
          '$buildUrl${buildUrl.contains('?') ? '&' : '?'}reload=30';
    }
    final CreateStatus status = CreateStatus(PENDING_STATE)
      ..context = builderName
      ..description = 'Flutter LUCI Build: $builderName'
      ..targetUrl = updatedBuildUrl;
    await gitHubClient.repositories.createStatus(slug, ref, status);
    return true;
  }

  Future<void> setCompletedStatus({
    @required String ref,
    @required String builderName,
    @required String buildUrl,
    @required Result result,
    @required RepositorySlug slug,
  }) async {
    final RepositorySlug slug = await config.repoNameForBuilder(builderName);
    // No builderName configuration, nothing to do here.
    if (slug == null) {
      return;
    }
    final GitHub gitHubClient =
        await config.createGitHubClient(slug.owner, slug.name);
    final CreateStatus status = statusForResult(result)
      ..context = builderName
      ..description = 'Flutter LUCI Build: $builderName'
      ..targetUrl = buildUrl;
    await gitHubClient.repositories.createStatus(slug, ref, status);
  }

  CreateStatus statusForResult(Result result) {
    switch (result) {
      case Result.canceled:
      case Result.failure:
        return CreateStatus('failure');
        break;
      case Result.success:
        return CreateStatus('success');
        break;
    }
    throw StateError('unreachable');
  }
}
