// 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)));
}
