// 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 'package:cocoon_service/cocoon_service.dart';
import 'package:cocoon_service/src/request_handlers/flaky_handler_utils.dart';
import 'package:cocoon_service/src/service/bigquery.dart';
import 'package:cocoon_service/src/service/github_service.dart';
import 'package:github/github.dart';
import 'package:http/http.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';

import '../src/datastore/fake_config.dart';
import '../src/request_handling/api_request_handler_tester.dart';
import '../src/request_handling/fake_authentication.dart';
import '../src/request_handling/fake_http.dart';
import '../src/utilities/mocks.dart';

import 'update_existing_flaky_issues_test_data.dart';

const String kThreshold = '0.02';

void main() {
  group('Update flaky', () {
    late UpdateExistingFlakyIssue handler;
    late ApiRequestHandlerTester tester;
    FakeHttpRequest request;
    late FakeConfig config;
    FakeClientContext clientContext;
    FakeAuthenticationProvider auth;
    late MockBigqueryService mockBigqueryService;
    late MockGitHub mockGitHubClient;
    late MockIssuesService mockIssuesService;
    MockRepositoriesService mockRepositoriesService;

    setUp(() {
      request = FakeHttpRequest(
        queryParametersValue: <String, dynamic>{
          FileFlakyIssueAndPR.kThresholdKey: kThreshold,
        },
      );

      clientContext = FakeClientContext();
      auth = FakeAuthenticationProvider(clientContext: clientContext);
      mockBigqueryService = MockBigqueryService();
      mockGitHubClient = MockGitHub();
      mockIssuesService = MockIssuesService();
      mockRepositoriesService = MockRepositoriesService();

      // when gets existing flaky issues.
      when(mockIssuesService.listByRepo(captureAny, state: captureAnyNamed('state'), labels: captureAnyNamed('labels')))
          .thenAnswer((Invocation invocation) {
        return const Stream<Issue>.empty();
      });

      // when gets the content of .ci.yaml
      when(mockRepositoriesService.getContents(captureAny, kCiYamlPath)).thenAnswer((Invocation invocation) {
        return Future<RepositoryContents>.value(
            RepositoryContents(file: GitHubFile(content: gitHubEncode(ciYamlContent))));
      });
      // when gets the content of TESTOWNERS
      when(mockRepositoriesService.getContents(captureAny, kTestOwnerPath)).thenAnswer((Invocation invocation) {
        return Future<RepositoryContents>.value(
            RepositoryContents(file: GitHubFile(content: gitHubEncode(testOwnersContent))));
      });

      when(mockGitHubClient.repositories).thenReturn(mockRepositoriesService);
      when(mockGitHubClient.issues).thenReturn(mockIssuesService);
      when(mockIssuesService.createComment(any, any, any)).thenAnswer((_) async => IssueComment());
      when(mockIssuesService.edit(any, any, any)).thenAnswer((_) async => Issue());
      config = FakeConfig(
        githubService: GithubService(mockGitHubClient),
        bigqueryService: mockBigqueryService,
        githubOAuthTokenValue: 'token',
      );
      tester = ApiRequestHandlerTester(request: request);

      handler = UpdateExistingFlakyIssue(
        config: config,
        authenticationProvider: auth,
      );
    });

    test('Can add existing issue comment', () async {
      const int existingIssueNumber = 1234;
      final List<IssueLabel> existingLabels = <IssueLabel>[
        IssueLabel(name: 'some random label'),
        IssueLabel(name: 'P2'),
      ];
      // When queries flaky data from BigQuery.
      when(mockBigqueryService.listBuilderStatistic(kBigQueryProjectId)).thenAnswer((Invocation invocation) {
        return Future<List<BuilderStatistic>>.value(semanticsIntegrationTestResponse);
      });
      when(mockBigqueryService.listBuilderStatistic(kBigQueryProjectId, bucket: 'staging'))
          .thenAnswer((Invocation invocation) {
        return Future<List<BuilderStatistic>>.value(stagingCiyamlTestResponse);
      });
      // when gets existing flaky issues.
      when(mockIssuesService.listByRepo(captureAny, state: captureAnyNamed('state'), labels: captureAnyNamed('labels')))
          .thenAnswer((Invocation invocation) {
        return Stream<Issue>.fromIterable(<Issue>[
          Issue(
            assignee: User(login: 'some dude'),
            number: existingIssueNumber,
            state: 'open',
            labels: existingLabels,
            title: expectedSemanticsIntegrationTestResponseTitle,
            body: expectedSemanticsIntegrationTestResponseBody,
            createdAt:
                DateTime.now().subtract(const Duration(days: UpdateExistingFlakyIssue.kFreshPeriodForOpenFlake + 1)),
          )
        ]);
      });
      // when firing github request.
      // This is for replacing labels.
      when(mockGitHubClient.request(
        captureAny,
        captureAny,
        body: captureAnyNamed('body'),
      )).thenAnswer((Invocation invocation) {
        return Future<Response>.value(Response('[]', 200));
      });
      final Map<String, dynamic> result = await utf8.decoder
          .bind((await tester.get<Body>(handler)).serialize() as Stream<List<int>>)
          .transform(json.decoder)
          .single as Map<String, dynamic>;

      // Verify comment is created correctly.
      List<dynamic> captured = verify(mockIssuesService.createComment(captureAny, captureAny, captureAny)).captured;
      expect(captured.length, 3);
      expect(captured[0].toString(), Config.flutterSlug.toString());
      expect(captured[1], existingIssueNumber);
      expect(captured[2], expectedSemanticsIntegrationTestIssueComment);

      // Verify labels are applied correctly.
      captured = verify(mockGitHubClient.request(
        captureAny,
        captureAny,
        body: captureAnyNamed('body'),
      )).captured;
      expect(captured.length, 3);
      expect(captured[0].toString(), 'PUT');
      expect(captured[1], '/repos/${Config.flutterSlug.fullName}/issues/$existingIssueNumber/labels');
      expect(captured[2], GitHubJson.encode(<String>['some random label', 'P1']));

      expect(result['Status'], 'success');
    });

    test('Add only one comment on existing issue when a builder has been marked as unflaky', () async {
      const int existingIssueNumber = 1234;
      final List<IssueLabel> existingLabels = <IssueLabel>[
        IssueLabel(name: 'some random label'),
        IssueLabel(name: 'P2'),
      ];
      // When queries flaky data from BigQuery.
      when(mockBigqueryService.listBuilderStatistic(kBigQueryProjectId)).thenAnswer((Invocation invocation) {
        return Future<List<BuilderStatistic>>.value(semanticsIntegrationTestResponse);
      });
      when(mockBigqueryService.listBuilderStatistic(kBigQueryProjectId, bucket: 'staging'))
          .thenAnswer((Invocation invocation) {
        return Future<List<BuilderStatistic>>.value(stagingSameBuilderSemanticsIntegrationTestResponse);
      });
      // when gets existing flaky issues.
      when(mockIssuesService.listByRepo(captureAny, state: captureAnyNamed('state'), labels: captureAnyNamed('labels')))
          .thenAnswer((Invocation invocation) {
        return Stream<Issue>.fromIterable(<Issue>[
          Issue(
            assignee: User(login: 'some dude'),
            number: existingIssueNumber,
            state: 'open',
            labels: existingLabels,
            title: expectedSemanticsIntegrationTestResponseTitle,
            body: expectedSemanticsIntegrationTestResponseBody,
            createdAt:
                DateTime.now().subtract(const Duration(days: UpdateExistingFlakyIssue.kFreshPeriodForOpenFlake + 1)),
          )
        ]);
      });
      // when firing github request.
      // This is for replacing labels.
      when(mockGitHubClient.request(
        captureAny,
        captureAny,
        body: captureAnyNamed('body'),
      )).thenAnswer((Invocation invocation) {
        return Future<Response>.value(Response('[]', 200));
      });
      final Map<String, dynamic> result = await utf8.decoder
          .bind((await tester.get<Body>(handler)).serialize() as Stream<List<int>>)
          .transform(json.decoder)
          .single as Map<String, dynamic>;

      // Verify comment is created correctly.
      List<dynamic> captured = verify(mockIssuesService.createComment(captureAny, captureAny, captureAny)).captured;
      expect(captured.length, 3);
      expect(captured[0].toString(), Config.flutterSlug.toString());
      expect(captured[1], existingIssueNumber);
      expect(captured[2], expectedSemanticsIntegrationTestIssueComment);

      // Verify labels are applied correctly.
      captured = verify(mockGitHubClient.request(
        captureAny,
        captureAny,
        body: captureAnyNamed('body'),
      )).captured;
      expect(captured.length, 3);
      expect(captured[0].toString(), 'PUT');
      expect(captured[1], '/repos/${Config.flutterSlug.fullName}/issues/$existingIssueNumber/labels');
      expect(captured[2], GitHubJson.encode(<String>['some random label', 'P1']));

      expect(result['Status'], 'success');
    });

    test('Can add bot staging and prod stats for a bringup: true builder', () async {
      const int existingIssueNumber = 1234;
      final List<IssueLabel> existingLabels = <IssueLabel>[
        IssueLabel(name: 'some random label'),
        IssueLabel(name: 'P2'),
      ];
      // When queries flaky data from BigQuery.
      when(mockBigqueryService.listBuilderStatistic(kBigQueryProjectId)).thenAnswer((Invocation invocation) {
        return Future<List<BuilderStatistic>>.value(ciyamlTestResponse);
      });
      when(mockBigqueryService.listBuilderStatistic(kBigQueryProjectId, bucket: 'staging'))
          .thenAnswer((Invocation invocation) {
        return Future<List<BuilderStatistic>>.value(stagingCiyamlTestResponse);
      });
      // when gets existing flaky issues.
      when(mockIssuesService.listByRepo(captureAny, state: captureAnyNamed('state'), labels: captureAnyNamed('labels')))
          .thenAnswer((Invocation invocation) {
        return Stream<Issue>.fromIterable(<Issue>[
          Issue(
            assignee: User(login: 'some dude'),
            number: existingIssueNumber,
            state: 'open',
            labels: existingLabels,
            title: expectedStagingSemanticsIntegrationTestResponseTitle,
            body: expectedStagingSemanticsIntegrationTestResponseBody,
            createdAt:
                DateTime.now().subtract(const Duration(days: UpdateExistingFlakyIssue.kFreshPeriodForOpenFlake + 1)),
          )
        ]);
      });
      // when firing github request.
      // This is for replacing labels.
      when(mockGitHubClient.request(
        captureAny,
        captureAny,
        body: captureAnyNamed('body'),
      )).thenAnswer((Invocation invocation) {
        return Future<Response>.value(Response('[]', 200));
      });
      final Map<String, dynamic> result = await utf8.decoder
          .bind((await tester.get<Body>(handler)).serialize() as Stream<List<int>>)
          .transform(json.decoder)
          .single as Map<String, dynamic>;

      // Verify comment is created correctly.
      List<dynamic> captured = verify(mockIssuesService.createComment(captureAny, captureAny, captureAny)).captured;
      expect(captured.length, 6);
      expect(captured[0].toString(), Config.flutterSlug.toString());
      expect(captured[1], existingIssueNumber);
      expect(captured[2], expectedCiyamlTestIssueComment);
      expect(captured[3].toString(), Config.flutterSlug.toString());
      expect(captured[4], existingIssueNumber);
      expect(captured[5], expectedStagingCiyamlTestIssueComment);

      // Verify labels are applied correctly.
      captured = verify(mockGitHubClient.request(
        captureAny,
        captureAny,
        body: captureAnyNamed('body'),
      )).captured;
      expect(captured.length, 6);
      expect(captured[0].toString(), 'PUT');
      expect(captured[1], '/repos/${Config.flutterSlug.fullName}/issues/$existingIssueNumber/labels');
      expect(captured[2], GitHubJson.encode(<String>['some random label', 'P1']));

      expect(result['Status'], 'success');
    });

    test('Can assign test owner', () async {
      const int existingIssueNumber = 1234;
      final List<IssueLabel> existingLabels = <IssueLabel>[
        IssueLabel(name: 'some random label'),
        IssueLabel(name: 'P2'),
      ];
      // When queries flaky data from BigQuery.
      when(mockBigqueryService.listBuilderStatistic(kBigQueryProjectId)).thenAnswer((Invocation invocation) {
        return Future<List<BuilderStatistic>>.value(semanticsIntegrationTestResponse);
      });
      when(mockBigqueryService.listBuilderStatistic(kBigQueryProjectId, bucket: 'staging'))
          .thenAnswer((Invocation invocation) {
        return Future<List<BuilderStatistic>>.value(stagingCiyamlTestResponse);
      });
      // when gets existing flaky issues.
      when(mockIssuesService.listByRepo(captureAny, state: captureAnyNamed('state'), labels: captureAnyNamed('labels')))
          .thenAnswer((Invocation invocation) {
        return Stream<Issue>.fromIterable(<Issue>[
          Issue(
            number: existingIssueNumber,
            state: 'open',
            labels: existingLabels,
            title: expectedSemanticsIntegrationTestResponseTitle,
            body: expectedSemanticsIntegrationTestResponseBody,
            createdAt:
                DateTime.now().subtract(const Duration(days: UpdateExistingFlakyIssue.kFreshPeriodForOpenFlake + 1)),
          )
        ]);
      });
      // when firing github request.
      // This is for replacing labels.
      when(mockGitHubClient.request(
        captureAny,
        captureAny,
        body: captureAnyNamed('body'),
      )).thenAnswer((Invocation invocation) {
        return Future<Response>.value(Response('[]', 200));
      });
      final Map<String, dynamic> result = await utf8.decoder
          .bind((await tester.get<Body>(handler)).serialize() as Stream<List<int>>)
          .transform(json.decoder)
          .single as Map<String, dynamic>;

      // Verify comment is created correctly.
      final List<dynamic> captured = verify(mockIssuesService.edit(captureAny, captureAny, captureAny)).captured;
      expect(captured.length, 3);
      expect(captured[0].toString(), Config.flutterSlug.toString());
      expect(captured[1], existingIssueNumber);
      final IssueRequest request = captured[2] as IssueRequest;
      expect(request.assignee, 'HansMuller');

      expect(result['Status'], 'success');
    });

    test('Can add existing issue comment case 0.0', () async {
      const int existingIssueNumber = 1234;
      final List<IssueLabel> existingLabels = <IssueLabel>[
        IssueLabel(name: 'some random label'),
        IssueLabel(name: 'P2'),
      ];
      // When queries flaky data from BigQuery.
      when(mockBigqueryService.listBuilderStatistic(kBigQueryProjectId)).thenAnswer((Invocation invocation) {
        return Future<List<BuilderStatistic>>.value(semanticsIntegrationTestResponseZeroFlake);
      });
      when(mockBigqueryService.listBuilderStatistic(kBigQueryProjectId, bucket: 'staging'))
          .thenAnswer((Invocation invocation) {
        return Future<List<BuilderStatistic>>.value(stagingCiyamlTestResponse);
      });
      // when gets existing flaky issues.
      when(mockIssuesService.listByRepo(captureAny, state: captureAnyNamed('state'), labels: captureAnyNamed('labels')))
          .thenAnswer((Invocation invocation) {
        return Stream<Issue>.fromIterable(<Issue>[
          Issue(
            number: existingIssueNumber,
            state: 'open',
            labels: existingLabels,
            title: expectedSemanticsIntegrationTestResponseTitle,
            body: expectedSemanticsIntegrationTestResponseBody,
            createdAt:
                DateTime.now().subtract(const Duration(days: UpdateExistingFlakyIssue.kFreshPeriodForOpenFlake + 1)),
          )
        ]);
      });
      // when firing github request.
      // This is for replacing labels.
      when(mockGitHubClient.request(
        captureAny,
        captureAny,
        body: captureAnyNamed('body'),
      )).thenAnswer((Invocation invocation) {
        return Future<Response>.value(Response('[]', 200));
      });

      final Map<String, dynamic> result = await utf8.decoder
          .bind((await tester.get<Body>(handler)).serialize() as Stream<List<int>>)
          .transform(json.decoder)
          .single as Map<String, dynamic>;

      // Verify issue is created correctly.
      List<dynamic> captured = verify(mockIssuesService.createComment(captureAny, captureAny, captureAny)).captured;
      expect(captured.length, 3);
      expect(captured[0].toString(), Config.flutterSlug.toString());
      expect(captured[1], existingIssueNumber);
      expect(captured[2], expectedSemanticsIntegrationTestZeroFlakeIssueComment);

      // Verify labels are the same.
      captured = verify(mockGitHubClient.request(
        captureAny,
        captureAny,
        body: captureAnyNamed('body'),
      )).captured;
      expect(captured.length, 3);
      expect(captured[0].toString(), 'PUT');
      expect(captured[1], '/repos/${Config.flutterSlug.fullName}/issues/$existingIssueNumber/labels');
      expect(captured[2], GitHubJson.encode(<String>['some random label', 'P2']));

      expect(result['Status'], 'success');
    });

    test('Does not add comment if the issue is still fresh', () async {
      const int existingIssueNumber = 1234;
      final List<IssueLabel> existingLabels = <IssueLabel>[
        IssueLabel(name: 'some random label'),
        IssueLabel(name: 'P2'),
      ];
      // When queries flaky data from BigQuery.
      when(mockBigqueryService.listBuilderStatistic(kBigQueryProjectId)).thenAnswer((Invocation invocation) {
        return Future<List<BuilderStatistic>>.value(semanticsIntegrationTestResponseZeroFlake);
      });
      when(mockBigqueryService.listBuilderStatistic(kBigQueryProjectId, bucket: 'staging'))
          .thenAnswer((Invocation invocation) {
        return Future<List<BuilderStatistic>>.value(stagingCiyamlTestResponse);
      });
      // when gets existing flaky issues.
      when(mockIssuesService.listByRepo(captureAny, state: captureAnyNamed('state'), labels: captureAnyNamed('labels')))
          .thenAnswer((Invocation invocation) {
        return Stream<Issue>.fromIterable(<Issue>[
          Issue(
            number: existingIssueNumber,
            state: 'open',
            labels: existingLabels,
            title: expectedSemanticsIntegrationTestResponseTitle,
            body: expectedSemanticsIntegrationTestResponseBody,
            createdAt:
                DateTime.now().subtract(const Duration(days: UpdateExistingFlakyIssue.kFreshPeriodForOpenFlake - 1)),
          )
        ]);
      });

      final Map<String, dynamic> result = await utf8.decoder
          .bind((await tester.get<Body>(handler)).serialize() as Stream<List<int>>)
          .transform(json.decoder)
          .single as Map<String, dynamic>;

      verifyNever(mockIssuesService.createComment(captureAny, captureAny, captureAny));

      // Verify labels are the same.
      verifyNever(mockGitHubClient.request(
        captureAny,
        captureAny,
        body: captureAnyNamed('body'),
      ));

      expect(result['Status'], 'success');
    });
  });
}
