// Copyright 2021 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/model/appengine/commit.dart';
import 'package:cocoon_service/src/model/appengine/stage.dart';
import 'package:cocoon_service/src/model/appengine/task.dart';
import 'package:cocoon_service/src/service/build_status_provider.dart';
import 'package:cocoon_service/src/service/datastore.dart';
import 'package:gcloud/db.dart';
import 'package:test/test.dart';

import '../src/datastore/fake_config.dart';
import '../src/request_handling/fake_authentication.dart';
import '../src/request_handling/fake_http.dart';
import '../src/request_handling/request_handler_tester.dart';
import '../src/service/fake_build_status_provider.dart';
import '../src/utilities/entity_generators.dart';

void main() {
  group('GetGreenCommits', () {
    late FakeConfig config;
    FakeClientContext clientContext;
    FakeKeyHelper keyHelper;
    FakeBuildStatusService buildStatusService;
    late RequestHandlerTester tester;
    late GetGreenCommits handler;

    final Commit commit1 = generateCommit(1, timestamp: 3, sha: 'ea28a9c34dc701de891eaf74503ca4717019f829');
    final Commit commit2 = generateCommit(2, timestamp: 1, sha: 'd5b0b3c8d1c5fd89302089077ccabbcfaae045e4');
    final Commit commitBranched = generateCommit(
      2,
      timestamp: 1,
      sha: 'ffffffffffffffffffffffffffffffffaae045e4',
      branch: 'flutter-2.13-candidate.0',
    );

    final Task task1Succeed = generateTask(1, status: Task.statusSucceeded);
    final Task task2Failed = generateTask(2, status: Task.statusFailed); // should fail if included
    final Task task3FailedFlaky =
        generateTask(3, status: Task.statusFailed, isFlaky: true); // should succeed if included because `bringup: true`
    final Task task4SucceedFlaky = generateTask(4, status: Task.statusSucceeded, isFlaky: true);

    final Stage stageOneSucceed =
        Stage('cocoon', commit1, [task1Succeed], Task.statusInProgress); // should scceed, since task 1 succeed
    final Stage stageFailed = Stage(
      'luci',
      commit1,
      [task1Succeed, task2Failed],
      Task.statusInProgress,
    ); // should fail, since task 1 succeed and task2 fail
    final Stage stageMultipleSucceed = Stage(
      'cocoon',
      commit2,
      [task1Succeed, task4SucceedFlaky],
      Task.statusInProgress,
    ); // should succeed, since both task 1 and task 4 succeed
    final Stage stageFailedFlaky = Stage(
      'luci',
      commit2,
      [task1Succeed, task3FailedFlaky],
      Task.statusInProgress,
    ); // should succeed, even though it includes task 3

    Future<List<T?>?> decodeHandlerBody<T>() async {
      final Body body = await tester.get(handler);
      return (await utf8.decoder.bind(body.serialize() as Stream<List<int>>).transform(json.decoder).single
              as List<dynamic>)
          .cast<T>();
    }

    setUp(() {
      clientContext = FakeClientContext();
      keyHelper = FakeKeyHelper(applicationContext: clientContext.applicationContext);
      tester = RequestHandlerTester();
      config = FakeConfig(keyHelperValue: keyHelper);
      buildStatusService = FakeBuildStatusService(commitStatuses: <CommitStatus>[]);
      handler = GetGreenCommits(
        config: config,
        datastoreProvider: (DatastoreDB db) => DatastoreService(config.db, 5),
        buildStatusProvider: (_) => buildStatusService,
      );
    });

    test('no green commits', () async {
      final List<String?> result = (await decodeHandlerBody())!;
      expect(result, isEmpty);
    });

    test('should return commits with all tasks succeed', () async {
      buildStatusService = FakeBuildStatusService(
        commitStatuses: <CommitStatus>[
          CommitStatus(commit1, <Stage>[stageOneSucceed]),
          CommitStatus(commit2, <Stage>[stageOneSucceed, stageMultipleSucceed])
        ],
      );
      handler = GetGreenCommits(
        config: config,
        datastoreProvider: (DatastoreDB db) => DatastoreService(config.db, 5),
        buildStatusProvider: (_) => buildStatusService,
      );

      final List<String?> result = (await decodeHandlerBody())!;

      expect(result.length, 2);
      expect(result, <String>[
        commit2.sha!,
        commit1.sha!,
      ]);
    });

    test('should fail commits that have failed task without [bringup: true] label', () async {
      buildStatusService = FakeBuildStatusService(
        commitStatuses: <CommitStatus>[
          CommitStatus(commit1, <Stage>[stageFailed]),
          CommitStatus(commit2, <Stage>[stageOneSucceed, stageMultipleSucceed])
        ],
      );
      handler = GetGreenCommits(
        config: config,
        datastoreProvider: (DatastoreDB db) => DatastoreService(config.db, 5),
        buildStatusProvider: (_) => buildStatusService,
      );

      final List<String?> result = (await decodeHandlerBody())!;

      expect(result.length, 1);
      expect(result, <String>[commit2.sha!]);
    });

    test('should return commits with failed tasks but with `bringup: true` label', () async {
      buildStatusService = FakeBuildStatusService(
        commitStatuses: <CommitStatus>[
          CommitStatus(commit1, <Stage>[stageFailed]),
          CommitStatus(commit2, <Stage>[stageFailedFlaky])
        ],
      );
      handler = GetGreenCommits(
        config: config,
        datastoreProvider: (DatastoreDB db) => DatastoreService(config.db, 5),
        buildStatusProvider: (_) => buildStatusService,
      );

      final List<String?> result = (await decodeHandlerBody())!;

      expect(result.length, 1);
      expect(result, <String>[commit2.sha!]);
    });

    test('should return commits with both flaky and succeeded tasks', () async {
      buildStatusService = FakeBuildStatusService(
        commitStatuses: <CommitStatus>[
          CommitStatus(commit1, <Stage>[stageOneSucceed, stageMultipleSucceed]),
          CommitStatus(commit2, <Stage>[stageOneSucceed, stageFailedFlaky])
        ],
      );
      handler = GetGreenCommits(
        config: config,
        datastoreProvider: (DatastoreDB db) => DatastoreService(config.db, 5),
        buildStatusProvider: (_) => buildStatusService,
      );

      final List<String?> result = (await decodeHandlerBody())!;

      expect(result.length, 2);
      expect(result, <String>[
        commit2.sha!,
        commit1.sha!,
      ]);
    });

    test('should return branched commits', () async {
      buildStatusService = FakeBuildStatusService(
        commitStatuses: <CommitStatus>[
          CommitStatus(commitBranched, <Stage>[stageOneSucceed]),
        ],
      );
      tester.request = FakeHttpRequest(
        queryParametersValue: <String, String>{
          GetGreenCommits.kBranchParam: commitBranched.branch!,
        },
      );
      handler = GetGreenCommits(
        config: config,
        datastoreProvider: (DatastoreDB db) => DatastoreService(config.db, 5),
        buildStatusProvider: (_) => buildStatusService,
      );

      final List<String?> result = (await decodeHandlerBody())!;

      expect(result, <String>[
        commitBranched.sha!,
      ]);
    });
  });
}
