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

void main() {
  testWidgets('CustomTransitionPage builds its child using transitionsBuilder',
      (WidgetTester tester) async {
    const HomeScreen child = HomeScreen();
    final CustomTransitionPage<void> transition = CustomTransitionPage<void>(
      transitionsBuilder: expectAsync4((_, __, ___, Widget child) => child),
      child: child,
    );
    final GoRouter router = GoRouter(
      routes: <GoRoute>[
        GoRoute(
          path: '/',
          pageBuilder: (_, __) => transition,
        ),
      ],
    );
    await tester.pumpWidget(
      MaterialApp.router(
        routerConfig: router,
        title: 'GoRouter Example',
      ),
    );
    expect(find.byWidget(child), findsOneWidget);
  });

  testWidgets('NoTransitionPage does not apply any transition',
      (WidgetTester tester) async {
    final ValueNotifier<bool> showHomeValueNotifier =
        ValueNotifier<bool>(false);
    await tester.pumpWidget(
      MaterialApp(
        home: ValueListenableBuilder<bool>(
          valueListenable: showHomeValueNotifier,
          builder: (_, bool showHome, __) {
            return Navigator(
              pages: <Page<void>>[
                const NoTransitionPage<void>(
                  child: LoginScreen(),
                ),
                if (showHome)
                  const NoTransitionPage<void>(
                    child: HomeScreen(),
                  ),
              ],
              onPopPage: (Route<dynamic> route, dynamic result) {
                return route.didPop(result);
              },
            );
          },
        ),
      ),
    );

    final Finder homeScreenFinder = find.byType(HomeScreen);

    showHomeValueNotifier.value = true;
    await tester.pump();
    final Offset homeScreenPositionInTheMiddleOfAddition =
        tester.getTopLeft(homeScreenFinder);
    await tester.pumpAndSettle();
    final Offset homeScreenPositionAfterAddition =
        tester.getTopLeft(homeScreenFinder);

    showHomeValueNotifier.value = false;
    await tester.pump();
    final Offset homeScreenPositionInTheMiddleOfRemoval =
        tester.getTopLeft(homeScreenFinder);
    await tester.pumpAndSettle();

    expect(
      homeScreenPositionInTheMiddleOfAddition,
      homeScreenPositionAfterAddition,
    );
    expect(
      homeScreenPositionAfterAddition,
      homeScreenPositionInTheMiddleOfRemoval,
    );
  });

  testWidgets('Dismiss a screen by tapping a modal barrier',
      (WidgetTester tester) async {
    const ValueKey<String> homeKey = ValueKey<String>('home');
    const ValueKey<String> dismissibleModalKey =
        ValueKey<String>('dismissibleModal');

    final GoRouter router = GoRouter(
      routes: <GoRoute>[
        GoRoute(
          path: '/',
          builder: (_, __) => const HomeScreen(key: homeKey),
        ),
        GoRoute(
          path: '/dismissible-modal',
          pageBuilder: (_, GoRouterState state) => CustomTransitionPage<void>(
            key: state.pageKey,
            barrierDismissible: true,
            transitionsBuilder: (_, __, ___, Widget child) => child,
            child: const DismissibleModal(key: dismissibleModalKey),
          ),
        ),
      ],
    );
    await tester.pumpWidget(MaterialApp.router(routerConfig: router));
    expect(find.byKey(homeKey), findsOneWidget);
    router.push('/dismissible-modal');
    await tester.pumpAndSettle();
    expect(find.byKey(dismissibleModalKey), findsOneWidget);
    await tester.tapAt(const Offset(50, 50));
    await tester.pumpAndSettle();
    expect(find.byKey(homeKey), findsOneWidget);
  });
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text('HomeScreen'),
      ),
    );
  }
}

class LoginScreen extends StatelessWidget {
  const LoginScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text('LoginScreen'),
      ),
    );
  }
}

class DismissibleModal extends StatelessWidget {
  const DismissibleModal({super.key});

  @override
  Widget build(BuildContext context) {
    return const SizedBox(
      width: 200,
      height: 200,
      child: Center(child: Text('Dismissible Modal')),
    );
  }
}
