// Copyright (c) 2019 The Chromium 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_test/flutter_test.dart';
import 'package:mockito/mockito.dart';

import 'package:cocoon_service/protos.dart' show Agent;

import 'package:app_flutter/service/cocoon.dart';
import 'package:app_flutter/service/fake_cocoon.dart';
import 'package:app_flutter/service/google_authentication.dart';
import 'package:app_flutter/state/agent.dart';

void main() {
  group('AgentState', () {
    AgentState agentState;
    MockCocoonService mockService;
    MockGoogleSignInService mockSignInService;

    setUp(() {
      mockSignInService = MockGoogleSignInService();
      mockService = MockCocoonService();
      agentState = AgentState(
          cocoonServiceValue: mockService, authServiceValue: mockSignInService);

      when(mockService.fetchAgentStatuses()).thenAnswer((_) =>
          Future<CocoonResponse<List<Agent>>>.value(
              CocoonResponse<List<Agent>>()..data = <Agent>[Agent()]));
    });

    tearDown(() {
      clearInteractions(mockSignInService);
      clearInteractions(mockService);
    });

    testWidgets('timer should periodically fetch updates',
        (WidgetTester tester) async {
      agentState.startFetchingStateUpdates();

      // startFetching immediately starts fetching results
      verify(mockService.fetchAgentStatuses()).called(1);

      // Periodic timers don't necessarily run at the same time in each interval.
      // We double the refreshRate to gurantee a call would have been made.
      await tester.pump(agentState.refreshRate * 2);
      verify(mockService.fetchAgentStatuses()).called(greaterThan(1));

      // Tear down fails to cancel the timer before the test is over
      agentState.dispose();
    });

    testWidgets('multiple start updates should not change the timer',
        (WidgetTester tester) async {
      agentState.startFetchingStateUpdates();
      final Timer refreshTimer = agentState.refreshTimer;

      // This second run should not change the refresh timer
      agentState.startFetchingStateUpdates();

      expect(refreshTimer, equals(agentState.refreshTimer));

      // Since startFetching sends out requests on start, we need to wait
      // for them to finish before disposing of the state.
      await tester.pumpAndSettle();

      // Tear down fails to cancel the timer before the test is over
      agentState.dispose();
    });

    testWidgets('fetching agents error should not delete previous data',
        (WidgetTester tester) async {
      agentState.startFetchingStateUpdates();

      // Periodic timers don't necessarily run at the same time in each interval.
      // We double the refreshRate to gurantee a call would have been made.
      await tester.pump(agentState.refreshRate * 2);
      final List<Agent> originalData = agentState.agents;

      when(mockService.fetchAgentStatuses()).thenAnswer((_) =>
          Future<CocoonResponse<List<Agent>>>.value(
              CocoonResponse<List<Agent>>()..error = 'error'));

      await tester.pump(agentState.refreshRate * 2);
      verify(mockService.fetchAgentStatuses()).called(greaterThan(1));

      expect(agentState.agents, originalData);
      expect(
          agentState.errors.message, AgentState.errorMessageFetchingStatuses);

      // Tear down fails to cancel the timer before the test is over
      agentState.dispose();
    });

    test('authorize agent calls cocoon service', () async {
      when(mockService.authorizeAgent(any, any))
          .thenAnswer((_) async => CocoonResponse<String>()..data = 'abc123');
      verifyNever(mockService.authorizeAgent(any, any));

      await agentState.authorizeAgent(Agent());

      verify(mockService.authorizeAgent(any, any)).called(1);
    });

    test('reserve task calls cocoon service', () async {
      verifyNever(mockService.reserveTask(any, any));

      await agentState.reserveTask(Agent());

      verify(mockService.reserveTask(any, any)).called(1);
    });

    test('auth functions call auth service', () async {
      verifyNever(mockSignInService.signIn());
      verifyNever(mockSignInService.signOut());

      await agentState.signIn();
      verify(mockSignInService.signIn()).called(1);
      verifyNever(mockSignInService.signOut());

      await agentState.signOut();
      verify(mockSignInService.signOut()).called(1);
    });
  });
}

/// CocoonService for checking interactions.
class MockCocoonService extends Mock implements FakeCocoonService {}

/// GoogleAuthenticationService for checking interactions.
class MockGoogleSignInService extends Mock implements GoogleSignInService {}
