// 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 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:github/github.dart';
import 'package:gql/language.dart' as lang;
import 'package:graphql/client.dart';
import 'package:http/http.dart' as http;
import 'package:meta/meta.dart';

import '../model/appengine/github_gold_status_update.dart';
import '../request_handling/api_request_handler.dart';
import '../request_handling/authentication.dart';
import '../request_handling/body.dart';
import '../request_handling/exceptions.dart';
import '../service/config.dart';
import '../service/datastore.dart';
import '../service/logging.dart';

@immutable
class PushGoldStatusToGithub extends ApiRequestHandler<Body> {
  PushGoldStatusToGithub(
    Config config,
    AuthenticationProvider authenticationProvider, {
    @visibleForTesting DatastoreServiceProvider? datastoreProvider,
    http.Client? goldClient,
    this.ingestionDelay = const Duration(seconds: 10),
  })  : datastoreProvider = datastoreProvider ?? DatastoreService.defaultProvider,
        goldClient = goldClient ?? http.Client(),
        super(config: config, authenticationProvider: authenticationProvider);

  final DatastoreServiceProvider datastoreProvider;
  final http.Client goldClient;
  final Duration ingestionDelay;

  @override
  Future<Body> get() async {
    final DatastoreService datastore = datastoreProvider(config.db);

    if (authContext!.clientContext.isDevelopmentEnvironment) {
      // Don't push gold status from the local dev server.
      return Body.empty;
    }

    await _sendStatusUpdates(datastore, Config.flutterSlug);
    await _sendStatusUpdates(datastore, Config.engineSlug);

    return Body.empty;
  }

  Future<void> _sendStatusUpdates(
    DatastoreService datastore,
    RepositorySlug slug,
  ) async {
    final GitHub gitHubClient = await config.createGitHubClient(slug: slug);
    final List<GithubGoldStatusUpdate> statusUpdates = <GithubGoldStatusUpdate>[];
    log.fine('Beginning Gold checks...');
    await for (PullRequest pr in gitHubClient.pullRequests.list(slug)) {
      assert(pr.number != null);
      // Get last known Gold status from datastore.
      final GithubGoldStatusUpdate lastUpdate = await datastore.queryLastGoldUpdate(slug, pr);
      CreateStatus statusRequest;

      log.fine('Last known Gold status for $slug#${pr.number} was with sha: '
          '${lastUpdate.head}, status: ${lastUpdate.status}, description: ${lastUpdate.description}');

      if (lastUpdate.status == GithubGoldStatusUpdate.statusCompleted && lastUpdate.head == pr.head!.sha) {
        log.fine('Completed status already reported for this commit.');
        // We have already seen this commit and it is completed or, this is not
        // a change staged to land on master, which we should ignore.
        continue;
      }

      final String defaultBranch = Config.defaultBranch(slug);
      if (pr.base!.ref != defaultBranch) {
        log.fine('This change is not staged to land on $defaultBranch, skipping.');
        // This is potentially a release branch, or another change not landing
        // on master, we don't need a Gold check.
        continue;
      }

      if (pr.draft!) {
        log.fine('This pull request is a draft.');
        // We don't want to query Gold while a PR is in a draft state, and we
        // don't want to needlessly hold a pending state either.
        // If a PR has been marked `draft` after the fact, and there has not
        // been a new commit, we cannot rescind a previously posted status, so
        // if it is already pending, we should make the contributor aware of
        // that fact.
        if (lastUpdate.status == GithubGoldStatusUpdate.statusRunning &&
            lastUpdate.head == pr.head!.sha &&
            !await _alreadyCommented(gitHubClient, pr, slug, config.flutterGoldDraftChange)) {
          await gitHubClient.issues
              .createComment(slug, pr.number!, config.flutterGoldDraftChange + config.flutterGoldAlertConstant(slug));
        }
        continue;
      }

      log.fine('Querying builds for pull request #${pr.number} with sha: ${lastUpdate.head}...');
      final GraphQLClient gitHubGraphQLClient = await config.createGitHubGraphQLClient();
      final List<String> incompleteChecks = <String>[];
      bool runsGoldenFileTests = false;
      final Map<String, dynamic> data = (await _queryGraphQL(
        gitHubGraphQLClient,
        slug,
        pr.number!,
      ))!;
      final Map<String, dynamic> prData = data['repository']['pullRequest'] as Map<String, dynamic>;
      final Map<String, dynamic> commit = prData['commits']['nodes'].single['commit'] as Map<String, dynamic>;
      List<Map<String, dynamic>>? checkRuns;
      if (commit['checkSuites']['nodes'] != null && (commit['checkSuites']['nodes'] as List<dynamic>).isNotEmpty) {
        checkRuns =
            (commit['checkSuites']['nodes']?.first['checkRuns']['nodes'] as List<dynamic>).cast<Map<String, dynamic>>();
      }
      checkRuns = checkRuns ?? <Map<String, dynamic>>[];
      log.fine('This PR has ${checkRuns.length} checks.');
      for (Map<String, dynamic> checkRun in checkRuns) {
        log.fine('Check run: $checkRun');
        final String name = checkRun['name'].toLowerCase() as String;
        if (name.contains('framework') || name.contains('web engine')) {
          runsGoldenFileTests = true;
        }
        if (checkRun['conclusion'] == null || checkRun['conclusion'].toUpperCase() != 'SUCCESS') {
          incompleteChecks.add(name);
        }
      }

      if (runsGoldenFileTests) {
        log.fine('This PR executes golden file tests.');
        // Check when this PR was last updated. Gold does not keep results after
        // >20 days. If a PR has gone stale, we should draw attention to it to be
        // updated or closed.
        final DateTime updatedAt = pr.updatedAt!.toUtc();
        final DateTime twentyDaysAgo = DateTime.now().toUtc().subtract(const Duration(days: 20));
        if (updatedAt.isBefore(twentyDaysAgo)) {
          log.fine('Stale PR, no gold status to report.');
          if (!await _alreadyCommented(gitHubClient, pr, slug, config.flutterGoldStalePR)) {
            log.fine('Notifying for stale PR.');
            await gitHubClient.issues
                .createComment(slug, pr.number!, config.flutterGoldStalePR + config.flutterGoldAlertConstant(slug));
          }
          continue;
        }

        if (incompleteChecks.isNotEmpty) {
          // If checks on an open PR are running or failing, the gold status
          // should just be pending. Any draft PRs are skipped
          // until marked ready for review.
          log.fine('Waiting for checks to be completed.');
          statusRequest =
              _createStatus(GithubGoldStatusUpdate.statusRunning, config.flutterGoldPending, slug, pr.number!);
        } else {
          // We do not want to query Gold on a draft PR.
          assert(!pr.draft!);
          // Get Gold status.
          final String goldStatus = await _getGoldStatus(slug, pr);
          statusRequest = _createStatus(
              goldStatus,
              goldStatus == GithubGoldStatusUpdate.statusRunning
                  ? config.flutterGoldChanges
                  : config.flutterGoldSuccess,
              slug,
              pr.number!);
          log.fine('New status for potential update: ${statusRequest.state}, ${statusRequest.description}');
          if (goldStatus == GithubGoldStatusUpdate.statusRunning &&
              !await _alreadyCommented(gitHubClient, pr, slug, config.flutterGoldCommentID(pr))) {
            log.fine('Notifying for triage.');
            await _commentAndApplyGoldLabels(gitHubClient, pr, slug);
          }
        }

        // Push updates if there is a status change (detected by unique description)
        // or this is a new commit.
        if (lastUpdate.description != statusRequest.description || lastUpdate.head != pr.head!.sha) {
          try {
            log.fine('Pushing status to GitHub: ${statusRequest.state}, ${statusRequest.description}');
            await gitHubClient.repositories.createStatus(slug, pr.head!.sha!, statusRequest);
            lastUpdate.status = statusRequest.state!;
            lastUpdate.head = pr.head!.sha;
            lastUpdate.updates = (lastUpdate.updates ?? 0) + 1;
            lastUpdate.description = statusRequest.description!;
            statusUpdates.add(lastUpdate);
          } catch (error) {
            log.severe('Failed to post status update to ${slug.fullName}#${pr.number}: $error');
          }
        }
      } else {
        log.fine('This PR does not execute golden file tests.');
      }
    }
    await datastore.insert(statusUpdates);
    log.fine('Committed all updates for $slug');
  }

  /// Returns a GitHub Status for the given state and description.
  CreateStatus _createStatus(String state, String description, RepositorySlug slug, int prNumber) {
    final CreateStatus statusUpdate = CreateStatus(state)
      ..targetUrl = _getTriageUrl(slug, prNumber)
      ..context = 'flutter-gold'
      ..description = description;
    return statusUpdate;
  }

  /// Used to check for any tryjob results from Flutter Gold associated with a
  /// pull request.
  Future<String> _getGoldStatus(RepositorySlug slug, PullRequest pr) async {
    // We wait for a few seconds in case tests _just_ finished and the tryjob
    // has not finished ingesting the results.
    await Future<void>.delayed(ingestionDelay);
    final Uri requestForTryjobStatus =
        Uri.parse('${_getGoldHost(slug)}/json/v1/changelist_summary/github/${pr.number}');
    try {
      log.fine('Querying Gold for image results...');
      final http.Response response = await goldClient.get(requestForTryjobStatus);
      if (response.statusCode != HttpStatus.ok) {
        throw HttpException(response.body);
      }

      final dynamic jsonResponseTriage = json.decode(response.body);
      if (jsonResponseTriage is! Map<String, dynamic>) {
        throw const FormatException('Skia gold changelist summary does not match expected format.');
      }
      final List<dynamic> patchsets = jsonResponseTriage['patchsets'] as List<dynamic>;
      int untriaged = 0;
      for (int i = 0; i < patchsets.length; i++) {
        final Map<String, dynamic> patchset = patchsets[i] as Map<String, dynamic>;
        if (patchset['patchset_id'] == pr.head!.sha) {
          untriaged = patchset['new_untriaged_images'] as int;
          break;
        }
      }

      if (untriaged == 0) {
        log.fine('There are no unexpected image results for #${pr.number} at sha '
            '${pr.head!.sha}.');

        return GithubGoldStatusUpdate.statusCompleted;
      } else {
        log.fine('Tryjob for #${pr.number} at sha ${pr.head!.sha} generated new '
            'images.');

        return GithubGoldStatusUpdate.statusRunning;
      }
    } on FormatException catch (e) {
      throw BadRequestException('Formatting error detected requesting '
          'tryjob status for pr #${pr.number} from Flutter Gold.\n'
          'response: $response\n'
          'error: $e');
    } catch (e) {
      throw BadRequestException('Error detected requesting tryjob status for pr '
          '#${pr.number} from Flutter Gold.\n'
          'error: $e');
    }
  }

  String _getTriageUrl(RepositorySlug slug, int number) {
    return '${_getGoldHost(slug)}/cl/github/$number';
  }

  String _getGoldHost(RepositorySlug slug) {
    if (slug == Config.flutterSlug) {
      return 'https://flutter-gold.skia.org';
    }

    if (slug == Config.engineSlug) {
      return 'https://flutter-engine-gold.skia.org';
    }

    throw Exception('Unknown slug: $slug');
  }

  /// Creates a comment on a given pull request identified to have golden file
  /// changes and applies the `will affect goldens` label.
  Future<void> _commentAndApplyGoldLabels(
    GitHub gitHubClient,
    PullRequest pr,
    RepositorySlug slug,
  ) async {
    String body;
    if (await _isFirstComment(gitHubClient, pr, slug)) {
      body = config.flutterGoldInitialAlert(_getTriageUrl(slug, pr.number!));
    } else {
      body = config.flutterGoldFollowUpAlert(_getTriageUrl(slug, pr.number!));
    }
    body += config.flutterGoldAlertConstant(slug) + config.flutterGoldCommentID(pr);
    await gitHubClient.issues.createComment(slug, pr.number!, body);
    await gitHubClient.issues.addLabelsToIssue(slug, pr.number!, <String>[
      'will affect goldens',
    ]);
  }

  Future<bool> _alreadyCommented(
    GitHub gitHubClient,
    PullRequest pr,
    RepositorySlug slug,
    String message,
  ) async {
    final Stream<IssueComment> comments = gitHubClient.issues.listCommentsByIssue(slug, pr.number!);
    await for (IssueComment comment in comments) {
      if (comment.body!.contains(message)) {
        return true;
      }
    }
    return false;
  }

  Future<bool> _isFirstComment(
    GitHub gitHubClient,
    PullRequest pr,
    RepositorySlug slug,
  ) async {
    final Stream<IssueComment> comments = gitHubClient.issues.listCommentsByIssue(slug, pr.number!);
    await for (IssueComment comment in comments) {
      if (comment.body!.contains(config.flutterGoldInitialAlert(_getTriageUrl(slug, pr.number!)))) {
        return false;
      }
    }
    return true;
  }
}

Future<Map<String, dynamic>?> _queryGraphQL(
  GraphQLClient client,
  RepositorySlug slug,
  int prNumber,
) async {
  final QueryResult result = await client.query(
    QueryOptions(
      document: lang.parseString(pullRequestChecksQuery),
      fetchPolicy: FetchPolicy.noCache,
      variables: <String, dynamic>{
        'sPullRequest': prNumber,
        'sRepoOwner': slug.owner,
        'sRepoName': slug.name,
      },
    ),
  );

  if (result.hasException) {
    log.severe(result.exception.toString());
    throw const BadRequestException('GraphQL query failed');
  }
  return result.data;
}

const String pullRequestChecksQuery = r'''
query ChecksForPullRequest($sPullRequest: Int!, $sRepoOwner: String!, $sRepoName: String!) {
  repository(owner: $sRepoOwner, name: $sRepoName) {
    pullRequest(number: $sPullRequest) {
      commits(last: 1) {
        nodes {
          commit {
            # (appId: 64368) == flutter-dashboard. We only care about
            # flutter-dashboard checks.

            checkSuites(last: 1, filterBy: {appId: 64368}) {
              nodes {
                checkRuns(first: 100) {
                  nodes {
                    name
                    status
                    conclusion
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}''';
