import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:marianum_mobile/api/marianumconnect/queries/get_ticker_nav/get_ticker_nav_response.dart';
import 'package:marianum_mobile/api/marianumconnect/queries/get_ticker_page/get_ticker_page_response.dart';
import 'package:marianum_mobile/view/pages/ticker/ticker_view.dart';

List<TickerNavSection> _sections() => [
  TickerNavSection(
    title: 'Infos',
    pages: [
      TickerNavPage(title: 'Über uns', slug: 'about', kind: TickerPageKind.content),
      TickerNavPage(
        title: 'Webseite',
        slug: 'web',
        kind: TickerPageKind.redirect,
        externalUrl: 'https://marianum-fulda.de',
      ),
    ],
  ),
];

Widget _host({
  List<TickerNavSection>? sections,
  String? initialSlug,
  void Function(String? slug)? onSelectionChanged,
}) => MaterialApp(
  home: TickerScaffold(
    sections: sections ?? _sections(),
    initialSlug: initialSlug,
    onSelectionChanged: onSelectionChanged,
    homeBuilder: (context, onLinkTap) => const Text('HOME'),
    pageBuilder: (context, slug, onLinkTap) => Text('PAGE:$slug'),
  ),
);

Finder _appBarText(String text) =>
    find.descendant(of: find.byType(AppBar), matching: find.text(text));

// The "Aktuelles" home action is always present; it is greyed out (disabled)
// while home is the current surface, active while a page is open.
bool _homeEnabled(WidgetTester tester) =>
    tester
        .widget<IconButton>(
          find.widgetWithIcon(IconButton, Icons.home_outlined),
        )
        .onPressed !=
    null;

// The home surface stays mounted (IndexedStack) while a page is open, so
// "which content is shown" is the stack index, not widget presence.
int _shownIndex(WidgetTester tester) =>
    tester.widget<IndexedStack>(find.byType(IndexedStack)).index!;

const String _navTooltip = 'Seiten';

void main() {
  group('narrow layout (< 900)', () {
    testWidgets('opens the nav in a bottom sheet from the floating button', (
      tester,
    ) async {
      await tester.pumpWidget(_host());
      await tester.pumpAndSettle();

      // No drawer, and the nav is hidden until the sheet is opened.
      expect(find.byType(Drawer), findsNothing);
      expect(find.text('Über uns'), findsNothing);
      expect(find.byTooltip(_navTooltip), findsOneWidget);

      await tester.tap(find.byTooltip(_navTooltip));
      await tester.pumpAndSettle();

      // Sheet shows the section-grouped nav.
      expect(find.text('Aktuelles'), findsOneWidget);
      expect(find.text('Über uns'), findsOneWidget);

      // Selecting a page closes the sheet and switches the content in place.
      await tester.tap(find.text('Über uns'));
      await tester.pumpAndSettle();

      expect(find.text('Aktuelles'), findsNothing);
      expect(_shownIndex(tester), 1);
      expect(_appBarText('Über uns'), findsOneWidget);
    });
  });

  group('wide layout (>= 900)', () {
    Future<void> pumpWide(WidgetTester tester) async {
      tester.view.physicalSize = const Size(1200, 2000);
      tester.view.devicePixelRatio = 1.0;
      addTearDown(tester.view.resetPhysicalSize);
      addTearDown(tester.view.resetDevicePixelRatio);
      await tester.pumpWidget(_host());
      await tester.pumpAndSettle();
    }

    testWidgets('shows a permanent sidebar and no drawer', (tester) async {
      await pumpWide(tester);

      expect(find.byType(Drawer), findsNothing);
      // No bottom-sheet trigger on tablets — the sidebar is permanent.
      expect(find.byTooltip(_navTooltip), findsNothing);
      // Sidebar nav item is visible without any interaction.
      expect(find.text('Über uns'), findsOneWidget);
    });

    testWidgets('selecting a page swaps content, title and home action', (
      tester,
    ) async {
      await pumpWide(tester);

      expect(_shownIndex(tester), 0);
      expect(find.text('PAGE:about'), findsNothing);
      expect(_appBarText('Ticker'), findsOneWidget);
      // Home action is shown but greyed out on the home surface.
      expect(find.byIcon(Icons.home_outlined), findsOneWidget);
      expect(_homeEnabled(tester), isFalse);

      await tester.tap(find.text('Über uns'));
      await tester.pumpAndSettle();

      expect(_shownIndex(tester), 1);
      expect(find.text('PAGE:about'), findsOneWidget);
      expect(_appBarText('Über uns'), findsOneWidget);
      expect(_homeEnabled(tester), isTrue);

      await tester.tap(find.byIcon(Icons.home_outlined));
      await tester.pumpAndSettle();

      expect(_shownIndex(tester), 0);
      expect(find.text('PAGE:about'), findsNothing);
      expect(_appBarText('Ticker'), findsOneWidget);
      expect(find.byIcon(Icons.home_outlined), findsOneWidget);
      expect(_homeEnabled(tester), isFalse);
    });
  });

  group('remembered selection', () {
    Future<void> pumpWide(WidgetTester tester, Widget host) async {
      tester.view.physicalSize = const Size(1200, 2000);
      tester.view.devicePixelRatio = 1.0;
      addTearDown(tester.view.resetPhysicalSize);
      addTearDown(tester.view.resetDevicePixelRatio);
      await tester.pumpWidget(host);
      await tester.pumpAndSettle();
    }

    testWidgets('reopens the persisted page on mount', (tester) async {
      await tester.pumpWidget(_host(initialSlug: 'about'));
      await tester.pumpAndSettle();

      expect(_shownIndex(tester), 1);
      expect(find.text('PAGE:about'), findsOneWidget);
      expect(_appBarText('Über uns'), findsOneWidget);
      expect(_homeEnabled(tester), isTrue);
    });

    testWidgets('falls back to home and drops a slug that is gone', (
      tester,
    ) async {
      String? persisted = 'ghost';
      await tester.pumpWidget(
        _host(initialSlug: 'ghost', onSelectionChanged: (slug) => persisted = slug),
      );
      await tester.pumpAndSettle();

      expect(_shownIndex(tester), 0);
      expect(_appBarText('Ticker'), findsOneWidget);
      expect(persisted, isNull);
    });

    testWidgets('does not restore a redirect slug', (tester) async {
      await tester.pumpWidget(_host(initialSlug: 'web'));
      await tester.pumpAndSettle();

      expect(_shownIndex(tester), 0);
    });

    testWidgets('reports selection changes so the host can persist them', (
      tester,
    ) async {
      final changes = <String?>[];
      await pumpWide(tester, _host(onSelectionChanged: changes.add));

      await tester.tap(find.text('Über uns'));
      await tester.pumpAndSettle();
      await tester.tap(find.byIcon(Icons.home_outlined));
      await tester.pumpAndSettle();

      expect(changes, ['about', null]);
    });

    testWidgets('drops the open page when a fresh nav no longer lists it', (
      tester,
    ) async {
      String? persisted;
      await pumpWide(
        tester,
        _host(onSelectionChanged: (slug) => persisted = slug),
      );

      await tester.tap(find.text('Über uns'));
      await tester.pumpAndSettle();
      expect(_shownIndex(tester), 1);

      await tester.pumpWidget(
        _host(
          sections: [
            TickerNavSection(
              title: 'Infos',
              pages: [
                TickerNavPage(
                  title: 'Anderes',
                  slug: 'other',
                  kind: TickerPageKind.content,
                ),
              ],
            ),
          ],
          onSelectionChanged: (slug) => persisted = slug,
        ),
      );
      await tester.pumpAndSettle();

      expect(_shownIndex(tester), 0);
      expect(_appBarText('Ticker'), findsOneWidget);
      expect(persisted, isNull);
    });
  });

  group('back gesture', () {
    testWidgets('pops from a sub-page back to home via the tab navigator', (
      tester,
    ) async {
      tester.view.physicalSize = const Size(1200, 2000);
      tester.view.devicePixelRatio = 1.0;
      addTearDown(tester.view.resetPhysicalSize);
      addTearDown(tester.view.resetDevicePixelRatio);
      await tester.pumpWidget(_host());
      await tester.pumpAndSettle();

      await tester.tap(find.text('Über uns'));
      await tester.pumpAndSettle();
      expect(_shownIndex(tester), 1);

      final navigator = tester.state<NavigatorState>(find.byType(Navigator));
      // The LocalHistoryEntry is what makes the enclosing tab shell delegate
      // the system back to this navigator instead of switching tabs.
      expect(navigator.canPop(), isTrue);

      await navigator.maybePop();
      await tester.pumpAndSettle();

      expect(_shownIndex(tester), 0);
      expect(_appBarText('Ticker'), findsOneWidget);
      expect(navigator.canPop(), isFalse);
    });

    testWidgets('home selection releases the back interception', (
      tester,
    ) async {
      tester.view.physicalSize = const Size(1200, 2000);
      tester.view.devicePixelRatio = 1.0;
      addTearDown(tester.view.resetPhysicalSize);
      addTearDown(tester.view.resetDevicePixelRatio);
      await tester.pumpWidget(_host());
      await tester.pumpAndSettle();

      await tester.tap(find.text('Über uns'));
      await tester.pumpAndSettle();
      await tester.tap(find.byIcon(Icons.home_outlined));
      await tester.pumpAndSettle();

      final navigator = tester.state<NavigatorState>(find.byType(Navigator));
      expect(navigator.canPop(), isFalse);
    });
  });
}
