part of 'app_test.dart';

class MenuTest {
  static Future labels2AppbarConsistency() async {
    patrolWidgetTest(
      'As labels dos menuItems correspondem aos títulos das AppBars? (MultiLocais)',
      //
      (PatrolTester tester) async {
        $ = tester;
        $.tester.printToConsole(
            'Menu Test - As labels dos menuItems correspondem aos títulos das AppBars?');

        await _loggedWithMultiLocalsAccount();
        await $.pumpWidgetAndSettle(const App());

        await $.waitUntilVisible($(MenuStaggeredView));
        await $.waitUntilVisible($(LocalProfileComponentWidget));

        final PatrolFinder profileFinder =
            await $(#AsyncLocalProfileComponentWidget_InkWell)
                .waitUntilVisible();
        expect(profileFinder, findsOneWidget);

        await $(profileFinder) //
            .waitUntilVisible()
            .tap();

        final PatrolFinder bottomSheetFinder =
            await $(BottomArrowLinkedLocalsComponentWidget) //
                .waitUntilVisible();
        expect(bottomSheetFinder, findsOneWidget);

        final PatrolFinder listViewFinder = await $(bottomSheetFinder) //
            .$(ListView)
            .waitUntilVisible();
        expect(listViewFinder, findsOneWidget);

        final PatrolFinder entriesFinder = await $(listViewFinder) //
            .$(CardItemTemplateComponentWidget)
            .waitUntilVisible();
        expect(entriesFinder, findsWidgets);

        if (entriesFinder.evaluate().isNotEmpty) {
          await $(entriesFinder.first) //
              .waitUntilVisible()
              .tap(settlePolicy: SettlePolicy.noSettle);
        }

        await $.waitUntilVisible($(MenuStaggeredView));
        await $.waitUntilVisible($(LocalProfileComponentWidget));

        final List<String> routes = MenuEntry.entries
            .where((entry) => entry.key != 'FRE-HUB-LOGOUT')
            .map((entry) => entry.route)
            .toList();
        final List<String> titles = MenuEntry.entries
            .where((entry) => entry.key != 'FRE-HUB-LOGOUT')
            .map((entry) => entry.name)
            .toList();

        final LinkedHashMap<String, String> routesTitles = LinkedHashMap //
            .fromIterables(routes, titles);

        late String route;
        late String title;

        for (final entry in routesTitles.entries) {
          route = entry.key;
          title = entry.value;

          print('route: $route');
          print('title: $title');

          if (route == '/petsPage') continue;
          if (route == '/fastPassPage') continue;
          if (route == '/reservation') continue;
          if (route == '/petsOnThePropertyPage') continue;
          if (route == '/registerVisitorPage') continue;
          if (route == '/messageHistoryPage') continue;
          if (route == '/packageOrder') continue;
          if (route == '/provisionalHistoryPage') continue;
          if (route == '/scheduleCompleteVisitPage') continue;
          if (route == '/preferencesSettings') continue;

          ff.navigatorKey.currentContext!.go(route);

          final PatrolFinder appBar = await $(AppBar) //
              .waitUntilExists();
          final PatrolFinder titleAppBar = await appBar //
              .$(title)
              .waitUntilVisible();
          expect(titleAppBar, findsOneWidget);
        }
      },
    );
  }

  static Future containEntries() async {
    patrolWidgetTest(
      'HomeMenu contém seus itens? (MultiLocais)', //
      (PatrolTester tester) async {
        $ = tester;
        $.tester.printToConsole('Menu Test - HomeMenu contém seus itens?');

        await _loggedWithMultiLocalsAccount();
        await $.pumpWidgetAndSettle(const App());

        await $.waitUntilVisible($(MenuStaggeredView));
        await $.waitUntilVisible($(GridView));
        final PatrolFinder gridEntries = await $(GridView) //
            .$(ButtonMenuItem)
            .waitUntilVisible();
        expect(gridEntries, findsWidgets);

        final List<String?> menuKeys = gridEntries
            .evaluate()
            .map((element) {
              final key = element.widget.key;
              if (key is ValueKey<String>) {
                return key.value;
              }
              return null;
            })
            .where((key) => key != null)
            .toList();

        await $.pumpAndSettle();
        final List<MenuEntry> entries = MenuEntry.entries;
        await $.pumpAndSettle();
        final List<String> entriesKey = entries
            .where((entry) => entry.types.contains(MenuEntryType.Home))
            .map((entry) => entry.key)
            .toList();
        await $.pumpAndSettle();
        expect(entriesKey, containsAll(menuKeys));
      },
    );
    patrolWidgetTest(
      'HomeMenu contém seus itens? (MonoLocal)', //
      (PatrolTester tester) async {
        $ = tester;
        $.tester.printToConsole('Menu Test - HomeMenu contém seus itens?');

        await _loggedWithSomeoneLocalAccount();
        await $.pumpWidgetAndSettle(const App());

        await $.waitUntilVisible($(MenuStaggeredView));
        await $.waitUntilVisible($(GridView));
        final PatrolFinder gridEntries = await $(GridView) //
            .$(ButtonMenuItem)
            .waitUntilVisible();
        expect(gridEntries, findsWidgets);

        final List<String?> menuKeys = gridEntries
            .evaluate()
            .map((element) {
              final key = element.widget.key;
              if (key is ValueKey<String>) {
                return key.value;
              }
              return null;
            })
            .where((key) => key != null)
            .toList();

        await $.pumpAndSettle();
        final List<MenuEntry> entries = MenuEntry.entries;
        await $.pumpAndSettle();
        final List<String> entriesKey = entries
            .where((entry) => entry.types.contains(MenuEntryType.Home))
            .map((entry) => entry.key)
            .toList();
        await $.pumpAndSettle();
        expect(entriesKey, containsAll(menuKeys));
      },
    );

    patrolWidgetTest(
      'DrawerMenu contém seus itens? (MultiLocais)', //
      (PatrolTester tester) async {
        $ = tester;
        $.tester.printToConsole('Menu Test - DrawerMenu contém seus itens?');

        await _loggedWithMultiLocalsAccount();
        await $.pumpWidgetAndSettle(const App());

        await $.waitUntilVisible($(MenuStaggeredView));
        await $.waitUntilVisible($(GridView));
        final PatrolFinder gridEntries = await $(GridView) //
            .$(ButtonMenuItem)
            .waitUntilVisible();
        expect(gridEntries, findsWidgets);

        await $(Icons.menu_rounded).waitUntilVisible().tap();
        await $.waitUntilVisible($(ListView));
        final PatrolFinder listEntries = await $(ListView) //
            .$(CardMenuItem)
            .waitUntilVisible();
        expect(listEntries, findsWidgets);

        final List<String?> menuKeys = listEntries
            .evaluate()
            .map((element) {
              final key = element.widget.key;
              if (key is ValueKey<String>) {
                return key.value;
              }
              return null;
            })
            .where((key) => key != null)
            .toList();

        await $.pumpAndSettle();
        final List<MenuEntry> entries = MenuEntry.entries;
        await $.pumpAndSettle();
        final List<String> entriesKey = entries
            .where((entry) => entry.types.contains(MenuEntryType.Drawer))
            .map((entry) => entry.key)
            .toList();
        await $.pumpAndSettle();
        expect(entriesKey, containsAll(menuKeys));
        await Future.delayed(const Duration(milliseconds: 500));
      },
    );
    patrolWidgetTest(
      'DrawerMenu contém seus itens? (MonoLocal)', //
      (PatrolTester tester) async {
        $ = tester;
        $.tester.printToConsole('Menu Test - DrawerMenu contém seus itens?');

        await _loggedWithSomeoneLocalAccount();
        await $.pumpWidgetAndSettle(const App());

        await $.waitUntilVisible($(MenuStaggeredView));
        await $.waitUntilVisible($(GridView));
        final PatrolFinder gridEntries = await $(GridView) //
            .$(ButtonMenuItem)
            .waitUntilVisible();
        expect(gridEntries, findsWidgets);

        await $(Icons.menu_rounded).waitUntilVisible().tap();
        await $.waitUntilVisible($(ListView));
        final PatrolFinder listEntries = await $(ListView) //
            .$(CardMenuItem)
            .waitUntilVisible();
        expect(listEntries, findsWidgets);

        final List<String?> menuKeys = listEntries
            .evaluate()
            .map((element) {
              final key = element.widget.key;
              if (key is ValueKey<String>) {
                return key.value;
              }
              return null;
            })
            .where((key) => key != null)
            .toList();

        await $.pumpAndSettle();
        final List<MenuEntry> entries = MenuEntry.entries;
        await $.pumpAndSettle();
        final List<String> entriesKey = entries
            .where((entry) => entry.types.contains(MenuEntryType.Drawer))
            .map((entry) => entry.key)
            .toList();
        await $.pumpAndSettle();
        expect(entriesKey, containsAll(menuKeys));
        await Future.delayed(const Duration(milliseconds: 500));
      },
    );
  }

  static Future navToEntries() async {
    patrolWidgetTest(
      'Navegação entre items do Menu (MultiLocais)',
      (PatrolTester tester) async {
        $ = tester;
        $.tester.printToConsole('Menu Test - Navegação entre items do Menu');

        await _loggedWithMultiLocalsAccount();
        await $.pumpWidgetAndSettle(const App());
        await $.waitUntilVisible($(MenuStaggeredView));

        final PatrolFinder profile =
            $(const Key('AsyncLocalProfileComponentWidget_InkWell'));
        await $(profile)
            .waitUntilVisible()
            .tap(settlePolicy: SettlePolicy.noSettle);
        await $.waitUntilVisible($(BottomArrowLinkedLocalsComponentWidget));

        final PatrolFinder local = $('FRE ACCESS DEMO');
        await $(local)
            .waitUntilVisible()
            .tap(settlePolicy: SettlePolicy.noSettle);

        await $.waitUntilVisible($(MenuStaggeredView));

        final Finder gridView = find.byType(GridView);
        await $.waitUntilVisible(gridView);
        final Finder gridEntries = find.descendant(
          of: gridView,
          matching: find.byType(ButtonMenuItem),
        );
        await $.pumpAndSettle();
        expect(gridEntries, findsWidgets);
        final int gridEntriesCount = gridEntries.evaluate().length;
        await $.pumpAndSettle();

        for (int i = 0; i < gridEntriesCount; i++) {
          await $.waitUntilVisible(
            $(MenuStaggeredView),
            timeout: Duration(seconds: 1),
          );
          await $.waitUntilVisible(
            gridView,
            timeout: Duration(seconds: 1),
          );
          await $.waitUntilVisible(
            gridEntries.at(i),
            timeout: Duration(seconds: 1),
          );

          final ButtonMenuItem entry =
              $.tester.widget<ButtonMenuItem>(gridEntries.at(i));
          final Key? widgetKey = entry.key;
          expect(widgetKey, isNotNull);

          print('WIDGETKEY = $widgetKey');
          if (widgetKey == ValueKey<String>('FRE-HUB-FASTPASS')) continue;
          if (widgetKey == ValueKey<String>('FRE-HUB-QRCODE')) continue;
          if (widgetKey == ValueKey<String>('FRE-HUB-RESERVATIONS')) continue;
          if (widgetKey == ValueKey<String>('FRE-HUB-SETTINGS')) continue;

          await $(gridEntries.at(i))
              .waitUntilVisible(timeout: const Duration(seconds: 1))
              .tap(
                settleTimeout: const Duration(seconds: 1),
                settlePolicy: SettlePolicy.noSettle,
              );

          await $.pumpAndSettle(duration: Duration(milliseconds: 500));

          await $(Icons.keyboard_arrow_left)
              .waitUntilVisible(timeout: const Duration(seconds: 1))
              .tap(
                settleTimeout: const Duration(seconds: 1),
                settlePolicy: SettlePolicy.noSettle,
              );

          await $.pumpAndSettle(duration: Duration(milliseconds: 500));
        }
      },
    );
  }
}
