import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
import 'package:iop_client/main.dart';
import 'package:iop_client/src/integrations/nexo/nexo_notification_host_integration.dart';
import 'support/client_test_harness.dart';

void main() {
  testWidgets(
    'notification stream from NexoNotificationHostIntegration connects to UI snackbar',
    (WidgetTester tester) async {
      final fakeClient = FakeClientWireClient(shouldSuccess: true);
      final fakeStatusRepo = FakeControlPlaneStatusRepository();

      // Create a fake NexoNotificationClient that emits a notification.
      final notificationController = StreamController<Map<String, dynamic>>();
      final fakeNexoClient = FakeNexoClientsForUiTest(notificationController);
      final fakeHost = NexoNotificationHostIntegration(
        pushClient: fakeNexoClient,
      );

      await tester.pumpWidget(
        IopClientApp(
          testClient: fakeClient,
          statusRepository: fakeStatusRepo,
          notificationHost: fakeHost,
        ),
      );
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 100));

      // Verify wire status shows connected.
      expect(find.text('CONNECTED'), findsOneWidget);

      // Emit a notification message through the fake client.
      notificationController.add(const {
        'type': 'message',
        'message': 'Hello from Nexo',
        'channel_name': 'general',
        'sender_name': 'test-user',
      });
      await tester.pump();

      // Verify the SnackBar appears in the UI.
      expect(find.textContaining('Hello from Nexo'), findsOneWidget);

      await notificationController.close();
    },
  );

  testWidgets(
    'notification stream shows channel-only message when sender is empty',
    (WidgetTester tester) async {
      final fakeClient = FakeClientWireClient(shouldSuccess: true);
      final fakeStatusRepo = FakeControlPlaneStatusRepository();

      final notificationController = StreamController<Map<String, dynamic>>();
      final fakeNexoClient = FakeNexoClientsForUiTest(notificationController);
      final fakeHost = NexoNotificationHostIntegration(
        pushClient: fakeNexoClient,
      );

      await tester.pumpWidget(
        IopClientApp(
          testClient: fakeClient,
          statusRepository: fakeStatusRepo,
          notificationHost: fakeHost,
        ),
      );
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 100));

      expect(find.text('CONNECTED'), findsOneWidget);

      // Emit notification with empty sender — should show just the message.
      notificationController.add(const {
        'type': 'message',
        'message': 'Direct message content',
        'channel_name': 'alerts',
        'sender_name': '',
      });
      await tester.pump();

      // When sender is empty, only message content is shown.
      expect(find.textContaining('Direct message content'), findsOneWidget);

      await notificationController.close();
    },
  );

  testWidgets('notification stream ignores non-message events (e.g. system)', (
    WidgetTester tester,
  ) async {
    final fakeClient = FakeClientWireClient(shouldSuccess: true);
    final fakeStatusRepo = FakeControlPlaneStatusRepository();

    final notificationController = StreamController<Map<String, dynamic>>();
    final fakeNexoClient = FakeNexoClientsForUiTest(notificationController);
    final fakeHost = NexoNotificationHostIntegration(
      pushClient: fakeNexoClient,
    );

    await tester.pumpWidget(
      IopClientApp(
        testClient: fakeClient,
        statusRepository: fakeStatusRepo,
        notificationHost: fakeHost,
      ),
    );
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 100));

    // Emit a non-message type.
    notificationController.add(const {
      'type': 'system',
      'message': 'System notification',
    });
    await tester.pump();

    // No SnackBar should appear for non-message types.
    expect(find.textContaining('System notification'), findsNothing);

    await notificationController.close();
  });
}
