using Data.SeaHavenIndustries; using SeaHaven.Services.Interfaces; namespace SeaHaven.Services.Implementation { public class SyncFieldMergePolicy : ISyncFieldMergePolicy { private static readonly HashSet ShocOwnedFieldSet = new(StringComparer.OrdinalIgnoreCase) { "LifecycleStatus", "AssignTo", "ScheduledDate", "ScheduledEnd", "TargetWeek", "ScheduleWeekOnly", "DueDate", "Description", "WorkerOrderTitle", "SiteCode", "Building", "LocationId", "WorkOrderType", "DocStatus", "Trade", "Problem", "Priority", "InternalWONumber", "Status" }; private readonly IWorkOrderFieldLockService _fieldLocks; private readonly IWorkOrderAuditService _audit; public SyncFieldMergePolicy(IWorkOrderFieldLockService fieldLocks, IWorkOrderAuditService audit) { _fieldLocks = fieldLocks; _audit = audit; } public IReadOnlySet ShocOwnedFields => ShocOwnedFieldSet; public bool CanSyncOverwrite(int workOrderId, string fieldName) => !_fieldLocks.IsLockedAsync(workOrderId, fieldName).GetAwaiter().GetResult(); public async Task TryApplyAsync(WorkOrderSyncContext context, string fieldName, object? incomingValue) { if (incomingValue == null) return false; if (await context.FieldLocks.IsLockedAsync(context.WorkOrder.Id, fieldName)) { var current = GetFieldValue(context.WorkOrder, fieldName); await context.Audit.LogSyncRejectedAsync( context.WorkOrder.Id, fieldName, current, incomingValue.ToString()); return false; } ApplyField(context.WorkOrder, fieldName, incomingValue); return true; } private static string? GetFieldValue(WorkOrder wo, string fieldName) => fieldName switch { "Description" => wo.Description, "WorkerOrderTitle" => wo.WorkerOrderTitle, "Status" => wo.Status, "DueDate" => wo.DueDate?.ToString("O"), "SiteCode" => wo.SiteCode, "Building" => wo.Building, "Priority" => wo.Priority, "Severity" => wo.Severity, _ => null }; private static void ApplyField(WorkOrder wo, string fieldName, object incomingValue) { switch (fieldName) { case "Description": wo.Description = incomingValue.ToString(); break; case "WorkerOrderTitle": wo.WorkerOrderTitle = incomingValue.ToString(); break; case "Status": wo.Status = incomingValue.ToString(); break; case "DueDate" when incomingValue is DateTime dt: wo.DueDate = dt; break; case "SiteCode": wo.SiteCode = incomingValue.ToString(); break; case "Building": wo.Building = incomingValue.ToString(); break; case "Priority": wo.Priority = incomingValue.ToString(); break; case "Severity": wo.Severity = incomingValue.ToString(); break; } } } }