using Data.SeaHavenIndustries; using Data.SeaHavenIndustries.Enums; using SeaHaven.DataServices.Interfaces; using SeaHaven.Services.Constants; using SeaHaven.Services.Interfaces; namespace SeaHaven.Services.Implementation { public class WorkOrderAuditService : IWorkOrderAuditService { private readonly IWorkOrderAuditDataService _auditData; private readonly IWorkOrderFieldLockService _fieldLocks; public WorkOrderAuditService(IWorkOrderAuditDataService auditData, IWorkOrderFieldLockService fieldLocks) { _auditData = auditData; _fieldLocks = fieldLocks; } public Task LogStatusChangedAsync(int workOrderId, string? oldStatus, string? newStatus, string? actorId) => LogAsync(workOrderId, AuditActionType.StatusChanged, AuditEventType.Manual, AuditActorType.Dispatcher, WorkOrderFieldNames.LifecycleStatus, oldStatus, newStatus, actorId); public Task LogAssignmentChangedAsync(int workOrderId, string? oldValue, string? newValue, string? actorId) => LogAsync(workOrderId, AuditActionType.AssignmentChanged, AuditEventType.Manual, AuditActorType.Dispatcher, WorkOrderFieldNames.AssignTo, oldValue, newValue, actorId); public Task LogSyncRejectedAsync(int workOrderId, string fieldName, string? oldValue, string? newValue) => LogAsync(workOrderId, AuditActionType.SyncRejected, AuditEventType.Sync, AuditActorType.Sync, fieldName, oldValue, newValue); public Task LogWeekRolledAsync(int workOrderId, int oldCarriedOver, int newCarriedOver, string correlationId) => LogAsync( workOrderId, AuditActionType.WeekRolled, AuditEventType.System, AuditActorType.System, "CarriedOver", oldCarriedOver.ToString(), newCarriedOver.ToString(), correlationId: correlationId); public Task StageFieldChangedAsync(int workOrderId, string fieldName, string? oldValue, string? newValue, string? actorId, int? dispatchId = null) => StageAuditAsync(workOrderId, AuditActionType.FieldChanged, fieldName, oldValue, newValue, actorId, dispatchId); public Task StageStatusChangedAsync(int workOrderId, string? oldStatus, string? newStatus, string? actorId) => StageAuditAsync(workOrderId, AuditActionType.StatusChanged, WorkOrderFieldNames.LifecycleStatus, oldStatus, newStatus, actorId); public Task StageAssignmentChangedAsync(int workOrderId, string? oldValue, string? newValue, string? actorId) => StageAuditAsync(workOrderId, AuditActionType.AssignmentChanged, WorkOrderFieldNames.AssignTo, oldValue, newValue, actorId); public Task StageCreatedAsync(int workOrderId, string? actorId, string? woNumber) => StageAuditAsync(workOrderId, AuditActionType.Create, "WorkOrder", null, woNumber, actorId); public async Task LogAsync( int workOrderId, AuditActionType action, AuditEventType eventType, AuditActorType actorType, string fieldName, string? oldValue, string? newValue, string? actorId = null, int? dispatchId = null, string? correlationId = null) { Enqueue(workOrderId, action, eventType, actorType, fieldName, oldValue, newValue, actorId, dispatchId, correlationId); if (eventType == AuditEventType.Manual && (action == AuditActionType.FieldChanged || action == AuditActionType.StatusChanged || action == AuditActionType.AssignmentChanged)) { await _fieldLocks.LockFieldAsync(workOrderId, fieldName, actorId); } await _auditData.PersistAsync(CancellationToken.None); } private async Task StageAuditAsync( int workOrderId, AuditActionType action, string fieldName, string? oldValue, string? newValue, string? actorId, int? dispatchId = null) { Enqueue(workOrderId, action, AuditEventType.Manual, AuditActorType.Dispatcher, fieldName, oldValue, newValue, actorId, dispatchId); if (action == AuditActionType.FieldChanged || action == AuditActionType.StatusChanged || action == AuditActionType.AssignmentChanged) { await _fieldLocks.LockFieldAsync(workOrderId, fieldName, actorId); } } private void Enqueue( int workOrderId, AuditActionType action, AuditEventType eventType, AuditActorType actorType, string fieldName, string? oldValue, string? newValue, string? actorId, int? dispatchId = null, string? correlationId = null) { _auditData.EnqueueAuditLog(new WorkOrderAuditLog { WorkOrderId = workOrderId, UserId = actorId, FieldName = fieldName, OldValue = oldValue ?? "", NewValue = newValue ?? "", Action = action.ToString(), EventType = eventType.ToString(), ActorType = actorType.ToString(), DispatchId = dispatchId, CorrelationId = correlationId, CreatedAt = DateTime.UtcNow }); } } }