import 'package:shared_preferences/shared_preferences.dart';

/// Registo local (por criança) de escovagens e da meta semanal.
/// Segue o mesmo padrão de [QuizPrefs]: chaves com sufixo `_scopeId`,
/// guardadas via [SharedPreferences], sem qualquer chamada ao Supabase.
///
/// Cada escovagem é guardada com a hora exata (não só a data), para permitir
/// até [maxPerDay] registos por dia — a criança pode escovar os dentes de
/// manhã, à tarde e à noite, a qualquer hora.
class BrushingPrefs {
  static const String _kGoalKey = 'brushing_weekly_goal';
  static const String _kDatesKey = 'brushing_dates';
  static const int maxPerDay = 3;
  static const int defaultWeeklyGoal = maxPerDay * 7;

  static String _key(String base, String scopeId) => '${base}_$scopeId';

  static DateTime _currentWeekMonday() {
    final now = DateTime.now();
    return DateTime(
      now.year,
      now.month,
      now.day,
    ).subtract(Duration(days: now.weekday - 1));
  }

  /// Lê as escovagens guardadas e, de caminho, descarta (apaga do
  /// armazenamento) qualquer registo de semanas anteriores — o contador
  /// semanal deve zerar a cada nova semana, não só na exibição mas também
  /// nos dados guardados, para não crescer para sempre.
  static Future<List<DateTime>> _getEntries(String scopeId) async {
    final prefs = await SharedPreferences.getInstance();
    final key = _key(_kDatesKey, scopeId);
    final raw = prefs.getStringList(key) ?? const [];
    final entries = raw.map(DateTime.tryParse).whereType<DateTime>().toList();

    final monday = _currentWeekMonday();
    final kept = entries
        .where((d) => !DateTime(d.year, d.month, d.day).isBefore(monday))
        .toList();
    if (kept.length != entries.length) {
      await prefs.setStringList(
        key,
        kept.map((d) => d.toIso8601String()).toList(),
      );
    }
    return kept;
  }

  static Future<int> getWeeklyGoal(String scopeId) async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getInt(_key(_kGoalKey, scopeId)) ?? defaultWeeklyGoal;
  }

  static Future<void> setWeeklyGoal(String scopeId, int goal) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setInt(_key(_kGoalKey, scopeId), goal);
  }

  static Future<int> getTodayCount(String scopeId) async {
    final entries = await _getEntries(scopeId);
    final now = DateTime.now();
    return entries
        .where(
          (d) =>
              d.year == now.year && d.month == now.month && d.day == now.day,
        )
        .length;
  }

  static Future<bool> canLogMore(String scopeId) async {
    return (await getTodayCount(scopeId)) < maxPerDay;
  }

  /// Regista uma escovagem agora — não faz nada se o limite diário já foi
  /// atingido (chamador deve verificar [canLogMore] antes, se quiser avisar
  /// o utilizador).
  static Future<void> logToday(String scopeId) async {
    if (!(await canLogMore(scopeId))) return;
    // Usa as entradas já podadas (só da semana atual) para não ressuscitar
    // registos de semanas anteriores ao gravar de volta.
    final entries = await _getEntries(scopeId);
    entries.add(DateTime.now());
    final prefs = await SharedPreferences.getInstance();
    await prefs.setStringList(
      _key(_kDatesKey, scopeId),
      entries.map((d) => d.toIso8601String()).toList(),
    );
  }

  /// Já atingiu o limite diário de [maxPerDay] escovagens hoje?
  static Future<bool> hasReachedDailyLimit(String scopeId) async {
    return (await getTodayCount(scopeId)) >= maxPerDay;
  }

  /// Conta quantas escovagens foram registadas na semana atual
  /// (segunda-feira a domingo). [_getEntries] já descarta semanas
  /// anteriores, por isso todas as entradas devolvidas já são desta semana.
  static Future<int> getWeekCount(String scopeId) async {
    return (await _getEntries(scopeId)).length;
  }
}
