import 'dart:convert'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:uuid/uuid.dart'; import '../modelos/alarma_musical.dart'; import '../modelos/emisora.dart'; import 'servicio_programacion_alarmas.dart'; class ConfiguracionAlarmas { const ConfiguracionAlarmas({ required this.alarmas, required this.vacaciones, required this.excepciones, }); final List alarmas; final List vacaciones; final List excepciones; } class ServicioAlarmas { ServicioAlarmas({ ServicioProgramacionAlarmas? programacion, SharedPreferences? prefs, DateTime Function()? reloj, }) : _programacion = programacion ?? ServicioProgramacionAlarmas(), _prefs = prefs, _reloj = reloj ?? DateTime.now; static const _keyConfig = 'alarmas_musicales_v1'; final ServicioProgramacionAlarmas _programacion; final SharedPreferences? _prefs; final DateTime Function() _reloj; final _uuid = const Uuid(); Future cargar() async { final prefs = await _resolverPrefs(); final raw = prefs.getString(_keyConfig); if (raw == null || raw.trim().isEmpty) { return const ConfiguracionAlarmas( alarmas: [], vacaciones: [], excepciones: [], ); } try { final data = jsonDecode(raw) as Map; return ConfiguracionAlarmas( alarmas: (data['alarmas'] as List? ?? const []) .whereType() .map( (e) => AlarmaMusical.fromJson(Map.from(e)), ) .toList(), vacaciones: (data['vacaciones'] as List? ?? const []) .whereType() .map( (e) => RangoVacaciones.fromJson(Map.from(e)), ) .toList(), excepciones: (data['excepciones'] as List? ?? const []) .whereType() .map( (e) => ExcepcionAlarma.fromJson(Map.from(e)), ) .toList(), ); } catch (_) { return const ConfiguracionAlarmas( alarmas: [], vacaciones: [], excepciones: [], ); } } Future guardarAlarma( AlarmaMusical alarma, { List? vacaciones, List? excepciones, }) async { final config = await cargar(); final ahora = _reloj(); final alarmas = List.from(config.alarmas); final index = alarmas.indexWhere((a) => a.id == alarma.id); final normalizada = _recalcular( alarma.copyWith(creadaEn: alarma.creadaEn ?? ahora, actualizadaEn: ahora), vacaciones ?? config.vacaciones, excepciones ?? config.excepciones, ); if (index >= 0) { alarmas[index] = normalizada; } else { alarmas.add(normalizada); } final nuevo = ConfiguracionAlarmas( alarmas: alarmas, vacaciones: vacaciones ?? config.vacaciones, excepciones: excepciones ?? config.excepciones, ); await _guardar(nuevo); return nuevo; } Future eliminarAlarma(String id) async { final config = await cargar(); final nuevo = ConfiguracionAlarmas( alarmas: config.alarmas.where((a) => a.id != id).toList(), vacaciones: config.vacaciones, excepciones: config.excepciones.where((e) => e.alarmaId != id).toList(), ); await _guardar(nuevo); return nuevo; } Future guardarVacaciones( List vacaciones, ) async { final config = await cargar(); final alarmas = config.alarmas .map((a) => _recalcular(a, vacaciones, config.excepciones)) .toList(); final nuevo = ConfiguracionAlarmas( alarmas: alarmas, vacaciones: vacaciones, excepciones: config.excepciones, ); await _guardar(nuevo); return nuevo; } Future saltarProxima(String alarmaId) async { final config = await cargar(); final alarma = config.alarmas.firstWhere((a) => a.id == alarmaId); final proxima = alarma.proximaEjecucion; if (proxima == null) return config; final excepciones = [ ...config.excepciones, ExcepcionAlarma(alarmaId: alarmaId, ejecucion: proxima, tipo: 'skipNext'), ]; final alarmas = config.alarmas .map( (a) => a.id == alarmaId ? _recalcular(a, config.vacaciones, excepciones) : a, ) .toList(); final nuevo = ConfiguracionAlarmas( alarmas: alarmas, vacaciones: config.vacaciones, excepciones: excepciones, ); await _guardar(nuevo); return nuevo; } AlarmaMusical crearAlarma({ required String nombre, required int hora, required int minuto, required TipoProgramacionAlarma tipoProgramacion, required List diasSemana, Emisora? emisora, }) { final ahora = _reloj(); return AlarmaMusical( id: _uuid.v4(), nombre: nombre, hora: hora, minuto: minuto, tipoProgramacion: tipoProgramacion, diasSemana: diasSemana, emisora: emisora, creadaEn: ahora, actualizadaEn: ahora, ); } Future _guardar(ConfiguracionAlarmas config) async { final prefs = await _resolverPrefs(); await prefs.setString( _keyConfig, jsonEncode({ 'alarmas': config.alarmas.map((a) => a.toJson()).toList(), 'vacaciones': config.vacaciones.map((v) => v.toJson()).toList(), 'excepciones': config.excepciones.map((e) => e.toJson()).toList(), }), ); } AlarmaMusical _recalcular( AlarmaMusical alarma, List vacaciones, List excepciones, ) { return alarma.copyWith( proximaEjecucion: _programacion.calcularProxima( alarma: alarma, desde: _reloj(), vacaciones: vacaciones, excepciones: excepciones, ), ); } Future _resolverPrefs() async => _prefs ?? SharedPreferences.getInstance(); }