// 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:async';

import 'package:github/github.dart';
import 'package:meta/meta.dart';

import '../datastore/cocoon_config.dart';
import '../model/appengine/github_build_status_update.dart';
import '../model/appengine/task.dart';
import '../request_handling/api_request_handler.dart';
import '../request_handling/authentication.dart';
import '../request_handling/body.dart';
import '../service/datastore.dart';
import '../service/luci.dart';

@immutable
class PushEngineStatusToGithub extends ApiRequestHandler<Body> {
  const PushEngineStatusToGithub(
    Config config,
    AuthenticationProvider authenticationProvider, {
    @visibleForTesting LuciServiceProvider luciServiceProvider,
    @visibleForTesting DatastoreServiceProvider datastoreProvider,
  })  : luciServiceProvider = luciServiceProvider ?? _createLuciService,
        datastoreProvider =
            datastoreProvider ?? DatastoreService.defaultProvider,
        super(config: config, authenticationProvider: authenticationProvider);

  final LuciServiceProvider luciServiceProvider;
  final DatastoreServiceProvider datastoreProvider;

  static LuciService _createLuciService(ApiRequestHandler<dynamic> handler) {
    return LuciService(
      config: handler.config,
      clientContext: handler.authContext.clientContext,
    );
  }

  @override
  Future<Body> get() async {
    if (authContext.clientContext.isDevelopmentEnvironment) {
      // Don't push GitHub status from the local dev server.
      return Body.empty;
    }

    final LuciService luciService = luciServiceProvider(this);
    final Map<LuciBuilder, List<LuciTask>> luciTasks =
        await luciService.getRecentTasks(repo: 'engine');

    String latestStatus = GithubBuildStatusUpdate.statusSuccess;
    for (List<LuciTask> tasks in luciTasks.values) {
      latestStatus = _getLatestStatus(tasks);
      if (latestStatus == GithubBuildStatusUpdate.statusFailure) {
        break;
      }
    }

    final RepositorySlug slug = RepositorySlug('flutter', 'engine');
    final DatastoreService datastore = datastoreProvider(config.db);
    final GitHub github =
        await config.createGitHubClient(slug.owner, slug.name);
    final List<GithubBuildStatusUpdate> updates = <GithubBuildStatusUpdate>[];
    await for (PullRequest pr in github.pullRequests.list(slug)) {
      final GithubBuildStatusUpdate update =
          await datastore.queryLastStatusUpdate(slug, pr);

      if (update.status != latestStatus) {
        log.debug(
            'Updating status of ${slug.fullName}#${pr.number} from ${update.status}');
        final CreateStatus request = CreateStatus(latestStatus);
        request.targetUrl =
            'https://ci.chromium.org/p/flutter/g/engine/console';
        request.context = 'luci-engine';
        if (latestStatus != GithubBuildStatusUpdate.statusSuccess) {
          request.description =
              'Flutter build is currently broken. Please do not merge this '
              'PR unless it contains a fix to the broken build.';
        }

        try {
          await github.repositories.createStatus(slug, pr.head.sha, request);
          update.status = latestStatus;
          update.updates += 1;
          update.updateTimeMillis = DateTime.now().millisecondsSinceEpoch;
          updates.add(update);
        } catch (error) {
          log.error(
              'Failed to post status update to ${slug.fullName}#${pr.number}: $error');
        }
      }
    }
    await datastore.insert(updates);
    log.debug('Committed all updates');
    return Body.empty;
  }

  String _getLatestStatus(List<LuciTask> tasks) {
    for (LuciTask task in tasks) {
      switch (task.status) {
        case Task.statusFailed:
          return GithubBuildStatusUpdate.statusFailure;
        case Task.statusSucceeded:
          return GithubBuildStatusUpdate.statusSuccess;
      }
    }
    return GithubBuildStatusUpdate.statusSuccess;
  }
}
