using adas_core.Application.Repositories.Interfaces; using adas_core.Domain.Models; using adas_core.Domain.Models.AppSettings; using adas_core.Domain.Models.GroupedObservations; using adas_core.Domain.Models.MongoModels; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using MongoDB.Bson; using MongoDB.Driver; using MongoUtils = adas_core.Infrastructure.Utils.MongoUtils; namespace adas_core.Infrastructure.Repositories; public class AlarmRepository : MongoRepository, IAlarmRepository { private readonly ApiSettings _apiSettings; private readonly ILogger _logger; public AlarmRepository(IOptions apiSettings, IMongoDatabase database, ILogger logger) : base(database) { if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings)); _logger = logger; _apiSettings = apiSettings.Value; } //For testing public async Task> AggregatedPatientLastObservationsByField(ObjectId patientId, List? filterObservations = null) { try { var results = new List(); IAsyncCursor? cursor; var builder = Builders.Filter; if (filterObservations != null) { foreach (var obs in filterObservations) { FilterDefinition filter; if (obs is { OnlyExpired: true, Name: not null }) filter = builder.And( builder.Eq(o => o.PatientId, patientId), builder.Eq(o => o.Name, obs.Name), builder.Eq("Expired", obs.OnlyExpired) //builder.Eq(o => o.Expired, obs.OnlyExpired) ); else filter = builder.And( builder.Eq(o => o.PatientId, patientId), builder.Eq(o => o.Name, obs.Name) ); cursor = await Collection.FindAsync( filter, new FindOptions { Sort = Builders.Sort.Descending("time").Descending("id"), Limit = obs.Last }); results.AddRange(cursor.ToEnumerable()); } } else { var filter = builder.Eq(o => o.PatientId, patientId); cursor = await Collection.FindAsync( filter, new FindOptions { Sort = Builders.Sort.Descending("time").Descending("id") }); results.AddRange(cursor.ToEnumerable()); } return results; } catch (Exception ex) { _logger.LogError("Error aggregated patient last observations by field {exMessage}", ex.Message); throw; } } public async Task> AggregatedPatientNotExpiredObservationsByField( ObjectId patientId, List? filterObservations, List configAlarm) { try { var results = new List(); IAsyncCursor? cursor; var builder = Builders.Filter; if (filterObservations != null) { foreach (var obs in filterObservations) { FilterDefinition filter; var conf = configAlarm.FirstOrDefault(c => c.Name == obs.Name); if (obs is { OnlyExpired: true, Name: not null }) filter = builder.And( builder.Eq(o => o.PatientId, patientId), builder.Eq(o => o.Name, obs.Name), builder.Eq("Expired", obs.OnlyExpired) //builder.Eq(o => o.Expired, obs.OnlyExpired) ); else filter = builder.And( builder.Eq(o => o.PatientId, patientId), builder.Eq(o => o.Name, obs.Name) ); if (conf is { Expires: not null }) { var dateNow = DateTime.UtcNow.AddSeconds(conf.Expires.Value * -1); filter = builder.And( filter, builder.Gte(o => o.Time, dateNow) ); } cursor = await Collection.FindAsync( filter, new FindOptions { Sort = Builders.Sort.Descending("time").Descending("id") }); results.AddRange(cursor.ToEnumerable()); } } else { var filter = builder.Eq(o => o.PatientId, patientId); cursor = await Collection.FindAsync( filter, new FindOptions { Sort = Builders.Sort.Descending("time").Descending("id") }); results.AddRange(cursor.ToEnumerable()); } return results; } catch (Exception ex) { _logger.LogError("Error aggregated patient last observations by field {exMessage}", ex.Message); throw; } } public override string GetCollectionName() { return _apiSettings.PatientsAlarms ?? "patients_alarms"; } public override async Task CreateIndexes() { try { var options = new CreateIndexOptions { Background = true, Unique = false }; var indexes = new List> { new("{ patientid: 1 }", options), new("{ patientid: 1, name: 1 }", options), new("{ name: 1 }", options), new("{ patientid: 1, name: 1 , time: 1}", options) }; await MongoUtils.EnsureIndexes(Collection, indexes); } catch (Exception e) { _logger.LogError( "error creating indexes for observation collection {eMessage} TRACE: {eStackTrace}", e.Message, e.StackTrace); throw; } } }