import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:timezone/timezone.dart' as tz; import 'package:timezone/data/latest.dart' as tz_data; import '../database/database_helper.dart'; class NotificationService { static final NotificationService instance = NotificationService._init(); final FlutterLocalNotificationsPlugin _plugin = FlutterLocalNotificationsPlugin(); bool _initialized = false; NotificationService._init(); Future init() async { if (_initialized) return; tz_data.initializeTimeZones(); const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); const settings = InitializationSettings(android: androidSettings); await _plugin.initialize(settings); _initialized = true; } Future scheduleRecordatorios() async { await _plugin.cancelAll(); final db = DatabaseHelper.instance; final facturas = await db.getFacturas(estado: 'Pendiente'); final config = await db.getConfiguracion(); final diasStr = config?.diasRecordatorio ?? '7,3,1,0'; final dias = diasStr.split(',').map((e) => int.tryParse(e.trim()) ?? 0).toList(); for (final factura in facturas) { final vencimiento = DateTime.tryParse(factura.fechaVencimiento); if (vencimiento == null) continue; for (final dia in dias) { final notifDate = vencimiento.subtract(Duration(days: dia)); final now = DateTime.now(); if (notifDate.isAfter(now) || notifDate.day == now.day) { await _scheduleNotification( id: factura.id! * 10 + dia, title: dia == 0 ? 'Factura vence hoy' : 'Recordatorio de factura', body: 'La factura vence en $dia día(s)', scheduledDate: notifDate, ); } } } } Future _scheduleNotification({ required int id, required String title, required String body, required DateTime scheduledDate, }) async { const androidDetails = AndroidNotificationDetails( 'hogarcontrol_recordatorios', 'Recordatorios de facturas', channelDescription: 'Notificaciones de recordatorio de pago', importance: Importance.high, priority: Priority.high, ); const details = NotificationDetails(android: androidDetails); final tzDate = tz.TZDateTime.from(scheduledDate, tz.local); await _plugin.zonedSchedule( id, title, body, tzDate, details, androidScheduleMode: AndroidScheduleMode.inexactAllowWhileIdle, matchDateTimeComponents: DateTimeComponents.dayOfMonthAndTime, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, ); } }