import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:tane/services/notification_service.dart';

class _MockPlugin extends Mock implements FlutterLocalNotificationsPlugin {}

void main() {
  late _MockPlugin plugin;

  setUpAll(() {
    registerFallbackValue(
      const NotificationDetails(
        android: AndroidNotificationDetails('x', 'x'),
      ),
    );
    registerFallbackValue(const InitializationSettings());
  });

  setUp(() {
    plugin = _MockPlugin();
    when(() => plugin.show(any(), any(), any(), any(),
        payload: any(named: 'payload'))).thenAnswer((_) async {});
    // Generic platform resolution returns null, so the permission requests in
    // initialize() are skipped in tests.
    when(() => plugin.resolvePlatformSpecificImplementation())
        .thenReturn(null);
  });

  test('showMessage passes the title and pubkey payload, no body', () async {
    final service = NotificationService(plugin: plugin, supported: true);
    await service.showMessage(
        peerPubkey: 'abc123', title: 'New message from Alice');
    final captured = verify(() => plugin.show(
          captureAny(),
          captureAny(),
          captureAny(),
          captureAny(),
          payload: captureAny(named: 'payload'),
        )).captured;
    expect(captured[1], 'New message from Alice'); // title
    expect(captured[2], isNull); // no body (privacy: no message text)
    expect(captured[4], 'abc123'); // payload = peer pubkey
  });

  test('is a no-op on unsupported platforms (web/windows)', () async {
    final service = NotificationService(plugin: plugin, supported: false);
    await service.initialize();
    await service.showMessage(peerPubkey: 'abc123', title: 'hi');
    verifyNever(() => plugin.show(any(), any(), any(), any(),
        payload: any(named: 'payload')));
  });

  test('a tap with a payload invokes onTapChat with the pubkey', () async {
    // Capture the response handler initialize() registers, then simulate a tap.
    void Function(NotificationResponse)? handler;
    when(() => plugin.initialize(
      any(),
      onDidReceiveNotificationResponse:
          any(named: 'onDidReceiveNotificationResponse'),
    )).thenAnswer((inv) async {
      handler = inv.namedArguments[#onDidReceiveNotificationResponse]
          as void Function(NotificationResponse)?;
      return true;
    });

    final service = NotificationService(plugin: plugin, supported: true);
    String? tapped;
    service.onTapChat = (pk) => tapped = pk;
    await service.initialize();

    handler!(const NotificationResponse(
      notificationResponseType: NotificationResponseType.selectedNotification,
      payload: 'abc123',
    ));
    expect(tapped, 'abc123');
  });
}
