using adas_core.Application.Repositories.Interfaces; using adas_core.Domain.Models.AppSettings; using adas_core.Domain.Models.Pumps; using Microsoft.Extensions.Options; using MongoDB.Bson; using MongoDB.Driver; namespace adas_core.Infrastructure.Repositories; /// /// Represents a MongoDB-backed repository for documents, exposing pump alarm event-specific data access through the contract. /// /// /// Inherits the generic MongoDB persistence capabilities of , specializing them for the entity type. /// public class PumpAlarmEventRepository : MongoRepository, IPumpAlarmEventRepository { private readonly ApiSettings _apiSettings; /// /// Initializes a new instance of the repository, capturing the configured from and forwarding to the base repository for persistence operations. /// /// The wrapper that exposes the application's . /// The passed to the base constructor and used to perform MongoDB operations. /// public PumpAlarmEventRepository(IOptions apiSettings, IMongoDatabase database) : base(database) { _apiSettings = apiSettings.Value; } /// /// Retrieves the collection name used for pump alarm events, returning the configured value from _apiSettings.PumpAlarmEvent when set, or falling back to the default "pump_alarm_event". /// /// The configured pump alarm event collection name, or the default "pump_alarm_event" when no configuration value is available. /// public override string GetCollectionName() { return _apiSettings.PumpAlarmEvent ?? "pump_alarm_event"; } /// /// Creates the MongoDB indexes for the PumpAlarmEvent collection, optimizing the most common query patterns: device lookup with reverse-chronological time ordering, time-only range queries, patient lookup, and device queries filtered by alarm type. /// /// public override async Task CreateIndexes() { var indexModels = new List> { // Principal para consultas por bomba y orden temporal new( Builders.IndexKeys .Ascending(x => x.DeviceId) .Descending(x => x.Time), new CreateIndexOptions { Name = "ix_deviceId_time" }), // Índice temporal new( Builders.IndexKeys.Descending(x => x.Time), new CreateIndexOptions { Name = "ix_time" }), // por paciente new( Builders.IndexKeys.Ascending(x => x.PatientId), new CreateIndexOptions { Name = "ix_patientId" }), //por tipo de alarma dentro de una bomba new( Builders.IndexKeys .Ascending(x => x.DeviceId) .Ascending(x => x.AlarmType), new CreateIndexOptions { Name = "ix_device_alarmType" }) }; await Collection.Indexes.CreateManyAsync(indexModels); } /// /// Asynchronously inserts a new document into the underlying MongoDB collection. /// /// The record to persist. /// public async Task InsertAsync(PumpAlarmEvent alarmEvent) { await Collection.InsertOneAsync(alarmEvent); } public async Task> FindByDeviceIdAsync(string deviceId, DateTime? from = null, DateTime? to = null, int? limit = null) { var filter = Builders.Filter.Eq(x => x.DeviceId, deviceId); if (from.HasValue) filter &= Builders.Filter.Gte(x => x.Time, from.Value); if (to.HasValue) filter &= Builders.Filter.Lte(x => x.Time, to.Value); var find = Collection.Find(filter).SortByDescending(x => x.Time); if (limit.HasValue) find = find.Limit(limit.Value) as IOrderedFindFluent; return await find.ToListAsync(); } /// /// Asynchronously retrieves the most recent for the device identified by , returning the entry with the latest time stamp, or null if no event exists. /// /// The identifier of the device whose latest alarm event is being retrieved. /// A that yields the latest associated with , or null if no matching event is found. /// public async Task FindLastByDeviceIdAsync(string deviceId) { return await Collection .Find(x => x.DeviceId == deviceId) .SortByDescending(x => x.Time) .FirstOrDefaultAsync(); } /// /// Asynchronously removes all documents linked to the specified patient by deleting every record whose PatientId matches the supplied . /// /// The of the patient whose associated documents should be deleted. /// public async Task DeleteByPatientId(ObjectId patientId) { await Collection.DeleteManyAsync(x => x.PatientId == patientId); } /// /// Asynchronously updates the value of the specified field across multiple documents, replacing occurrences of with , and returns the number of documents that were modified. /// /// The name of the field on whose value should be replaced. /// The new value to assign to the field in matching documents. /// The existing value used to identify documents to be updated. /// The number of documents modified by the bulk update. /// public async Task UpdateManyObjectIdByFiledNameAsync(string fieldName, ObjectId newId, ObjectId oldId) { var filter = Builders.Filter.Eq(fieldName, oldId); var update = Builders.Update.Set(fieldName, newId); var result = await Collection.UpdateManyAsync(filter, update); return result.ModifiedCount; } }