// 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:async';

import 'package:flutter_dashboard/model/branch.pb.dart';
import 'package:flutter_dashboard/model/build_status_response.pb.dart';
import 'package:flutter_dashboard/model/commit.pb.dart';
import 'package:flutter_dashboard/model/commit_status.pb.dart';
import 'package:flutter_dashboard/model/key.pb.dart';
import 'package:flutter_dashboard/service/cocoon.dart';
import 'package:flutter_dashboard/service/google_authentication.dart';
import 'package:flutter_dashboard/state/build.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:mockito/mockito.dart';

import '../utils/mocks.dart';
import '../utils/output.dart';

void main() {
  const String defaultBranch = 'master';

  group('BuildState', () {
    late MockCocoonService mockCocoonService;
    late CommitStatus setupCommitStatus;

    setUp(() {
      mockCocoonService = MockCocoonService();
      setupCommitStatus = _createCommitStatus('setup');

      when(mockCocoonService.fetchCommitStatuses(branch: anyNamed('branch'), repo: anyNamed('repo')))
          .thenAnswer((dynamic _) async => CocoonResponse<List<CommitStatus>>.data(<CommitStatus>[setupCommitStatus]));
      when(mockCocoonService.fetchTreeBuildStatus(branch: anyNamed('branch'), repo: anyNamed('repo'))).thenAnswer(
          (_) async =>
              CocoonResponse<BuildStatusResponse>.data(BuildStatusResponse()..buildStatus = EnumBuildStatus.success));
      when(mockCocoonService.fetchRepos())
          .thenAnswer((_) async => const CocoonResponse<List<String>>.data(<String>['flutter']));
      when(mockCocoonService.fetchFlutterBranches()).thenAnswer((_) async => CocoonResponse<List<Branch>>.data(<Branch>[
            Branch()
              ..branch = defaultBranch
              ..repository = 'flutter'
          ]));
    });

    tearDown(() {
      clearInteractions(mockCocoonService);
    });

    testWidgets('start calls fetch branches', (WidgetTester tester) async {
      final BuildState buildState = BuildState(
        authService: MockGoogleSignInService(),
        cocoonService: mockCocoonService,
      );
      void listener() {}
      buildState.addListener(listener);

      // startFetching immediately starts fetching results
      verify(await mockCocoonService.fetchFlutterBranches()).called(1);

      buildState.dispose();
    });

    testWidgets('timer should periodically fetch updates', (WidgetTester tester) async {
      final BuildState buildState = BuildState(
        authService: MockGoogleSignInService(),
        cocoonService: mockCocoonService,
      );
      verifyNever(mockCocoonService.fetchCommitStatuses(branch: anyNamed('branch'), repo: anyNamed('repo')));

      void listener() {}
      buildState.addListener(listener);

      // startFetching immediately starts fetching results
      verify(await mockCocoonService.fetchCommitStatuses(branch: defaultBranch, repo: 'flutter')).called(1);

      verifyNever(mockCocoonService.fetchCommitStatuses(branch: anyNamed('branch'), repo: anyNamed('repo')));
      await tester.pump(buildState.refreshRate! * 2);
      verify(await mockCocoonService.fetchCommitStatuses(branch: defaultBranch, repo: 'flutter')).called(2);

      buildState.dispose();
    });

    testWidgets('updateCurrentRepoBranch should make old updates stale', (WidgetTester tester) async {
      final BuildState buildState = BuildState(
        authService: MockGoogleSignInService(),
        cocoonService: mockCocoonService,
      );

      verifyNever(mockCocoonService.fetchCommitStatuses(branch: anyNamed('branch'), repo: anyNamed('repo')));
      expect(buildState.statuses, isEmpty);

      void listener() {}
      // This invokes startFetchUpdates
      buildState.addListener(listener);

      // startFetching immediately starts fetching results (and returns fake data)
      verify(await mockCocoonService.fetchCommitStatuses(branch: defaultBranch, repo: 'flutter')).called(1);
      verifyNever(mockCocoonService.fetchCommitStatuses(branch: 'main', repo: 'cocoon'));
      expect(buildState.statuses, isNotEmpty);
      // Start another Timer.periodic async call
      await tester.pump();
      // Change the repo to Cocoon while a timer is set, and Cocoon is not expected to return data
      buildState.updateCurrentRepoBranch('cocoon', 'main');
      expect(buildState.statuses, isEmpty);
      await untilCalled(mockCocoonService.fetchCommitStatuses(branch: defaultBranch, repo: 'flutter'));
      expect(buildState.statuses, isEmpty);

      buildState.dispose();
    });

    test('multiple start updates should not change the timer', () {
      final BuildState buildState = BuildState(
        authService: MockGoogleSignInService(),
        cocoonService: mockCocoonService,
      );
      void listener1() {}
      buildState.addListener(listener1);

      // Another listener shouldn't change the timer.
      final Timer? refreshTimer = buildState.refreshTimer;
      void listener2() {}
      buildState.addListener(listener2);
      expect(buildState.refreshTimer, equals(refreshTimer));

      // Removing a listener shouldn't change the timer.
      buildState.removeListener(listener1);
      expect(buildState.refreshTimer, equals(refreshTimer));

      // Removing both listeners should cancel the timer.
      buildState.removeListener(listener2);
      expect(buildState.refreshTimer, isNull);

      // A new listener now should change the timer.
      buildState.addListener(listener1);
      expect(buildState.refreshTimer, isNot(isNull));
      expect(buildState.refreshTimer, isNot(equals(refreshTimer)));
    });

    testWidgets('statuses error should not delete previous statuses data', (WidgetTester tester) async {
      String? lastError;
      final BuildState buildState = BuildState(
        authService: MockGoogleSignInService(),
        cocoonService: mockCocoonService,
      )..errors.addListener((String message) => lastError = message);
      verifyNever(mockCocoonService.fetchTreeBuildStatus(branch: anyNamed('branch'), repo: anyNamed('repo')));
      verifyNever(mockCocoonService.fetchCommitStatuses(branch: anyNamed('branch'), repo: anyNamed('repo')));
      void listener() {}
      buildState.addListener(listener);
      verify(mockCocoonService.fetchTreeBuildStatus(branch: defaultBranch, repo: 'flutter')).called(1);
      verify(mockCocoonService.fetchCommitStatuses(branch: defaultBranch, repo: 'flutter')).called(1);
      await tester.pump();
      final List<CommitStatus> originalData = buildState.statuses;
      verifyNever(mockCocoonService.fetchTreeBuildStatus(branch: anyNamed('branch'), repo: anyNamed('repo')));
      verifyNever(mockCocoonService.fetchCommitStatuses(branch: anyNamed('branch'), repo: anyNamed('repo')));

      when(mockCocoonService.fetchCommitStatuses(branch: defaultBranch, repo: 'flutter')).thenAnswer(
        (_) =>
            Future<CocoonResponse<List<CommitStatus>>>.value(const CocoonResponse<List<CommitStatus>>.error('error')),
      );
      await checkOutput(
        block: () async {
          await tester.pump(buildState.refreshRate);
        },
        output: <String>[
          'An error occurred fetching build statuses from Cocoon: error',
        ],
      );
      verify(await mockCocoonService.fetchTreeBuildStatus(branch: defaultBranch, repo: 'flutter')).called(1);
      verify(await mockCocoonService.fetchCommitStatuses(branch: defaultBranch, repo: 'flutter')).called(1);

      expect(buildState.statuses, originalData);
      expect(lastError, startsWith(BuildState.errorMessageFetchingStatuses));

      buildState.dispose();
    });

    testWidgets('build status error should not delete previous build status data', (WidgetTester tester) async {
      String? lastError;
      final BuildState buildState = BuildState(
        authService: MockGoogleSignInService(),
        cocoonService: mockCocoonService,
      )..errors.addListener((String message) => lastError = message);
      verifyNever(mockCocoonService.fetchTreeBuildStatus(branch: anyNamed('branch'), repo: anyNamed('repo')));
      void listener() {}
      buildState.addListener(listener);

      await tester.pump();
      verify(mockCocoonService.fetchTreeBuildStatus(branch: defaultBranch, repo: 'flutter')).called(1);
      final bool? originalData = buildState.isTreeBuilding;
      verifyNever(mockCocoonService.fetchTreeBuildStatus(branch: anyNamed('branch'), repo: anyNamed('repo')));
      verifyNever(mockCocoonService.fetchTreeBuildStatus(branch: defaultBranch, repo: 'flutter'));

      when(mockCocoonService.fetchTreeBuildStatus(branch: defaultBranch, repo: 'flutter')).thenAnswer(
        (_) =>
            Future<CocoonResponse<BuildStatusResponse>>.value(const CocoonResponse<BuildStatusResponse>.error('error')),
      );
      await checkOutput(
        block: () async {
          await tester.pump(buildState.refreshRate);
        },
        output: <String>[
          'An error occurred fetching tree status from Cocoon: error',
        ],
      );
      verify(await mockCocoonService.fetchTreeBuildStatus(branch: defaultBranch, repo: 'flutter')).called(1);

      expect(buildState.isTreeBuilding, originalData);
      expect(lastError, startsWith(BuildState.errorMessageFetchingTreeStatus));

      buildState.dispose();
    });

    testWidgets('fetch more commit statuses appends', (WidgetTester tester) async {
      final BuildState buildState = BuildState(
        authService: MockGoogleSignInService(),
        cocoonService: mockCocoonService,
      );
      void listener() {}
      buildState.addListener(listener);

      await untilCalled(mockCocoonService.fetchCommitStatuses(branch: anyNamed('branch'), repo: anyNamed('repo')));

      expect(buildState.statuses, <CommitStatus?>[setupCommitStatus]);

      final CommitStatus statusA = _createCommitStatus('A');
      when(
        mockCocoonService.fetchCommitStatuses(
          lastCommitStatus: captureThat(isNotNull, named: 'lastCommitStatus'),
          branch: anyNamed('branch'),
          repo: anyNamed('repo'),
        ),
      ).thenAnswer((_) async => CocoonResponse<List<CommitStatus>>.data(<CommitStatus>[statusA]));

      await buildState.fetchMoreCommitStatuses();

      expect(buildState.statuses, <CommitStatus?>[setupCommitStatus, statusA]);

      await tester.pump(buildState.refreshRate);

      expect(buildState.statuses, <CommitStatus?>[setupCommitStatus, statusA]);
      expect(buildState.moreStatusesExist, true);

      buildState.dispose();
    });

    testWidgets('fetchMoreCommitStatuses returns empty stops fetching more', (WidgetTester tester) async {
      final BuildState buildState = BuildState(
        authService: MockGoogleSignInService(),
        cocoonService: mockCocoonService,
      );
      void listener() {}
      buildState.addListener(listener);

      await untilCalled(mockCocoonService.fetchCommitStatuses(branch: anyNamed('branch'), repo: anyNamed('repo')));

      expect(buildState.statuses, <CommitStatus?>[setupCommitStatus]);

      when(mockCocoonService.fetchCommitStatuses(
        lastCommitStatus: captureThat(isNotNull, named: 'lastCommitStatus'),
        branch: anyNamed('branch'),
        repo: anyNamed('repo'),
      )).thenAnswer((_) async => const CocoonResponse<List<CommitStatus>>.data(<CommitStatus>[]));

      await buildState.fetchMoreCommitStatuses();

      expect(buildState.statuses, <CommitStatus?>[setupCommitStatus]);
      expect(buildState.moreStatusesExist, false);

      buildState.dispose();
    });

    testWidgets('update branch resets build state data', (WidgetTester tester) async {
      // Only return statuses when on master branch
      when(
        mockCocoonService.fetchCommitStatuses(branch: 'master', repo: 'flutter'),
      ).thenAnswer(
        (_) => Future<CocoonResponse<List<CommitStatus>>>.value(
          CocoonResponse<List<CommitStatus>>.data(<CommitStatus>[setupCommitStatus]),
        ).then((CocoonResponse<List<CommitStatus>> value) => value),
      );
      // Mark tree green on master, red on dev
      when(mockCocoonService.fetchTreeBuildStatus(branch: 'master', repo: 'flutter')).thenAnswer((_) =>
          Future<CocoonResponse<BuildStatusResponse>>.value(
              CocoonResponse<BuildStatusResponse>.data(BuildStatusResponse()..buildStatus = EnumBuildStatus.success)));
      when(mockCocoonService.fetchTreeBuildStatus(branch: 'dev', repo: 'flutter')).thenAnswer((_) =>
          Future<CocoonResponse<BuildStatusResponse>>.value(
              CocoonResponse<BuildStatusResponse>.data(BuildStatusResponse()
                ..buildStatus = EnumBuildStatus.failure
                ..failingTasks.addAll(<String>['failing_task_1']))));
      final BuildState buildState = BuildState(
        authService: MockGoogleSignInService(),
        cocoonService: mockCocoonService,
      );
      void listener() {}
      buildState.addListener(listener);

      await untilCalled(mockCocoonService.fetchCommitStatuses(branch: 'master', repo: 'flutter'));
      expect(buildState.statuses, isNotEmpty);
      expect(buildState.isTreeBuilding, isNotNull);

      // With mockito, the fetch requests for data will finish immediately
      buildState.updateCurrentRepoBranch('flutter', 'dev');
      await tester.pump();

      expect(buildState.statuses, isEmpty);
      expect(buildState.isTreeBuilding, false);
      expect(buildState.moreStatusesExist, true);

      buildState.dispose();
    });
  });

  testWidgets('sign in functions call notify listener', (WidgetTester tester) async {
    final MockGoogleSignIn mockSignInPlugin = MockGoogleSignIn();
    when(mockSignInPlugin.signIn()).thenAnswer((_) => Future<GoogleSignInAccount?>.value(null));
    when(mockSignInPlugin.signOut()).thenAnswer((_) => Future<GoogleSignInAccount?>.value(null));
    when(mockSignInPlugin.signInSilently()).thenAnswer((_) => Future<GoogleSignInAccount?>.value(null));
    when(mockSignInPlugin.onCurrentUserChanged).thenAnswer((_) => Stream<GoogleSignInAccount?>.value(null));
    final MockCocoonService mockCocoonService = MockCocoonService();
    when(mockCocoonService.fetchFlutterBranches()).thenAnswer((_) => Completer<CocoonResponse<List<Branch>>>().future);
    when(mockCocoonService.fetchCommitStatuses(branch: anyNamed('branch'), repo: anyNamed('repo')))
        .thenAnswer((_) => Completer<CocoonResponse<List<CommitStatus>>>().future);
    when(mockCocoonService.fetchRepos()).thenAnswer((_) => Completer<CocoonResponse<List<String>>>().future);
    when(mockCocoonService.fetchTreeBuildStatus(branch: anyNamed('branch'), repo: anyNamed('repo')))
        .thenAnswer((_) => Completer<CocoonResponse<BuildStatusResponse>>().future);
    final GoogleSignInService signInService = GoogleSignInService(googleSignIn: mockSignInPlugin);
    final BuildState buildState = BuildState(
      cocoonService: mockCocoonService,
      authService: signInService, // TODO(ianh): Settle on one of these two for the whole codebase.
    );

    int callCount = 0;
    buildState.addListener(() => callCount += 1);

    await tester.pump(const Duration(seconds: 5));
    expect(callCount, 1);

    await signInService.signIn();
    expect(callCount, 2);

    await signInService.signOut();
    expect(callCount, 3);

    buildState.dispose();
  });
}

CommitStatus _createCommitStatus(
  String keyValue, {
  String branch = 'master',
  String repo = 'flutter',
}) {
  return CommitStatus()
    ..branch = branch
    ..commit = (Commit()
      // Author is set so we don't have to dig through all the nested fields
      // while debugging
      ..author = keyValue
      ..repository = 'flutter/$repo'
      ..key = (RootKey()..child = (Key()..name = keyValue)));
}
