import '../models/user_profile.dart'; import '../models/cycle_entry.dart'; class CycleInfo { final CyclePhase phase; final int dayOfCycle; final int daysUntilPeriod; final bool isPeriodExpected; CycleInfo({ required this.phase, required this.dayOfCycle, required this.daysUntilPeriod, required this.isPeriodExpected, }); @override bool operator ==(Object other) => identical(this, other) || other is CycleInfo && runtimeType == other.runtimeType && phase == other.phase && dayOfCycle == other.dayOfCycle && daysUntilPeriod == other.daysUntilPeriod && isPeriodExpected == other.isPeriodExpected; @override int get hashCode => phase.hashCode ^ dayOfCycle.hashCode ^ daysUntilPeriod.hashCode ^ isPeriodExpected.hashCode; } class CycleService { /// Calculates the current cycle information based on user profile static CycleInfo calculateCycleInfo(UserProfile? user) { if (user?.lastPeriodStartDate == null) { return CycleInfo( phase: CyclePhase.follicular, dayOfCycle: 1, daysUntilPeriod: user?.averageCycleLength ?? 28, isPeriodExpected: false, ); } final lastPeriod = user!.lastPeriodStartDate!; final cycleLength = user.averageCycleLength; final now = DateTime.now(); // Normalize dates to midnight for accurate day counting final startOfToday = DateTime(now.year, now.month, now.day); final startOfLastPeriod = DateTime(lastPeriod.year, lastPeriod.month, lastPeriod.day); final daysSinceLastPeriod = startOfToday.difference(startOfLastPeriod).inDays + 1; // Handle cases where last period was long ago (more than one cycle) final dayOfCycle = ((daysSinceLastPeriod - 1) % cycleLength) + 1; final daysUntilPeriod = cycleLength - dayOfCycle; CyclePhase phase; if (dayOfCycle <= 5) { phase = CyclePhase.menstrual; } else if (dayOfCycle <= 13) { phase = CyclePhase.follicular; } else if (dayOfCycle <= 16) { phase = CyclePhase.ovulation; } else { phase = CyclePhase.luteal; } return CycleInfo( phase: phase, dayOfCycle: dayOfCycle, daysUntilPeriod: daysUntilPeriod, isPeriodExpected: daysUntilPeriod <= 0 || dayOfCycle <= 5, ); } /// Format cycle day for display static String getDayOfCycleDisplay(int day) => 'Day $day'; /// Get phase description static String getPhaseDescription(CyclePhase phase) { switch (phase) { case CyclePhase.menstrual: return 'Your body is resting and clearing. Be gentle with yourself.'; case CyclePhase.follicular: return 'Energy and optimism are rising. A great time for new projects.'; case CyclePhase.ovulation: return 'You are at your peak energy and fertility.'; case CyclePhase.luteal: return 'Progesterone is rising. You may feel more introverted or sensitive.'; } } }