import 'package:didvan/models/notification_message.dart'; import 'package:didvan/services/app_home_widget/home_widget_repository.dart'; import 'package:didvan/services/app_initalizer.dart'; import 'package:didvan/services/auth/auth_api_service.dart'; import 'package:didvan/services/auth/token_storage.dart'; import 'package:didvan/services/notification/notification_service.dart'; import 'package:didvan/services/storage/storage.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; class FirebaseApi { static String? fcmToken; Future initNotification() async { if (kIsWeb) { try { bool isSupported = await FirebaseMessaging.instance.isSupported(); if (!isSupported) { if (kDebugMode) { print( "⚠️ مرورگر از نوتیفیکیشن پشتیبانی نمی‌کند. پروسه نوتیفیکیشن با موفقیت لغو شد تا از کرش جلوگیری شود."); } return; } } catch (e) { if (kDebugMode) print("Error checking FCM support: $e"); return; } } try { final messaging = FirebaseMessaging.instance; NotificationSettings settings = await messaging.requestPermission( alert: true, announcement: true, badge: true, carPlay: false, criticalAlert: true, provisional: true, sound: true, ); if (settings.authorizationStatus == AuthorizationStatus.authorized || settings.authorizationStatus == AuthorizationStatus.provisional) { if (kIsWeb) { fcmToken = await messaging.getToken( vapidKey: "BMXHGd93t_htpS7c62ceuuLVVmia2cEDmqxp46g9Vt0B3OxNMKIqN9nupsUMtv2Vq8Yy2sQGIqgCm9FxUSKvssU", ); } else { fcmToken = await messaging.getToken(); } if (kDebugMode) { print("fCMToken: $fcmToken"); } } else { if (kDebugMode) { print("User declined or has not accepted notification permissions"); } } } catch (e) { if (kDebugMode) print("Error initializing notifications: $e"); } try { final initMsg = await FirebaseMessaging.instance.getInitialMessage(); if (initMsg != null) { if (kDebugMode) print("=== APP OPENED FROM NOTIFICATION (TERMINATED) ==="); NotificationMessage data = NotificationMessage.fromJson(initMsg.data); HomeWidgetRepository.data = data; } } catch (e) { if (kDebugMode) print("Error handling initial message: $e"); } FirebaseMessaging.onMessageOpenedApp.listen((initMsg) async { try { NotificationMessage data = NotificationMessage.fromJson(initMsg.data); HomeWidgetRepository.data = data; await Future.delayed(const Duration(milliseconds: 300)); await HomeWidgetRepository.decideWhereToGoNotif(); await StorageService.delete( key: 'notification${AppInitializer.createNotificationId(data)}'); } catch (e) { if (kDebugMode) print("Error handling background message: $e"); } }); FirebaseMessaging.onMessage.listen((event) => handleMessage(event)); // Push the current token to auth-service whenever it changes (Firebase // rotates it every few months, or after app reinstall, or after the // user clears app data). Without this we'd lose push delivery for // already-logged-in users until they explicitly logged in again. FirebaseMessaging.instance.onTokenRefresh.listen((newToken) async { fcmToken = newToken; await _syncTokenToServer(newToken); }); // Also sync once on every cold start: covers the case where the user // already logged in on a previous build and the server has a stale or // missing token. if (fcmToken != null && fcmToken!.isNotEmpty) { await _syncTokenToServer(fcmToken!); } } /// Push the FCM token up to auth-service so push notifications can reach /// this device. Safely no-ops when the user isn't logged in (no userId /// yet) — we'll catch them on the next cold start once they sign in. Future _syncTokenToServer(String token) async { try { final userId = TokenStorage.userId; if (userId == null || userId.isEmpty) { if (kDebugMode) { print('FCM token refresh: skipping — user not logged in yet'); } return; } final result = await AuthApiService.instance.updateUser( id: userId, data: {'firebaseToken': token}, ); if (kDebugMode) { print('FCM token pushed to server: success=${result.isSuccess}'); } } catch (e) { if (kDebugMode) print('FCM token sync failed: $e'); } } void handleMessage(RemoteMessage? message) async { if (message == null) return; try { await NotificationService.showFirebaseNotification(message); } catch (e) { if (kDebugMode) print("Error showing local notification: $e"); } } }