// 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/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';

import 'package:cocoon_service/protos.dart';

import 'package:app_flutter/build_dashboard_page.dart';
import 'package:app_flutter/main.dart' as app show lightTheme;
import 'package:app_flutter/service/cocoon.dart';
import 'package:app_flutter/service/google_authentication.dart';
import 'package:app_flutter/state/build.dart';
import 'package:app_flutter/widgets/error_brook_watcher.dart';
import 'package:app_flutter/widgets/sign_in_button.dart';
import 'package:app_flutter/widgets/state_provider.dart';

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

void main() {
  testWidgets('shows sign in button', (WidgetTester tester) async {
    final BuildState buildState = BuildState(
      cocoonService: MockCocoonService(),
      authService: MockGoogleSignInService(),
    );

    throwOnMissingStub(buildState.cocoonService as Mock);
    when(buildState.cocoonService.fetchFlutterBranches())
        .thenAnswer((_) => Completer<CocoonResponse<List<String>>>().future);
    when(buildState.cocoonService.fetchCommitStatuses(branch: anyNamed('branch')))
        .thenAnswer((_) => Completer<CocoonResponse<List<CommitStatus>>>().future);
    when(buildState.cocoonService.fetchTreeBuildStatus(branch: anyNamed('branch')))
        .thenAnswer((_) => Completer<CocoonResponse<bool>>().future);

    await tester.pumpWidget(
      MaterialApp(
        home: ValueProvider<BuildState>(
          value: buildState,
          child: ValueProvider<GoogleSignInService>(
            value: buildState.authService,
            child: const BuildDashboardPage(),
          ),
        ),
      ),
    );
    expect(find.byType(SignInButton), findsOneWidget);

    await tester.pumpWidget(Container());
    buildState.dispose();
  });

  testWidgets('shows branch dropdown button', (WidgetTester tester) async {
    final BuildState fakeBuildState = FakeBuildState();

    await tester.pumpWidget(
      MaterialApp(
        home: ValueProvider<BuildState>(
          value: fakeBuildState,
          child: ValueProvider<GoogleSignInService>(
            value: fakeBuildState.authService,
            child: const BuildDashboardPage(),
          ),
        ),
      ),
    );

    final Type dropdownButtonType = DropdownButton<String>(
      onChanged: (_) {},
      items: const <DropdownMenuItem<String>>[],
    ).runtimeType;
    expect(find.byType(dropdownButtonType), findsOneWidget);
  });

  testWidgets('shows loading when fetch tree status is null', (WidgetTester tester) async {
    final BuildState fakeBuildState = FakeBuildState()..isTreeBuilding = null;

    await tester.pumpWidget(
      MaterialApp(
        theme: app.lightTheme,
        home: ValueProvider<BuildState>(
          value: fakeBuildState,
          child: ValueProvider<GoogleSignInService>(
            value: fakeBuildState.authService,
            child: const BuildDashboardPage(),
          ),
        ),
      ),
    );

    expect(find.text('Loading...'), findsOneWidget);

    final AppBar appbarWidget = find.byType(AppBar).evaluate().first.widget as AppBar;
    expect(appbarWidget.backgroundColor, Colors.grey);
  });

  testWidgets('shows tree closed when fetch tree status is false', (WidgetTester tester) async {
    final BuildState fakeBuildState = FakeBuildState()..isTreeBuilding = false;

    await tester.pumpWidget(
      MaterialApp(
        theme: app.lightTheme,
        home: ValueProvider<BuildState>(
          value: fakeBuildState,
          child: ValueProvider<GoogleSignInService>(
            value: fakeBuildState.authService,
            child: const BuildDashboardPage(),
          ),
        ),
      ),
    );

    expect(find.text('Tree is Closed'), findsOneWidget);

    final AppBar appbarWidget = find.byType(AppBar).evaluate().first.widget as AppBar;
    expect(appbarWidget.backgroundColor, app.lightTheme.errorColor);
  });

  testWidgets('shows tree open when fetch tree status is true', (WidgetTester tester) async {
    final BuildState fakeBuildState = FakeBuildState()..isTreeBuilding = true;

    await tester.pumpWidget(
      MaterialApp(
        theme: app.lightTheme,
        home: ValueProvider<BuildState>(
          value: fakeBuildState,
          child: ValueProvider<GoogleSignInService>(
            value: fakeBuildState.authService,
            child: const BuildDashboardPage(),
          ),
        ),
      ),
    );

    expect(find.text('Tree is Open'), findsOneWidget);

    final AppBar appbarWidget = find.byType(AppBar).evaluate().first.widget as AppBar;
    expect(appbarWidget.backgroundColor, app.lightTheme.appBarTheme.color);
  });

  testWidgets('show error snackbar when error occurs', (WidgetTester tester) async {
    String lastError;
    final FakeBuildState buildState = FakeBuildState()..errors.addListener((String message) => lastError = message);

    await tester.pumpWidget(
      MaterialApp(
        home: ValueProvider<BuildState>(
          value: buildState,
          child: ValueProvider<GoogleSignInService>(
            value: buildState.authService,
            child: const BuildDashboardPage(),
          ),
        ),
      ),
    );

    expect(find.text(lastError), findsNothing);

    // propagate the error message
    await checkOutput(
      block: () async {
        buildState.errors.send('ERROR');
      },
      output: <String>[
        'ERROR',
      ],
    );
    await tester.pump();

    await tester.pump(const Duration(milliseconds: 750)); // open animation for snackbar

    expect(find.text(lastError), findsOneWidget);

    // Snackbar message should go away after its duration
    await tester.pump(ErrorBrookWatcher.errorSnackbarDuration); // wait the duration
    await tester.pump(); // schedule animation
    await tester.pump(const Duration(milliseconds: 1500)); // close animation

    expect(find.text(lastError), findsNothing);
  });
}
