import 'package:flutter_timezone/flutter_timezone.dart'; import 'package:timezone/data/latest.dart' as tzdata; import 'package:timezone/timezone.dart' as tz; class TimeService { static const String estLocationName = 'America/New_York'; static bool _initialized = false; static Future initialize() async { if (_initialized) { return; } tzdata.initializeTimeZones(); final localName = await FlutterTimezone.getLocalTimezone(); tz.setLocalLocation(tz.getLocation(localName)); _initialized = true; } static tz.Location get est => tz.getLocation(estLocationName); static tz.TZDateTime estNow() => tz.TZDateTime.now(est); static DateTime localNow() => tz.TZDateTime.now(tz.local); static tz.TZDateTime estDeadlinePassedAt(int year, int month) { return tz.TZDateTime(est, year, month, 2, 0, 0); } static tz.TZDateTime estFirstReminderAt(int year, int month) { return tz.TZDateTime(est, year, month, 2, 0, 5); } static bool isOnTimeByDeadline(DateTime paidAtUtc, int year, int month) { final estPaidAt = tz.TZDateTime.from(paidAtUtc, est); final cutoff = tz.TZDateTime(est, year, month, 1, 23, 59, 59, 999); return !estPaidAt.isAfter(cutoff); } static DateTime applyQuietHours({ required DateTime localTime, required int quietHourStart, required int fallbackHour, }) { if (localTime.hour >= quietHourStart) { return DateTime( localTime.year, localTime.month, localTime.day + 1, fallbackHour, ); } return localTime; } static DateTime nextEligibleLocal({ required DateTime candidate, required int quietHourStart, required int fallbackHour, }) { final now = localNow(); var result = candidate; if (result.isBefore(now)) { result = now.add(const Duration(minutes: 1)); } if (result.hour >= quietHourStart) { result = DateTime( result.year, result.month, result.day + 1, fallbackHour, ); } return result; } static bool monthAtOrAfter({ required int year, required int month, required int pivotYear, required int pivotMonth, }) { return year > pivotYear || (year == pivotYear && month >= pivotMonth); } static bool monthBefore({ required int year, required int month, required int otherYear, required int otherMonth, }) { return year < otherYear || (year == otherYear && month < otherMonth); } static String monthKey(int year, int month) { return '$year-${month.toString().padLeft(2, '0')}'; } }