using SeaHaven.Services.Helpers; namespace SeaHavenIndustries.Tests; public class WorkOrderAddonCutoffTests { // Schedule week Mon 2026-06-22 → cutoff Sat 2026-06-20 23:59:59 UTC private static readonly DateTime ScheduleMonday = new(2026, 6, 22, 0, 0, 0, DateTimeKind.Utc); private static readonly DateTime ExpectedCutoff = new(2026, 6, 20, 23, 59, 59, DateTimeKind.Utc); [Fact] public void GetAddonCutoffUtc_FromScheduledDate_IsPriorSaturdayEndOfDay() { // Wednesday in schedule week var cutoff = WorkOrderAddonCutoff.GetAddonCutoffUtc(new DateTime(2026, 6, 24, 15, 0, 0, DateTimeKind.Utc)); Assert.Equal(ExpectedCutoff, cutoff); } [Fact] public void GetAddonCutoffUtc_FromTargetWeekMonday_IsPriorSaturdayEndOfDay() { var cutoff = WorkOrderAddonCutoff.GetAddonCutoffUtc(new DateOnly(2026, 6, 22)); Assert.Equal(ExpectedCutoff, cutoff); } [Fact] public void GetAddonCutoffUtc_FromMondayAnchor_MatchesGetWeekStartMondayMinusTwo() { var monday = WorkOrderBoardMutationRules.GetWeekStartMonday(ScheduleMonday); Assert.Equal(ScheduleMonday.Date, monday.Date); Assert.Equal(ExpectedCutoff, WorkOrderAddonCutoff.GetAddonCutoffUtc(ScheduleMonday)); } [Fact] public void Compute_AfterCutoff_ReturnsTrue_IgnoresManualFalse() { var created = new DateTime(2026, 6, 21, 0, 0, 0, DateTimeKind.Utc); var result = WorkOrderAddonCutoff.ComputeIsAddOnAtCreation( created, scheduledDate: new DateTime(2026, 6, 24), targetWeek: null, manualOverride: false); Assert.True(result); } [Fact] public void Compute_BeforeCutoff_ReturnsFalse_IgnoresManualTrue() { var created = new DateTime(2026, 6, 20, 23, 59, 59, DateTimeKind.Utc); var result = WorkOrderAddonCutoff.ComputeIsAddOnAtCreation( created, scheduledDate: new DateTime(2026, 6, 24), targetWeek: null, manualOverride: true); Assert.False(result); } [Fact] public void Compute_ExactlyAtCutoff_ReturnsFalse() { var result = WorkOrderAddonCutoff.ComputeIsAddOnAtCreation( ExpectedCutoff, scheduledDate: ScheduleMonday, targetWeek: null, manualOverride: true); Assert.False(result); } [Fact] public void Compute_TargetWeekOnly_UsesCutoff() { var after = WorkOrderAddonCutoff.ComputeIsAddOnAtCreation( new DateTime(2026, 6, 21, 12, 0, 0, DateTimeKind.Utc), scheduledDate: null, targetWeek: new DateOnly(2026, 6, 22), manualOverride: false); var before = WorkOrderAddonCutoff.ComputeIsAddOnAtCreation( new DateTime(2026, 6, 19, 12, 0, 0, DateTimeKind.Utc), scheduledDate: null, targetWeek: new DateOnly(2026, 6, 22), manualOverride: true); Assert.True(after); Assert.False(before); } [Fact] public void Compute_NoSchedule_UsesManualOverride() { Assert.True(WorkOrderAddonCutoff.ComputeIsAddOnAtCreation( DateTime.UtcNow, null, null, manualOverride: true)); Assert.False(WorkOrderAddonCutoff.ComputeIsAddOnAtCreation( DateTime.UtcNow, null, null, manualOverride: false)); Assert.False(WorkOrderAddonCutoff.ComputeIsAddOnAtCreation( DateTime.UtcNow, null, null, manualOverride: null)); } [Fact] public void Compute_ScheduledDatePreferredOverTargetWeek() { // Target week far future (cutoff after created) would be false; // scheduled date near past (cutoff before created) → true. var created = new DateTime(2026, 7, 1, 0, 0, 0, DateTimeKind.Utc); var result = WorkOrderAddonCutoff.ComputeIsAddOnAtCreation( created, scheduledDate: new DateTime(2026, 6, 24), targetWeek: new DateOnly(2099, 1, 5), manualOverride: false); Assert.True(result); } // Rescheduled on Wed 2026-06-24: the week of 06-22 is past its cutoff (Sat 06-20 23:59:59), // the week of 06-29 is not (cutoff Sat 06-27 23:59:59). private static readonly DateTime RescheduledAt = new(2026, 6, 24, 10, 0, 0, DateTimeKind.Utc); [Fact] public void RecalculateOnReschedule_NoSchedule_ReturnsFalse() { Assert.False(WorkOrderAddonCutoff.RecalculateIsAddOnOnReschedule( currentIsAddOn: true, previousScheduledDate: new DateTime(2026, 6, 24), previousTargetWeek: null, scheduledDate: null, targetWeek: null, RescheduledAt)); } [Fact] public void RecalculateOnReschedule_IntoWeekPastCutoff_TurnsOnForWorkOrderCreatedLongBefore() { // SH-412: the WO was created weeks earlier; it arrives in the current week at the // moment of the reschedule, which is already past that week's cutoff. var result = WorkOrderAddonCutoff.RecalculateIsAddOnOnReschedule( currentIsAddOn: false, previousScheduledDate: new DateTime(2026, 7, 8), previousTargetWeek: null, scheduledDate: new DateTime(2026, 6, 25), targetWeek: null, RescheduledAt); Assert.True(result); } [Fact] public void RecalculateOnReschedule_IntoWeekBeforeCutoff_TurnsOff() { var result = WorkOrderAddonCutoff.RecalculateIsAddOnOnReschedule( currentIsAddOn: true, previousScheduledDate: new DateTime(2026, 6, 24), previousTargetWeek: null, scheduledDate: new DateTime(2026, 7, 1), targetWeek: null, RescheduledAt); Assert.False(result); } [Theory] [InlineData(true)] [InlineData(false)] public void RecalculateOnReschedule_WithinSameWeek_KeepsCurrentValue(bool currentIsAddOn) { var result = WorkOrderAddonCutoff.RecalculateIsAddOnOnReschedule( currentIsAddOn, previousScheduledDate: new DateTime(2026, 6, 22), previousTargetWeek: null, scheduledDate: new DateTime(2026, 6, 26), targetWeek: null, RescheduledAt); Assert.Equal(currentIsAddOn, result); } [Fact] public void RecalculateOnReschedule_FirstScheduleIntoWeekPastCutoff_TurnsOn() { var result = WorkOrderAddonCutoff.RecalculateIsAddOnOnReschedule( currentIsAddOn: false, previousScheduledDate: null, previousTargetWeek: null, scheduledDate: new DateTime(2026, 6, 26), targetWeek: null, RescheduledAt); Assert.True(result); } }