// Copyright 2022 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.

// ignore_for_file: constant_identifier_names
import 'dart:async';
import 'dart:convert';
import 'package:auto_submit/service/config.dart';

import 'package:auto_submit/requests/check_pull_request.dart';
import 'package:auto_submit/requests/check_pull_request_queries.dart';
import 'package:auto_submit/service/log.dart';
import 'package:github/github.dart';
import 'package:googleapis/bigquery/v2.dart';
import 'package:googleapis/pubsub/v1.dart' as pub;
import 'package:graphql/client.dart' hide Request, Response;
import 'package:logging/logging.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';

import '../service/bigquery_test.dart';
import '../src/service/fake_bigquery_service.dart';
import './github_webhook_test_data.dart';
import '../src/request_handling/fake_pubsub.dart';
import '../src/request_handling/fake_authentication.dart';
import '../src/service/fake_config.dart';
import '../src/service/fake_github_service.dart';
import '../src/service/fake_graphql_client.dart';
import '../utilities/mocks.dart';
import '../utilities/utils.dart' hide createQueryResult;

const String oid = '6dcb09b5b57875f334f61aebed695e2e4193db5e';
const String title = 'some_title';

void main() {
  group('Check CheckPullRequest', () {
    late CheckPullRequest checkPullRequest;
    late FakeConfig config;
    late FakeCronAuthProvider auth;
    late FakeGraphQLClient githubGraphQLClient;
    final FakeGithubService githubService = FakeGithubService();
    late MockJobsResource jobsResource;
    late FakeBigqueryService bigqueryService;
    late MockPullRequestsService pullRequests;
    final MockGitHub gitHub = MockGitHub();
    late FakePubSub pubsub;
    late PullRequestHelper flutterRequest;
    late PullRequestHelper cocoonRequest;
    late List<QueryOptions> expectedOptions;
    late QueryOptions flutterOption;
    late QueryOptions cocoonOption;
    const String testTopic = 'test-topic';
    const String rollorAuthor = "engine-flutter-autoroll";
    const String labelName = "warning: land on red to fix tree breakage";
    const String cocoonRepo = 'cocoon';
    const String noAutosubmitLabel = 'no_autosubmit';

    setUp(() {
      githubGraphQLClient = FakeGraphQLClient();
      auth = FakeCronAuthProvider();
      pubsub = FakePubSub();
      expectedOptions = <QueryOptions>[];

      githubGraphQLClient.mutateResultForOptions = (MutationOptions options) => createFakeQueryResult();

      githubGraphQLClient.queryResultForOptions = (QueryOptions options) {
        expect(options.variables['sOwner'], 'flutter');
        final String? repoName = options.variables['sName'] as String?;
        if (repoName == 'flutter') {
          return createQueryResult(flutterRequest);
        } else if (repoName == 'cocoon') {
          return createQueryResult(cocoonRequest);
        } else {
          fail('unexpected repo $repoName');
        }
      };

      flutterOption = QueryOptions(
        document: pullRequestWithReviewsQuery,
        fetchPolicy: FetchPolicy.noCache,
        variables: const <String, dynamic>{
          'sOwner': 'flutter',
          'sName': 'flutter',
          'sPrNumber': 0,
        },
      );
      cocoonOption = QueryOptions(
        document: pullRequestWithReviewsQuery,
        fetchPolicy: FetchPolicy.noCache,
        variables: const <String, dynamic>{
          'sOwner': 'flutter',
          'sName': 'cocoon',
          'sPrNumber': 1,
        },
      );

      githubService.checkRunsData = checkRunsMock;
      githubService.compareTwoCommitsData = compareTwoCommitsMock;
      githubService.successMergeData = successMergeMock;
      githubService.createCommentData = createCommentMock;
      githubService.commitData = commitMock;
      jobsResource = MockJobsResource();
      bigqueryService = FakeBigqueryService(jobsResource);
      config = FakeConfig(githubService: githubService, githubGraphQLClient: githubGraphQLClient, githubClient: gitHub);
      config.bigqueryService = bigqueryService;
      pullRequests = MockPullRequestsService();
      when(gitHub.pullRequests).thenReturn(pullRequests);
      when(pullRequests.get(any, any)).thenAnswer((_) async => PullRequest(number: 123, state: 'open'));

      when(jobsResource.query(captureAny, any)).thenAnswer((Invocation invocation) {
        return Future<QueryResponse>.value(
          QueryResponse.fromJson(jsonDecode(insertDeleteSuccessResponse) as Map<dynamic, dynamic>),
        );
      });
    });

    void verifyQueries(List<QueryOptions> expectedOptions) {
      githubGraphQLClient.verifyQueries(expectedOptions);
    }

    test('Multiple identical messages are processed once', () async {
      final PullRequest pullRequest1 = generatePullRequest(prNumber: 0, repoName: cocoonRepo);
      githubService.pullRequestData = pullRequest1;
      for (int i = 0; i < 2; i++) {
        unawaited(pubsub.publish('auto-submit-queue-sub', pullRequest1));
      }

      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);
      cocoonRequest = PullRequestHelper(prNumber: 0, lastCommitHash: oid);
      await checkPullRequest.get();

      githubGraphQLClient.verifyMutations(
        <MutationOptions>[
          MutationOptions(
            document: mergePullRequestMutation,
            variables: getMergePullRequestVariables(pullRequest1.number!.toString(), pullRequest1.number!.toString()),
          ),
        ],
      );
      expect(0, pubsub.messagesQueue.length);
    });

    test('Closed PRs are not processed', () async {
      final PullRequest pullRequest1 = generatePullRequest(prNumber: 0, repoName: cocoonRepo, state: 'close');
      githubService.pullRequestData = pullRequest1;
      when(pullRequests.get(any, any)).thenAnswer((_) async => PullRequest(number: 0, state: 'close'));
      for (int i = 0; i < 2; i++) {
        unawaited(pubsub.publish('auto-submit-queue-sub', pullRequest1));
      }

      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);
      cocoonRequest = PullRequestHelper(prNumber: 0, lastCommitHash: oid);
      await checkPullRequest.get();

      githubGraphQLClient.verifyMutations(
        <MutationOptions>[],
      );
      expect(0, pubsub.messagesQueue.length);
    });

    test('Merge exception is handled correctly', () async {
      final PullRequest pullRequest1 = generatePullRequest(prNumber: 0);
      final PullRequest pullRequest2 = generatePullRequest(prNumber: 1, repoName: cocoonRepo);
      githubService.pullRequestData = pullRequest1;
      int errorIndex = 0;
      final List<PullRequest> pullRequests = <PullRequest>[pullRequest1, pullRequest2];
      for (PullRequest pr in pullRequests) {
        unawaited(pubsub.publish(testTopic, pr));
      }

      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);
      flutterRequest = PullRequestHelper(
        prNumber: 0,
        lastCommitHash: oid,
      );
      cocoonRequest = PullRequestHelper(prNumber: 1, lastCommitHash: oid);
      githubGraphQLClient.mutateResultForOptions = (_) {
        if (errorIndex == 0) {
          errorIndex++;
          throw const GraphQLError(message: 'error');
        }
        return createQueryResult(cocoonRequest);
      };
      final List<LogRecord> records = <LogRecord>[];
      log.onRecord.listen((LogRecord record) => records.add(record));
      // this is the test.
      await checkPullRequest.get();
      // every failure is now acknowledged from the queue.
      expect(pubsub.messagesQueue.length, 0);
      final List<LogRecord> errorLogs = records.where((LogRecord record) => record.level == Level.SEVERE).toList();
      expect(errorLogs.length, 1);
      expect(errorLogs[0].message.contains('Failed to merge'), true);
      pubsub.messagesQueue.clear();
    });

    test('Merges PR with successful status and checks', () async {
      final PullRequest pullRequest1 = generatePullRequest(prNumber: 0);
      final PullRequest pullRequest2 = generatePullRequest(prNumber: 1, repoName: cocoonRepo);
      githubService.pullRequestData = pullRequest1;

      final List<PullRequest> pullRequests = <PullRequest>[pullRequest1, pullRequest2];
      for (PullRequest pr in pullRequests) {
        unawaited(pubsub.publish(testTopic, pr));
      }

      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);
      flutterRequest = PullRequestHelper(prNumber: 0, lastCommitHash: oid);
      cocoonRequest = PullRequestHelper(prNumber: 1, lastCommitHash: oid);

      await checkPullRequest.get();
      expectedOptions.add(flutterOption);
      expectedOptions.add(cocoonOption);
      verifyQueries(expectedOptions);
      githubGraphQLClient.verifyMutations(
        <MutationOptions>[
          MutationOptions(
            document: mergePullRequestMutation,
            variables: getMergePullRequestVariables(pullRequest1.number!.toString(), pullRequest1.number!.toString()),
          ),
          MutationOptions(
            document: mergePullRequestMutation,
            variables: getMergePullRequestVariables(pullRequest2.number!.toString(), pullRequest2.number!.toString()),
          ),
        ],
      );
      assert(pubsub.messagesQueue.isEmpty);
    });

    test('Merges unapproved PR from autoroller', () async {
      final PullRequest pullRequest = generatePullRequest(prNumber: 0, author: rollorAuthor);
      githubService.pullRequestData = pullRequest;
      unawaited(pubsub.publish(testTopic, pullRequest));

      checkPullRequest = CheckPullRequest(
        config: config,
        pubsub: pubsub,
        cronAuthProvider: auth,
        approverProvider: (Config config) => MockApproverService(),
      );

      flutterRequest = PullRequestHelper(
        prNumber: 0,
        author: 'dependabot',
        reviews: const <PullRequestReviewHelper>[],
        lastCommitHash: oid,
      );
      cocoonRequest = PullRequestHelper(
        prNumber: 1,
        author: 'dependabot',
        reviews: const <PullRequestReviewHelper>[],
      );

      await checkPullRequest.get();
      expectedOptions.add(flutterOption);
      verifyQueries(expectedOptions);
      githubGraphQLClient.verifyMutations(
        <MutationOptions>[
          MutationOptions(
            document: mergePullRequestMutation,
            variables: getMergePullRequestVariables(pullRequest.number!.toString(), pullRequest.number!.toString()),
          ),
        ],
      );
      assert(pubsub.messagesQueue.isEmpty);
    });

    test('Merges PR with failed tree status if override tree status label is provided', () async {
      PullRequest pullRequest = generatePullRequest(prNumber: 0, labelName: labelName);
      githubService.pullRequestData = pullRequest;
      unawaited(pubsub.publish(testTopic, pullRequest));

      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);

      flutterRequest = PullRequestHelper(
        prNumber: 0,
        lastCommitHash: oid,
        lastCommitStatuses: const <StatusHelper>[
          StatusHelper.flutterBuildFailure,
        ],
      );

      await checkPullRequest.get();
      expectedOptions.add(flutterOption);
      verifyQueries(expectedOptions);
      githubGraphQLClient.verifyMutations(
        <MutationOptions>[
          MutationOptions(
            document: mergePullRequestMutation,
            variables: getMergePullRequestVariables(pullRequest.number!.toString(), pullRequest.number!.toString()),
          ),
        ],
      );
      assert(pubsub.messagesQueue.isEmpty);
    });

    test('Merges a clean revert PR with in progress tests', () async {
      PullRequest pullRequest = generatePullRequest(prNumber: 0);
      githubService.pullRequestData = pullRequest;
      unawaited(pubsub.publish(testTopic, pullRequest));
      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);

      flutterRequest = PullRequestHelper(
        prNumber: 0,
        lastCommitHash: oid,
        lastCommitStatuses: const <StatusHelper>[
          StatusHelper.flutterBuildSuccess,
        ],
        lastCommitMessage: 'Revert "This is a test PR" This reverts commit abc.',
      );

      await checkPullRequest.get();
      expectedOptions.add(flutterOption);
      verifyQueries(expectedOptions);
      githubGraphQLClient.verifyMutations(
        <MutationOptions>[
          MutationOptions(
            document: mergePullRequestMutation,
            variables: getMergePullRequestVariables(pullRequest.number!.toString(), pullRequest.number!.toString()),
          ),
        ],
      );
      assert(pubsub.messagesQueue.isEmpty);
    });

    test('Merges PR with successful checks on repo without tree status', () async {
      PullRequest pullRequest = generatePullRequest(prNumber: 1, repoName: cocoonRepo);
      githubService.pullRequestData = pullRequest;
      unawaited(pubsub.publish(testTopic, pullRequest));

      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);

      cocoonRequest = PullRequestHelper(
        lastCommitHash: oid,
        lastCommitStatuses: const <StatusHelper>[],
      );

      await checkPullRequest.get();
      expectedOptions.add(cocoonOption);
      verifyQueries(expectedOptions);
      githubGraphQLClient.verifyMutations(
        <MutationOptions>[
          MutationOptions(
            document: mergePullRequestMutation,
            variables: getMergePullRequestVariables('0', pullRequest.number!.toString()),
          ),
        ],
      );
      assert(pubsub.messagesQueue.isEmpty);
    });

    test('Merges PR with neutral status checkrun', () async {
      PullRequest pullRequest1 = generatePullRequest(prNumber: 0);
      PullRequest pullRequest2 = generatePullRequest(prNumber: 1, repoName: cocoonRepo);
      githubService.pullRequestData = pullRequest1;
      final List<PullRequest> pullRequests = <PullRequest>[pullRequest1, pullRequest2];
      for (PullRequest pr in pullRequests) {
        unawaited(pubsub.publish(testTopic, pr));
      }
      githubService.checkRunsData = neutralCheckRunsMock;
      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);
      flutterRequest = PullRequestHelper(prNumber: 0, lastCommitHash: oid);
      cocoonRequest = PullRequestHelper(prNumber: 1, lastCommitHash: oid);

      await checkPullRequest.get();
      expectedOptions.add(flutterOption);
      expectedOptions.add(cocoonOption);
      verifyQueries(expectedOptions);
      assert(pubsub.messagesQueue.isEmpty);
    });

    test('Removes the label for the PR with failed tests', () async {
      PullRequest pullRequest1 = generatePullRequest(prNumber: 0);
      PullRequest pullRequest2 = generatePullRequest(prNumber: 1, repoName: cocoonRepo);
      githubService.pullRequestData = pullRequest1;
      final List<PullRequest> pullRequests = <PullRequest>[pullRequest1, pullRequest2];
      for (PullRequest pr in pullRequests) {
        unawaited(pubsub.publish(testTopic, pr));
      }
      githubService.checkRunsData = failedCheckRunsMock;
      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);
      flutterRequest = PullRequestHelper(prNumber: 0, lastCommitHash: oid);
      cocoonRequest = PullRequestHelper(prNumber: 1, lastCommitHash: oid);

      await checkPullRequest.get();
      expectedOptions.add(flutterOption);
      expectedOptions.add(cocoonOption);
      verifyQueries(expectedOptions);
      assert(pubsub.messagesQueue.isEmpty);
    });

    test('Removes the label for the PR with failed status', () async {
      PullRequest pullRequest = generatePullRequest(prNumber: 0);
      githubService.pullRequestData = pullRequest;
      unawaited(pubsub.publish(testTopic, pullRequest));

      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);

      flutterRequest = PullRequestHelper(
        lastCommitHash: oid,
        lastCommitStatuses: const <StatusHelper>[
          StatusHelper.flutterBuildSuccess,
          StatusHelper.otherStatusFailure,
        ],
      );

      await checkPullRequest.get();
      expectedOptions.add(flutterOption);
      verifyQueries(expectedOptions);
      assert(pubsub.messagesQueue.isEmpty);
    });

    test('Removes the label if non member does not have at least 2 member reviews', () async {
      PullRequest pullRequest = generatePullRequest(prNumber: 0, authorAssociation: '');
      githubService.pullRequestData = pullRequest;
      unawaited(pubsub.publish(testTopic, pullRequest));

      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);

      flutterRequest = PullRequestHelper(
        authorAssociation: '',
        lastCommitHash: oid,
        lastCommitStatuses: const <StatusHelper>[
          StatusHelper.flutterBuildSuccess,
        ],
      );

      await checkPullRequest.get();
      expectedOptions.add(flutterOption);
      verifyQueries(expectedOptions);
      assert(pubsub.messagesQueue.isEmpty);
    });

    test('Removes the label for the PR with null checks and statuses', () async {
      PullRequest pullRequest = generatePullRequest(prNumber: 0);
      githubService.pullRequestData = pullRequest;
      unawaited(pubsub.publish(testTopic, pullRequest));

      githubService.checkRunsData = emptyCheckRunsMock;
      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);

      flutterRequest = PullRequestHelper(
        lastCommitHash: oid,
        lastCommitStatuses: const <StatusHelper>[],
      );

      await checkPullRequest.get();
      expectedOptions.add(flutterOption);
      verifyQueries(expectedOptions);
      assert(pubsub.messagesQueue.isEmpty);
    });

    test('Does not merge PR with in progress checks', () async {
      PullRequest pullRequest1 = generatePullRequest(prNumber: 0);
      PullRequest pullRequest2 = generatePullRequest(prNumber: 1, repoName: cocoonRepo);
      githubService.pullRequestData = pullRequest1;
      final List<PullRequest> pullRequests = <PullRequest>[pullRequest1, pullRequest2];
      for (PullRequest pr in pullRequests) {
        unawaited(pubsub.publish(testTopic, pr));
      }
      githubService.checkRunsData = inProgressCheckRunsMock;
      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);
      flutterRequest = PullRequestHelper(prNumber: 0);
      cocoonRequest = PullRequestHelper(prNumber: 1);
      await checkPullRequest.get();
      expectedOptions.add(flutterOption);
      expectedOptions.add(cocoonOption);
      verifyQueries(expectedOptions);
      expect(pubsub.messagesQueue.length, 2);
      pubsub.messagesQueue.clear();
    });

    test('Does not merge PR if no autosubmit label any more', () async {
      PullRequest pullRequest1 = generatePullRequest(prNumber: 0, autosubmitLabel: noAutosubmitLabel);
      PullRequest pullRequest2 =
          generatePullRequest(prNumber: 1, autosubmitLabel: noAutosubmitLabel, repoName: cocoonRepo);
      githubService.pullRequestData = pullRequest1;
      final List<PullRequest> pullRequests = <PullRequest>[pullRequest1, pullRequest2];
      for (PullRequest pr in pullRequests) {
        unawaited(pubsub.publish(testTopic, pr));
      }
      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);
      flutterRequest = PullRequestHelper(prNumber: 0);
      cocoonRequest = PullRequestHelper(prNumber: 1);
      await checkPullRequest.get();
      assert(pubsub.messagesQueue.isEmpty);
    });

    test('Self review is disallowed', () async {
      PullRequest pullRequest = generatePullRequest(prNumber: 0, author: 'some_rando');
      githubService.pullRequestData = pullRequest;
      unawaited(pubsub.publish(testTopic, pullRequest));
      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);
      flutterRequest = PullRequestHelper(
        author: 'some_rando',
        lastCommitHash: oid,
        authorAssociation: 'MEMBER',
        reviews: <PullRequestReviewHelper>[
          const PullRequestReviewHelper(
            authorName: 'some_rando',
            state: ReviewState.APPROVED,
            memberType: MemberType.MEMBER,
          )
        ],
        lastCommitStatuses: const <StatusHelper>[
          StatusHelper.flutterBuildSuccess,
        ],
      );
      await checkPullRequest.get();
      expectedOptions.add(flutterOption);
      verifyQueries(expectedOptions);
      assert(pubsub.messagesQueue.isEmpty);
    });

    test('All messages are pulled', () async {
      for (int i = 0; i < 3; i++) {
        final PullRequest pullRequest = generatePullRequest(prNumber: i, repoName: cocoonRepo);
        unawaited(pubsub.publish('auto-submit-queue-sub', pullRequest));
      }

      checkPullRequest = CheckPullRequest(config: config, pubsub: pubsub, cronAuthProvider: auth);
      cocoonRequest = PullRequestHelper(prNumber: 0, lastCommitHash: oid);
      final List<pub.ReceivedMessage> messages = await checkPullRequest.pullMessages();
      expect(messages.length, 3);
    });
  });
}

QueryResult createQueryResult(PullRequestHelper pullRequest) {
  return createFakeQueryResult(
    data: <String, dynamic>{
      'repository': <String, dynamic>{
        'pullRequest': pullRequest.toEntry().cast<String, dynamic>(),
      },
    },
  );
}

Map<String, dynamic> getMergePullRequestVariables(String id, String number) {
  return <String, dynamic>{
    'id': id,
    'oid': oid,
    'title': '$title (#$number)',
  };
}
