using Data.SeaHavenIndustries.Enums; namespace SeaHaven.Services.Helpers { public static class WorkOrderBoardMutationRules { private static readonly HashSet ReadOnlyStatuses = LifecycleStatusSets.Terminal.Cast().ToHashSet(); public static bool IsReadOnly(LifecycleStatus? status) => ReadOnlyStatuses.Contains(status); public static bool IsFullyLocked(LifecycleStatus? status) => status == LifecycleStatus.Canceled; public static bool IsCoreLocked(LifecycleStatus? status) => status == LifecycleStatus.Completed; public static bool CanPatchBoardField(LifecycleStatus? status, string field) { if (IsFullyLocked(status)) return false; if (!IsCoreLocked(status)) return true; return field.Equals(WorkOrderBoardFieldNames.FlagColor, StringComparison.OrdinalIgnoreCase); } public static bool CanMutateComments(LifecycleStatus? status) => !IsFullyLocked(status); public static bool CanMutateExtraMedia(LifecycleStatus? status, WorkOrderMediaCategory? category) { if (IsFullyLocked(status)) return false; if (!IsCoreLocked(status)) return true; return IsExtraDocsFamily(category); } public static bool IsExtraDocsFamily(WorkOrderMediaCategory? category) { var resolved = category ?? WorkOrderMediaCategory.Extra; return resolved == WorkOrderMediaCategory.Extra || resolved == WorkOrderMediaCategory.Aveta; } public static bool ShouldBlockStatusChangeWhenPastDue(string field, bool isPastDue) => field.Equals(WorkOrderBoardFieldNames.LifecycleStatus, StringComparison.OrdinalIgnoreCase) && isPastDue; /// /// SHOC rule: Incomplete + specific scheduled date + assignee → Scheduled. /// Week-only targets do not auto-schedule (same as ). /// public static bool ShouldAutoSchedule( LifecycleStatus? status, DateTime? scheduledDate, string? assignTo, bool? scheduleWeekOnly = null) => status == LifecycleStatus.Incomplete && scheduleWeekOnly != true && scheduledDate.HasValue && !string.IsNullOrWhiteSpace(assignTo); public static bool IsReschedule(DateTime? previousDate, DateTime? newDate) => previousDate.HasValue && newDate.HasValue && previousDate.Value.Date != newDate.Value.Date; public static DateOnly? ComputeOriginalWeek(DateTime? scheduledDate) => scheduledDate.HasValue ? DateOnly.FromDateTime(GetWeekStartMonday(scheduledDate.Value)) : null; public static DateTime GetWeekStartMonday(DateTime date) { var diff = (7 + (date.DayOfWeek - DayOfWeek.Monday)) % 7; return date.Date.AddDays(-diff); } } }