// Copyright 2013 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 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:go_router/src/go_router_cupertino.dart';

import 'error_screen_helpers.dart';

void main() {
  group('isCupertinoApp', () {
    testWidgets('returns [true] when CupertinoApp is present',
        (WidgetTester tester) async {
      final GlobalKey<_DummyStatefulWidgetState> key =
          GlobalKey<_DummyStatefulWidgetState>();
      await tester.pumpWidget(
        CupertinoApp(
          home: DummyStatefulWidget(key: key),
        ),
      );
      final bool isCupertino = isCupertinoApp(key.currentContext! as Element);
      expect(isCupertino, true);
    });

    testWidgets('returns [false] when MaterialApp is present',
        (WidgetTester tester) async {
      final GlobalKey<_DummyStatefulWidgetState> key =
          GlobalKey<_DummyStatefulWidgetState>();
      await tester.pumpWidget(
        MaterialApp(
          home: DummyStatefulWidget(key: key),
        ),
      );
      final bool isCupertino = isCupertinoApp(key.currentContext! as Element);
      expect(isCupertino, false);
    });
  });

  test('pageBuilderForCupertinoApp creates a [CupertinoPage] accordingly', () {
    final UniqueKey key = UniqueKey();
    const String name = 'name';
    const String arguments = 'arguments';
    const String restorationId = 'restorationId';
    const DummyStatefulWidget child = DummyStatefulWidget();
    final CupertinoPage<void> page = pageBuilderForCupertinoApp(
      key: key,
      name: name,
      arguments: arguments,
      restorationId: restorationId,
      child: child,
    );
    expect(page.key, key);
    expect(page.name, name);
    expect(page.arguments, arguments);
    expect(page.restorationId, restorationId);
    expect(page.child, child);
  });

  group('GoRouterCupertinoErrorScreen', () {
    testWidgets(
      'shows "page not found" by default',
      testPageNotFound(
        widget: const CupertinoApp(
          home: GoRouterCupertinoErrorScreen(null),
        ),
      ),
    );

    final Exception exception = Exception('Something went wrong!');
    testWidgets(
      'shows the exception message when provided',
      testPageShowsExceptionMessage(
        exception: exception,
        widget: CupertinoApp(
          home: GoRouterCupertinoErrorScreen(exception),
        ),
      ),
    );

    testWidgets(
      'clicking the CupertinoButton should redirect to /',
      testClickingTheButtonRedirectsToRoot(
        buttonFinder: find.byType(CupertinoButton),
        appRouterBuilder: cupertinoAppRouterBuilder,
        widget: const CupertinoApp(
          home: GoRouterCupertinoErrorScreen(null),
        ),
      ),
    );
  });
}

class DummyStatefulWidget extends StatefulWidget {
  const DummyStatefulWidget({Key? key}) : super(key: key);

  @override
  State<DummyStatefulWidget> createState() => _DummyStatefulWidgetState();
}

class _DummyStatefulWidgetState extends State<DummyStatefulWidget> {
  @override
  Widget build(BuildContext context) => Container();
}
