using System.Reflection; using adas_core.Application.Repositories.Interfaces; using adas_core.Application.Services.Interfaces; using adas_core.Domain.Models; using adas_core.Domain.Models.AppSettings; using adas_core.Domain.Models.MongoModels; using adas_core.Domain.Models.Pumps; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace adas_core.Application.Services; public class ConfigUnitsService( IConfigUnitsRepository configUnitsRepository, IOptions apiSettings, ILogger logger) : IConfigUnitsService { private static ConfigUnits? _config; private static DateTime _nextRefresh = DateTime.MinValue; private readonly bool _configUnitsRequired = apiSettings.Value.ConfigUnitsRequired; private readonly string _key = apiSettings.Value.ConfigUnitsKey ?? "PV1"; private readonly int? _refreshTimeout = apiSettings.Value.ConfigObservation?.Refresh; public async Task Map(T obs) where T : BasePatientObservation { if (!_configUnitsRequired) return obs; var conf = !string.IsNullOrEmpty(obs.Units) ? await Get(obs.Units) : null; return conf == null ? obs : MapConf(obs, conf); } public async Task Map(PumpObservation obs) { if (!_configUnitsRequired) return obs; //Para cada propiedad de la observación que sea del tipo PumpValue llama a GetByCodeSysAndCode(PumpValue) await MapPumpValues(obs); // var conf = !string.IsNullOrEmpty(obs.Units) ? await Get(obs.Units) : null; // return conf == null ? obs : MapConf(obs, conf); return obs; } /// /// Recorre recursivamente las propiedades del objeto para encontrar y convertir PumpValues. /// private async Task MapPumpValues(object? targetObject) { if (targetObject == null) return; var properties = targetObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var property in properties) { var propertyValue = property.GetValue(targetObject); if (propertyValue == null) continue; if (property.PropertyType == typeof(CommonPumpTypes.PumpValue)) { var pumpValue = (CommonPumpTypes.PumpValue)propertyValue; if (string.IsNullOrEmpty(pumpValue.Units)) continue; var conf = await Get(pumpValue.Units); if (conf != null) pumpValue.Units = conf.Value; } // En este caso Syringe es una clase que tienen un pumpValue else if (property.PropertyType.IsClass && property.PropertyType != typeof(string)) { // Llamada recursiva para inspeccionar las propiedades anidadas await MapPumpValues(propertyValue); } } } private T MapConf(T obs, ConfigUnitItem conf) where T : BasePatientObservation { if (obs is not PatientObservation pobs) return obs; logger.LogDebug("Mapping config Unit obs: {obs} to units: {conf}", obs, conf.Value); pobs.Units = conf.Value; return obs; } public async Task Get(string code) { var result = await GetConfig(); return result?.Items?.FirstOrDefault(i => i.Code == code); } private async Task GetConfig() { try { if (_config != null && DateTime.Now <= _nextRefresh) return _config; _config = await configUnitsRepository.FindById(_key); _nextRefresh = _refreshTimeout.HasValue ? DateTime.Now.AddSeconds(_refreshTimeout.Value) : DateTime.MinValue; return _config; } catch (Exception ex) { logger.LogError(ex, "ERROR READ config_units: {_key}: {ex}", _key, ex.Message); return null; } } }