import 'dart:convert'; import 'package:workmanager/workmanager.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:odoo_rpc/odoo_rpc.dart'; import 'notification_service.dart'; // NOTE: This key tracks what IDs have been shown as device tray notifications. // It is separate from 'last_seen_notification_id' (which tracks what the user READ in-app). @pragma('vm:entry-point') void callbackDispatcher() { Workmanager().executeTask((task, inputData) async { try { final prefs = await SharedPreferences.getInstance(); final url = prefs.getString('odoo_url'); final sessionStr = prefs.getString('odoo_session'); if (url == null || sessionStr == null) { return Future.value(true); // Not logged in, nothing to do } final sessionArgs = json.decode(sessionStr); final session = OdooSession.fromJson( Map.from(sessionArgs as Map)); final partnerId = session.partnerId; final keyLastDeviceNotifiedId = 'last_device_notified_id_$partnerId'; final keyReadNotificationIds = 'read_notification_ids_$partnerId'; final client = OdooClient(url, sessionId: session); final response = await client.callRPC( '/api/loyalty/fetch_notifications', 'call', {'last_id': 0}, ); client.close(); if (response != null && response['status'] == 'success') { final List notifications = List.from(response['data'] ?? []); // Filter to only truly new ones not yet shown on device tray final lastDeviceNotifiedId = prefs.getInt(keyLastDeviceNotifiedId) ?? 0; final newNotifs = notifications .where((n) => (n['id'] as int? ?? 0) > lastDeviceNotifiedId) .toList(); final notifService = NotificationService(); await notifService.initialize(); if (newNotifs.isNotEmpty) { int highestId = lastDeviceNotifiedId; for (final notif in newNotifs) { final int notifId = notif['id'] as int? ?? 0; if (notifId > highestId) highestId = notifId; await notifService.showNotification( id: notifId, title: notif['title'] as String? ?? 'Mie Mapan', body: notif['body'] as String? ?? '', ); } await prefs.setInt(keyLastDeviceNotifiedId, highestId); } // Always compute badge count based on read_notification_ids final readIds = prefs.getStringList(keyReadNotificationIds); if (readIds == null) { // Initialize read list with all currently fetched notifications on first install/run final initialRead = notifications.map((n) => (n['id'] as int? ?? 0).toString()).toList(); await prefs.setStringList(keyReadNotificationIds, initialRead); await notifService.setBadge(0); } else { final unreadCount = notifications .where((n) => !readIds.contains((n['id'] as int? ?? 0).toString())) .length; await notifService.setBadge(unreadCount); } } } catch (_) { // Silently swallow — background isolate must never crash } return Future.value(true); }); }