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

import 'dart:convert';

import 'package:auto_submit/model/auto_submit_query_result.dart';
import 'package:auto_submit/validations/validation.dart';
import 'package:github/github.dart' as github;

import 'revert_test_data.dart';

import 'package:auto_submit/validations/revert.dart';
import 'package:test/scaffolding.dart';

import '../utilities/mocks.dart';
import '../src/service/fake_config.dart';
import '../src/service/fake_github_service.dart';
import '../src/service/fake_graphql_client.dart';

void main() {
  late FakeConfig config;
  FakeGithubService githubService = FakeGithubService();
  late FakeGraphQLClient githubGraphQLClient;
  MockGitHub gitHub = MockGitHub();
  late Revert revert;

  /// Setup objects needed across test groups.
  setUp(() {
    githubGraphQLClient = FakeGraphQLClient();
    config = FakeConfig(githubService: githubService, githubGraphQLClient: githubGraphQLClient, githubClient: gitHub);
    revert = Revert(config: config);
  });

  group('Author validation tests.', () {
    test('Validate author association member is valid.', () {
      String authorAssociation = 'MEMBER';
      assert(revert.isValidAuthor('octocat', authorAssociation));
    });

    test('Validate author association owner is valid.', () {
      String authorAssociation = 'OWNER';
      assert(revert.isValidAuthor('octocat', authorAssociation));
    });

    test('Validate author dependabot is valid.', () {
      String author = 'dependabot';
      String authorAssociation = 'NON_MEMBER';
      assert(revert.isValidAuthor(author, authorAssociation));
    });

    test('Validate autoroller account is valid.', () {
      String author = 'engine-flutter-autoroll';
      String authorAssociation = 'CONTRIBUTOR';
      assert(revert.isValidAuthor(author, authorAssociation));
    });
  });

  group('Pattern matching for revert text link', () {
    test('Link extraction from description is successful.', () {
      // input, expected
      Map<String, String> tests = <String, String>{};
      tests['Reverts flutter/cocoon#123456'] = 'flutter/cocoon#123456';
      tests['Reverts    flutter/cocoon#123456'] = 'flutter/cocoon#123456';
      tests['Reverts flutter/flutter-intellij#123456'] = 'flutter/flutter-intellij#123456';
      tests['Reverts flutter/platform_tests#123456'] = 'flutter/platform_tests#123456';
      tests['Reverts flutter/.github#123456'] = 'flutter/.github#123456';
      tests['Reverts flutter/assets-for-api-docs#123456'] = 'flutter/assets-for-api-docs#123456';
      tests['Reverts flutter/flutter.github.io#123456'] = 'flutter/flutter.github.io#123456';
      tests['Reverts flutter/flutter_gallery_assets#123456'] = 'flutter/flutter_gallery_assets#123456';
      tests['reverts flutter/cocoon#12323'] = 'flutter/cocoon#12323';
      tests['reverts flutter/cocoon#223'] = 'flutter/cocoon#223';
      tests["""Reverts flutter/cocoon#123456

      Some other notes in the description a developer might add.
      And another note."""] = 'flutter/cocoon#123456';

      tests.forEach((key, value) {
        String? linkFound = revert.extractLinkFromText(key);
        assert(linkFound != null);
        assert(linkFound == value);
      });
    });

    test('Link extraction from description returns null', () {
      Map<String, String> tests = <String, String>{};
      tests['Revert flutter/cocoon#123456'] = '';
      tests['revert flutter/cocoon#123456'] = '';
      tests['Reverts flutter/cocoon#'] = '';
      tests['Reverts flutter123'] = '';

      tests.forEach((key, value) {
        String? linkFound = revert.extractLinkFromText(key);
        assert(linkFound == null);
      });
    });
  });

  group('Validate Pull Requests.', () {
    test('Validation fails on author validation, returns error.', () async {
      Map<String, dynamic> pullRequestJsonMap = jsonDecode(revertPullRequestJson) as Map<String, dynamic>;
      github.PullRequest revertPullRequest = github.PullRequest.fromJson(pullRequestJsonMap);
      revertPullRequest.authorAssociation = 'CONTRIBUTOR';
      final Map<String, dynamic> queryResultJsonDecode =
          jsonDecode(queryResultRepositoryContributorJson) as Map<String, dynamic>;
      final QueryResult queryResult = QueryResult.fromJson(queryResultJsonDecode);
      ValidationResult validationResult = await revert.validate(queryResult, revertPullRequest);
      assert(!validationResult.result);
      assert(validationResult.action == Action.REMOVE_LABEL);
      assert(validationResult.message.contains(RegExp(r'The author.*does not have permissions to make this request.')));
    });

    test('Validation fails on merge conflict flag.', () async {
      Map<String, dynamic> pullRequestJsonMap = jsonDecode(revertPullRequestJson) as Map<String, dynamic>;
      github.PullRequest revertPullRequest = github.PullRequest.fromJson(pullRequestJsonMap);
      revertPullRequest.mergeable = false;
      final Map<String, dynamic> queryResultJsonDecode =
          jsonDecode(queryResultRepositoryOwnerJson) as Map<String, dynamic>;
      final QueryResult queryResult = QueryResult.fromJson(queryResultJsonDecode);
      ValidationResult validationResult = await revert.validate(queryResult, revertPullRequest);
      assert(!validationResult.result);
      assert(validationResult.action == Action.REMOVE_LABEL);
      assert(
        validationResult.message ==
            'This pull request cannot be merged due to conflicts. Please resolve conflicts and re-add the revert label.',
      );
    });

    test('Validation fails on malformed reverts link in the pr body.', () async {
      Map<String, dynamic> pullRequestJsonMap = jsonDecode(revertPullRequestJson) as Map<String, dynamic>;
      github.PullRequest revertPullRequest = github.PullRequest.fromJson(pullRequestJsonMap);
      revertPullRequest.body = 'Reverting flutter/cocoon#1234';
      final Map<String, dynamic> queryResultJsonDecode =
          jsonDecode(queryResultRepositoryOwnerJson) as Map<String, dynamic>;
      final QueryResult queryResult = QueryResult.fromJson(queryResultJsonDecode);
      ValidationResult validationResult = await revert.validate(queryResult, revertPullRequest);
      assert(!validationResult.result);
      assert(validationResult.action == Action.REMOVE_LABEL);
      assert(
        validationResult.message ==
            'A reverts link could not be found or was formatted incorrectly. Format is \'Reverts owner/repo#id\'',
      );
    });

    test('Validation fails on pull request file lists not matching.', () async {
      Map<String, dynamic> pullRequestJsonMap = jsonDecode(revertPullRequestJson) as Map<String, dynamic>;
      github.PullRequest revertPullRequest = github.PullRequest.fromJson(pullRequestJsonMap);
      final Map<String, dynamic> queryResultJsonDecode =
          jsonDecode(queryResultRepositoryOwnerJson) as Map<String, dynamic>;
      final QueryResult queryResult = QueryResult.fromJson(queryResultJsonDecode);

      Map<String, dynamic> originalPullRequestJsonMap = jsonDecode(originalPullRequestJson) as Map<String, dynamic>;
      github.PullRequest originalPullRequest = github.PullRequest.fromJson(originalPullRequestJsonMap);
      githubService.pullRequestData = originalPullRequest;

      // code gets the original file list then the current file list.
      githubService.usePullRequestFilesList = true;
      githubService.pullRequestFilesMockList.add(originalPullRequestFilesSubsetJson);
      githubService.pullRequestFilesMockList.add(revertPullRequestFilesJson);

      ValidationResult validationResult = await revert.validate(queryResult, revertPullRequest);
      assert(!validationResult.result);
      assert(validationResult.action == Action.REMOVE_LABEL);
      assert(
        validationResult.message ==
            'Validation of the revert request has failed. Verify the files in the revert request are the same as the original PR and resubmit the revert request.',
      );
    });

    test('Validation is successful.', () async {
      Map<String, dynamic> pullRequestJsonMap = jsonDecode(revertPullRequestJson) as Map<String, dynamic>;
      github.PullRequest revertPullRequest = github.PullRequest.fromJson(pullRequestJsonMap);
      final Map<String, dynamic> queryResultJsonDecode =
          jsonDecode(queryResultRepositoryOwnerJson) as Map<String, dynamic>;
      final QueryResult queryResult = QueryResult.fromJson(queryResultJsonDecode);

      Map<String, dynamic> originalPullRequestJsonMap = jsonDecode(originalPullRequestJson) as Map<String, dynamic>;
      github.PullRequest originalPullRequest = github.PullRequest.fromJson(originalPullRequestJsonMap);
      githubService.pullRequestData = originalPullRequest;

      // code gets the original file list then the current file list.
      githubService.usePullRequestFilesList = true;
      githubService.pullRequestFilesMockList.add(originalPullRequestFilesJson);
      githubService.pullRequestFilesMockList.add(revertPullRequestFilesJson);

      ValidationResult validationResult = await revert.validate(queryResult, revertPullRequest);
      assert(validationResult.result);
      assert(validationResult.message == 'Revert request has been verified and will be queued for merge.');
    });
  });
}
