// 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_dashboard/build_dashboard_page.dart';
import 'package:flutter_dashboard/model/branch.pb.dart';
import 'package:flutter_dashboard/model/build_status_response.pb.dart';
import 'package:flutter_dashboard/model/commit_status.pb.dart';
import 'package:flutter_dashboard/service/cocoon.dart';
import 'package:flutter_dashboard/service/dev_cocoon.dart';
import 'package:flutter_dashboard/service/google_authentication.dart';
import 'package:flutter_dashboard/state/build.dart';
import 'package:flutter_dashboard/widgets/error_brook_watcher.dart';
import 'package:flutter_dashboard/widgets/sign_in_button.dart';
import 'package:flutter_dashboard/widgets/state_provider.dart';
import 'package:flutter_dashboard/widgets/task_box.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';

import 'utils/fake_build.dart';
import 'utils/fake_google_account.dart';
import 'utils/golden.dart';
import 'utils/mocks.dart';
import 'utils/output.dart';
import 'utils/task_icons.dart';

void main() {
  final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
  late MockGoogleSignInService fakeAuthService;

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

  setUp(() {
    binding.window.devicePixelRatioTestValue = 1.0;
    binding.window.physicalSizeTestValue = const Size(1080, 2280);
    // device pixel ratio of 1.0 works well on web app and emulator
    // If not set, flutter test uses a Pixel 4 device pixel ratio of roughly 2.75, which doesn't quite work
    // I am using the default settings of Pixel 4 in this test, as referenced in the link below
    // https://android.googlesource.com/platform/external/qemu/+/b5b78438ae9ff3b90aafdab0f4f25585affc22fb/android/avd/hardware-properties.ini
    fakeAuthService = MockGoogleSignInService();
    when(fakeAuthService.isAuthenticated).thenAnswer((_) => Future<bool>.value(true));
    when(fakeAuthService.user).thenReturn(FakeGoogleSignInAccount());
  });

  testWidgets('shows sign in button', (WidgetTester tester) async {
    final MockCocoonService fakeCocoonService = MockCocoonService();
    throwOnMissingStub(fakeCocoonService);
    when(fakeCocoonService.fetchFlutterBranches()).thenAnswer((_) => Completer<CocoonResponse<List<Branch>>>().future);
    when(fakeCocoonService.fetchRepos()).thenAnswer((_) => Completer<CocoonResponse<List<String>>>().future);
    when(
      fakeCocoonService.fetchCommitStatuses(
        branch: anyNamed('branch'),
        repo: anyNamed('repo'),
      ),
    ).thenAnswer((_) => Completer<CocoonResponse<List<CommitStatus>>>().future);
    when(
      fakeCocoonService.fetchTreeBuildStatus(
        branch: anyNamed('branch'),
        repo: anyNamed('repo'),
      ),
    ).thenAnswer((_) => Completer<CocoonResponse<BuildStatusResponse>>().future);

    final BuildState buildState = BuildState(
      cocoonService: fakeCocoonService,
      authService: fakeAuthService,
    );

    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 settings button', (WidgetTester tester) async {
    final BuildState fakeBuildState = FakeBuildState()..authService = fakeAuthService;

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

    expect(find.byIcon(Icons.settings), findsOneWidget);
  });

  testWidgets('shows file a bug button', (WidgetTester tester) async {
    final BuildState fakeBuildState = FakeBuildState()..authService = fakeAuthService;

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

    expect(find.byIcon(Icons.bug_report), findsOneWidget);
  });

  testWidgets('shows key button & legend', (WidgetTester tester) async {
    final BuildState fakeBuildState = FakeBuildState()..authService = fakeAuthService;

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

    expect(find.byIcon(Icons.info_outline), findsOneWidget);

    await tester.tap(find.byIcon(Icons.info_outline));
    await tester.pump();

    for (final String status in TaskBox.statusColor.keys) {
      expect(find.text(status), findsOneWidget);
    }
    expect(find.text('Flaky'), findsOneWidget);
    expect(find.text('Ran more than once'), findsOneWidget);
  });

  testWidgets('shows branch and repo dropdown button when screen is decently large', (WidgetTester tester) async {
    final BuildState fakeBuildState = FakeBuildState()..authService = fakeAuthService;

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

    expect(find.byType(dropdownButtonType), findsNWidgets(2));

    expect(find.text('repo: '), findsOneWidget);
    expect((tester.widget(find.byKey(const Key('repo dropdown'))) as DropdownButton).value, equals('flutter'));

    expect(find.text('branch: '), findsOneWidget);
    expect((tester.widget(find.byKey(const Key('branch dropdown'))) as DropdownButton).value, equals('master'));
  });

  testWidgets('shows vacuum github commits button', (WidgetTester tester) async {
    final BuildState fakeBuildState = FakeBuildState()..authService = fakeAuthService;

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

    // Open settings overlay
    await tester.tap(find.byIcon(Icons.settings));
    await tester.pump();

    expect(find.text('Vacuum GitHub Commits'), findsOneWidget);
  });

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

    await tester.pumpWidget(
      MaterialApp(
        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[850]);
    expect(tester, meetsGuideline(textContrastGuideline));
  });

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

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData.dark(),
        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[850]);
    expect(tester, meetsGuideline(textContrastGuideline));
  });

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

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

    // Verify the "Tree is Closed" message is wrapped in a [Tooltip].
    final Finder tooltipFinder = find.byWidgetPredicate((Widget widget) {
      return widget is Tooltip && (widget.message?.contains('Tree is Closed') ?? false);
    });
    expect(tooltipFinder, findsOneWidget);

    final AppBar appbarWidget = find.byType(AppBar).evaluate().first.widget as AppBar;
    expect(appbarWidget.backgroundColor, Colors.red);
    expect(tester, meetsGuideline(textContrastGuideline));
  });

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

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

    // Verify the "Tree is Closed" message is wrapped in a [Tooltip].
    final Finder tooltipFinder = find.byWidgetPredicate((Widget widget) {
      return widget is Tooltip && (widget.message?.contains('Tree is Closed') ?? false);
    });
    expect(tooltipFinder, findsOneWidget);

    final AppBar appbarWidget = find.byType(AppBar).evaluate().first.widget as AppBar;
    expect(appbarWidget.backgroundColor, Colors.red[800]);
    expect(tester, meetsGuideline(textContrastGuideline));
  });

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

    await tester.pumpWidget(
      MaterialApp(
        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, Colors.green);
    expect(tester, meetsGuideline(textContrastGuideline));
  });

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

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData.dark(),
        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, Colors.green[800]);
    expect(tester, meetsGuideline(textContrastGuideline));
  });

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

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

    expect(lastError, isNull);

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

  testWidgets('TaskGridContainer with default Settings property sheet', (WidgetTester tester) async {
    await precacheTaskIcons(tester);
    final BuildState buildState = BuildState(
      cocoonService: DevelopmentCocoonService(DateTime.utc(2020)),
      authService: fakeAuthService,
    );
    void listener1() {}
    buildState.addListener(listener1);

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

    await tester.tap(find.byIcon(Icons.settings));
    await tester.pump();

    await expectGoldenMatches(find.byType(BuildDashboardPage), 'build_dashboard.defaultPropertySheet.png');
    expect(tester, meetsGuideline(textContrastGuideline));

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

  testWidgets('TaskGridContainer with default Settings property sheet, dark mode', (WidgetTester tester) async {
    await precacheTaskIcons(tester);
    final BuildState buildState = BuildState(
      cocoonService: DevelopmentCocoonService(DateTime.utc(2020)),
      authService: fakeAuthService,
    );
    void listener1() {}
    buildState.addListener(listener1);

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

    await tester.tap(find.byIcon(Icons.settings));
    await tester.pump();

    await expectGoldenMatches(find.byType(BuildDashboardPage), 'build_dashboard.defaultPropertySheet.dark.png');
    expect(tester, meetsGuideline(textContrastGuideline));

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

  testWidgets('ensure smooth transition between invalid states', (WidgetTester tester) async {
    final BuildState fakeBuildState = FakeBuildState()..authService = fakeAuthService;
    BuildDashboardPage controlledBuildDashboardPage = const BuildDashboardPage(
      queryParameters: {
        'repo': 'flutter',
        'branch': 'flutter-release',
      },
    );

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

    expect(find.byType(dropdownButtonType), findsNWidgets(2));
    // simulate a url request, which retriggers a rebuild of the widget
    controlledBuildDashboardPage = const BuildDashboardPage(
      queryParameters: {
        'repo': 'engine',
      },
    );
    expect(
      (tester.widget(find.byKey(const Key('branch dropdown'))) as DropdownButton).value,
      equals('flutter-release'),
    ); //invalid state: engine + flutter-release
    await tester.pump(); //an invalid state will generate delayed network responses

    //if a delayed network request come in, from a previous invalid state: cocoon + engine - release, no exceptions should be raised
    controlledBuildDashboardPage = const BuildDashboardPage(
      queryParameters: {
        'repo': 'cocoon',
        'branch': 'engine-release',
      },
    );
  });

  testWidgets('shows branch and repo dropdown button in settings when screen is small', (WidgetTester tester) async {
    binding.window.physicalSizeTestValue = const Size(500, 500);
    binding.window.devicePixelRatioTestValue = 1.0;
    final BuildState fakeBuildState = FakeBuildState()..authService = fakeAuthService;

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

    expect(find.byType(dropdownButtonType), findsNothing);

    await tester.tap(find.byIcon(Icons.settings));
    await tester.pump();

    expect(find.byType(dropdownButtonType), findsNWidgets(2));
  });
}
