import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../models/availability.dart'; import 'session_controller.dart'; /// Availability is stored as `yyyy-mm-dd` -> the blocks switched on that day. typedef AvailabilityMap = Map>; String dayKey(DateTime d) => '${d.year}-${d.month.toString().padLeft(2, '0')}-${d.day.toString().padLeft(2, '0')}'; class AvailabilityController extends Notifier { static const _key = 'availability'; SharedPreferences get _prefs => ref.read(prefsProvider); @override AvailabilityMap build() { final raw = _prefs.getStringList(_key) ?? const []; final map = >{}; for (final entry in raw) { // Stored as "2026-08-14:morning,evening". final parts = entry.split(':'); if (parts.length != 2) continue; final blocks = parts[1] .split(',') .where((s) => s.isNotEmpty) .map( (name) => DayBlock.values.firstWhere( (b) => b.name == name, orElse: () => DayBlock.morning, ), ) .toSet(); if (blocks.isNotEmpty) map[parts[0]] = blocks; } return map; } void _persist(AvailabilityMap map) { _prefs.setStringList(_key, [ for (final e in map.entries) if (e.value.isNotEmpty) '${e.key}:${e.value.map((b) => b.name).join(',')}', ]); state = map; } Set blocksFor(DateTime day) => state[dayKey(day)] ?? {}; bool isDayOff(DateTime day) => blocksFor(day).isEmpty; void toggleBlock(DateTime day, DayBlock block) { final map = { for (final e in state.entries) e.key: {...e.value}, }; final key = dayKey(day); final blocks = map[key] ?? {}; if (!blocks.remove(block)) blocks.add(block); if (blocks.isEmpty) { map.remove(key); } else { map[key] = blocks; } _persist(map); } /// The day toggle: all three blocks on, or the day cleared. void setDayAvailable(DateTime day, bool available) { final map = { for (final e in state.entries) e.key: {...e.value}, }; final key = dayKey(day); if (available) { map[key] = DayBlock.values.toSet(); } else { map.remove(key); } _persist(map); } /// Presets across the visible week: all days, weekdays only, weekends only. void applyPreset( List week, { required bool Function(DateTime) test, }) { final map = { for (final e in state.entries) e.key: {...e.value}, }; for (final day in week) { final key = dayKey(day); if (test(day)) { map[key] = DayBlock.values.toSet(); } else { map.remove(key); } } _persist(map); } void clearWeek(List week) { final map = { for (final e in state.entries) e.key: {...e.value}, }; for (final day in week) { map.remove(dayKey(day)); } _persist(map); } } final availabilityProvider = NotifierProvider( AvailabilityController.new, ); /// How many days in the coming week have at least one block switched on. final daysSetProvider = Provider((ref) { final map = ref.watch(availabilityProvider); final now = DateTime.now(); var count = 0; for (var i = 0; i < 7; i++) { final d = now.add(Duration(days: i)); if ((map[dayKey(d)] ?? const {}).isNotEmpty) count++; } return count; });