import 'dart:async'; import 'dart:convert'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'auth_service.dart'; @pragma('vm:entry-point') Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { await Firebase.initializeApp(); print('Background message: ${message.messageId}'); } class NotificationService { static final NotificationService _instance = NotificationService._internal(); factory NotificationService() => _instance; NotificationService._internal(); final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance; final FlutterLocalNotificationsPlugin _localNotifications = FlutterLocalNotificationsPlugin(); bool _initialized = false; // Stream per gestire i tap sulle notifiche final StreamController _messageStreamController = StreamController.broadcast(); Stream get onMessageTap => _messageStreamController.stream; Future initialize() async { if (_initialized) return; try { await _requestPermissions(); await _initializeLocalNotifications(); _configureHandlers(); await _getFcmToken(); _initialized = true; print('NotificationService initialized'); } catch (e) { print('Error initializing notifications: $e'); } } Future _requestPermissions() async { final settings = await _firebaseMessaging.requestPermission( alert: true, badge: true, sound: true, ); print('Notification permission: ${settings.authorizationStatus}'); } Future _initializeLocalNotifications() async { const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); const iosSettings = DarwinInitializationSettings(); await _localNotifications.initialize( const InitializationSettings(android: androidSettings, iOS: iosSettings), onDidReceiveNotificationResponse: _onNotificationTapped, ); const channel = AndroidNotificationChannel( 'allarmi_channel', 'Allarmi', description: 'Notifiche per allarmi del sistema di monitoraggio', importance: Importance.high, playSound: true, enableVibration: true, ); await _localNotifications .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(channel); } void _onNotificationTapped(NotificationResponse response) { print('Notifica tappata: ${response.payload}'); if (response.payload != null && response.payload!.isNotEmpty) { try { final data = jsonDecode(response.payload!); // Crea un RemoteMessage mock per compatibilità final message = RemoteMessage( data: data, messageId: DateTime.now().toString(), ); _messageStreamController.add(message); } catch (e) { print('Errore parsing payload: $e'); } } } void _configureHandlers() { FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); FirebaseMessaging.onMessage.listen(_handleForegroundMessage); // Handler quando app aperta da notifica (background/terminated) FirebaseMessaging.onMessageOpenedApp.listen((message) { print('Notifica aperta (background): ${message.messageId}'); _messageStreamController.add(message); }); // Controlla se app avviata da notifica _firebaseMessaging.getInitialMessage().then((message) { if (message != null) { print('App avviata da notifica: ${message.messageId}'); _messageStreamController.add(message); } }); } Future _getFcmToken() async { try { final token = await _firebaseMessaging.getToken(); if (token != null) { print('FCM Token: $token'); await AuthService().saveFcmToken(token); } _firebaseMessaging.onTokenRefresh.listen((newToken) { AuthService().saveFcmToken(newToken); }); } catch (e) { print('Error getting FCM token: $e'); } } Future _handleForegroundMessage(RemoteMessage message) async { print('Foreground message: ${message.messageId}'); final notification = message.notification; if (notification != null) { await _showLocalNotification( title: notification.title ?? 'ASE Monitor', body: notification.body ?? 'Nuovo allarme', payload: jsonEncode(message.data), ); } } Future _showLocalNotification({ required String title, required String body, String? payload, }) async { const androidDetails = AndroidNotificationDetails( 'allarmi_channel', 'Allarmi', channelDescription: 'Notifiche per allarmi del sistema di monitoraggio', importance: Importance.high, priority: Priority.high, playSound: true, enableVibration: true, icon: '@mipmap/ic_launcher', ); const iosDetails = DarwinNotificationDetails( presentAlert: true, presentBadge: true, presentSound: true, ); await _localNotifications.show( DateTime.now().millisecondsSinceEpoch ~/ 1000, title, body, const NotificationDetails(android: androidDetails, iOS: iosDetails), payload: payload, ); } Future getFcmToken() async { try { return await _firebaseMessaging.getToken(); } catch (e) { print('Errore ottenimento FCM token: $e'); return null; } } void dispose() { _messageStreamController.close(); } }