using Microsoft.Extensions.Options; using SeaHaven.DataServices.Interfaces; using SeaHaven.Services.DTOs; using SeaHaven.Services.Interfaces; namespace SeaHaven.Services.Implementation { public class WorkOrderOpsHealthService : IWorkOrderOpsHealthService { private readonly IWorkOrderOpsHealthDataService _healthData; private readonly IWorkOrderJobRunStateAccessor _runState; private readonly WorkOrderOpsHealthOptions _options; public WorkOrderOpsHealthService( IWorkOrderOpsHealthDataService healthData, IWorkOrderJobRunStateAccessor runState, IOptions options) { _healthData = healthData; _runState = runState; _options = options.Value; } public async Task GetHealthAsync(CancellationToken cancellationToken = default) { var since = DateTime.UtcNow.AddHours(-24); var syncRejected = await _healthData.CountSyncRejectedSinceAsync(since, cancellationToken); var fieldLocks = await _healthData.CountFieldLocksAsync(cancellationToken); var state = _runState.State; var ledgerWeekRolled = await _healthData.GetLastWeekRolledProcessedAtAsync(cancellationToken); return new WorkOrderOpsHealthDto { LastWeekRolledRunUtc = state.LastWeekRolledRunUtc ?? ledgerWeekRolled, LastPastDueCacheRunUtc = state.LastPastDueCacheRunUtc, LastWeekRolledError = state.LastWeekRolledError, LastPastDueCacheError = state.LastPastDueCacheError, SyncRejectedLast24h = syncRejected, FieldLockCount = fieldLocks, SyncEnabled = _options.SyncEnabled, IngestEnabled = _options.IngestEnabled, LegacyDeprecationEnabled = _options.LegacyDeprecationEnabled, LegacySunsetDate = _options.LegacySunsetDate, CheckedAtUtc = DateTime.UtcNow }; } } /// Options bridged from API configuration for health snapshots. public class WorkOrderOpsHealthOptions { public bool SyncEnabled { get; set; } = true; public bool IngestEnabled { get; set; } = true; public bool LegacyDeprecationEnabled { get; set; } public string? LegacySunsetDate { get; set; } } /// Shared in-memory job run timestamps (API hosted services + ops health). public class WorkOrderJobRunStateAccessor : IWorkOrderJobRunStateAccessor { public WorkOrderJobRunState State { get; } = new(); } }