import 'dart:math'; import '../data/services/calendar_service.dart'; import '../../../core/notifications/local_notification_service.dart'; import 'models/reminder_action.dart'; import 'models/reminder_payload.dart'; import 'reminder_outbox_store.dart'; class ReminderActionExecutor { final CalendarService _calendarService; final LocalNotificationService _notificationService; final ReminderOutboxStore _outboxStore; final Random _random; ReminderActionExecutor({ required CalendarService calendarService, required LocalNotificationService notificationService, required ReminderOutboxStore outboxStore, Random? random, }) : _calendarService = calendarService, _notificationService = notificationService, _outboxStore = outboxStore, _random = random ?? Random(); Future handleAction({ required ReminderAction action, required ReminderPayload payload, }) async { final ids = payload.mode == ReminderPayloadMode.aggregate ? payload.aggregateIds : [payload.eventId]; if (action == ReminderAction.cancel) { for (final id in ids) { await _notificationService.cancelEventReminder(id); await _archiveEvent(id, ReminderAction.cancel); } return; } if (action == ReminderAction.snooze10m || action == ReminderAction.timeout30s) { for (final id in ids) { await _snoozeEvent(id); } } } Future replayPendingActions() async { final pending = await _outboxStore.listPending(); for (final item in pending) { if (item.targetStatus != 'archived') { await _outboxStore.markDone(item.opId); continue; } try { await _calendarService.archiveEvent(item.eventId); await _outboxStore.markDone(item.opId); } catch (error) { await _outboxStore.markRetry(item.opId, error.toString()); } } } Future _snoozeEvent(String eventId) async { final event = await _calendarService.getEventById(eventId); if (event == null) { return; } final now = DateTime.now(); final endAt = event.endAt; if (endAt != null && !now.isBefore(endAt)) { await _notificationService.cancelEventReminder(eventId); await _archiveEvent(eventId, ReminderAction.autoArchive); return; } final nextAt = now.add(const Duration(minutes: 10)); if (endAt != null && !nextAt.isBefore(endAt)) { await _notificationService.cancelEventReminder(eventId); await _archiveEvent(eventId, ReminderAction.autoArchive); return; } await _notificationService.scheduleReminderAt(event, nextAt); } Future _archiveEvent(String eventId, ReminderAction action) async { final opId = '${DateTime.now().millisecondsSinceEpoch}-${_random.nextInt(1 << 32)}'; final outboxItem = ReminderOutboxItem( opId: opId, eventId: eventId, action: action, targetStatus: 'archived', occurredAt: DateTime.now(), ); await _outboxStore.enqueue(outboxItem); try { await _calendarService.archiveEvent(eventId); await _outboxStore.markDone(opId); } catch (error) { await _outboxStore.markRetry(opId, error.toString()); } } }