import 'dart:async'; import 'package:flutter/services.dart'; import '../modelos/alarma_musical.dart'; class EventoAlarmaAndroid { const EventoAlarmaAndroid({ required this.alarmaId, required this.titulo, required this.accion, }); final String alarmaId; final String titulo; final String accion; factory EventoAlarmaAndroid.fromMap(Map map) { return EventoAlarmaAndroid( alarmaId: map['alarmId'] as String? ?? '', titulo: map['alarmTitle'] as String? ?? 'PluriWave', accion: map['alarmAction'] as String? ?? '', ); } } class DiagnosticoAlarmasAndroid { const DiagnosticoAlarmasAndroid({ required this.puedeProgramarExactas, required this.notificacionesPermitidas, required this.fabricante, required this.versionSdk, }); final bool puedeProgramarExactas; final bool notificacionesPermitidas; final String fabricante; final int versionSdk; factory DiagnosticoAlarmasAndroid.fromMap(Map map) { return DiagnosticoAlarmasAndroid( puedeProgramarExactas: map['canScheduleExactAlarms'] as bool? ?? true, notificacionesPermitidas: map['notificationsEnabled'] as bool? ?? true, fabricante: map['manufacturer'] as String? ?? 'Android', versionSdk: map['sdkInt'] as int? ?? 0, ); } } class ServicioAlarmasAndroid { ServicioAlarmasAndroid({ MethodChannel channel = const MethodChannel('pluriwave/alarm_scheduler'), }) : _channel = channel { _instalarHandler(_channel); } final MethodChannel _channel; static final _eventosController = StreamController.broadcast(); static bool _handlerInstalado = false; Stream get eventosAlarma => _eventosController.stream; Future programar(AlarmaMusical alarma) async { final proxima = alarma.proximaEjecucion; if (proxima == null || !alarma.activa) { await cancelar(alarma.id); return; } await _channel.invokeMethod('scheduleAlarm', { 'id': alarma.id, 'title': alarma.nombre, 'triggerAtMillis': proxima.millisecondsSinceEpoch, 'preNoticeAtMillis': proxima.subtract(const Duration(minutes: 30)).millisecondsSinceEpoch, }); } Future cancelar(String alarmaId) => _channel.invokeMethod('cancelAlarm', {'id': alarmaId}); Future ocultarNotificacionAlarma(String alarmaId) => _channel .invokeMethod('dismissAlarmNotification', {'id': alarmaId}); Future diagnostico() async { final raw = await _channel.invokeMethod>( 'diagnostics', ); return DiagnosticoAlarmasAndroid.fromMap(raw ?? const {}); } Future obtenerEventoInicial() async { final raw = await _channel.invokeMethod>( 'getInitialAlarmIntent', ); if (raw == null || raw.isEmpty) return null; final evento = EventoAlarmaAndroid.fromMap(raw); return evento.alarmaId.isEmpty ? null : evento; } static void _instalarHandler(MethodChannel channel) { if (_handlerInstalado) return; _handlerInstalado = true; channel.setMethodCallHandler((call) async { if (call.method != 'alarmFired') return; final args = call.arguments; if (args is Map) { final evento = EventoAlarmaAndroid.fromMap(args); if (evento.alarmaId.isNotEmpty) { _eventosController.add(evento); } } }); } }