using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; 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 { /// /// Repositorio de archivo para observaciones de bombas. /// Colección: archive_pumpobservations (configurable por ApiSettings.ArchivePumpObservations). /// public class PumpArchiveRepository : MongoRepository, IPumpArchiveRepository { private readonly ApiSettings _apiSettings; /// /// Initializes a new instance of the class, forwarding to the base repository and storing the resolved configuration for subsequent operations. /// /// The wrapper whose supplies the current . /// The connection passed to the base class constructor. /// public PumpArchiveRepository(IOptions apiSettings, IMongoDatabase database) : base(database) { _apiSettings = apiSettings.Value; } /// /// Returns the agreed MongoDB collection name used to store archived pump observations for patients, falling back to the default value when the corresponding setting is not configured. /// /// The collection name to use, either the value configured in ArchivePatientsPumpobservations or the default archive_pumpobservations. /// public override string GetCollectionName() { // Nombre de colección pactado: "archive_pumpobservations" return _apiSettings.ArchivePatientsPumpobservations ?? "archive_pumpobservations"; } /// /// Creates the MongoDB indexes required by the collection: an ascending index on for patient-based lookups and audits, a compound index on (ascending) and (descending) for per-device timelines, and a descending index on for chronological ordering. /// /// public override async Task CreateIndexes() { var indexModels = new List> { // Búsquedas por paciente (audit / restauraciones) new CreateIndexModel( Builders.IndexKeys.Ascending(x => x.PatientId), new CreateIndexOptions { Name = "ix_patientId" }), // Timeline por dispositivo (útil para auditorías por equipo) new CreateIndexModel( Builders.IndexKeys .Ascending(x => x.DeviceId) .Descending(x => x.Time), new CreateIndexOptions { Name = "ix_deviceId_time" }), // Orden temporal simple new CreateIndexModel( Builders.IndexKeys.Descending(x => x.Time), new CreateIndexOptions { Name = "ix_time" }) }; await Collection.Indexes.CreateManyAsync(indexModels); } /// /// Asynchronously inserts a into the underlying MongoDB collection. /// /// The pump observation to persist. public async Task InsertAsync(PumpObservation obs) { await Collection.InsertOneAsync(obs); } /// /// Asynchronously inserts a batch of pump observations into the underlying data store. If the collection is empty, the method completes without performing any insertion. /// /// The pump observations to insert into the collection. public async Task InsertManyAsync(IEnumerable observations) { var list = observations as IList ?? observations.ToList(); if (list.Count == 0) return; await Collection.InsertManyAsync(list); } /// /// Retrieves a collection of records for a specific patient, optionally filtered by a time range and limited in count, sorted by time in descending order. /// /// The identifier of the patient whose pump observations are being queried. /// Optional inclusive lower bound for the observation time. When provided, only observations on or after this time are returned. /// Optional inclusive upper bound for the observation time. When provided, only observations on or before this time are returned. /// Optional maximum number of observations to return. When null, all matching observations are returned. /// A task that represents the asynchronous operation. The task result contains an of matching observations ordered from newest to oldest. public async Task> FindByPatientIdAsync( ObjectId patientId, DateTime? from = null, DateTime? to = null, int? limit = null) { var filter = Builders.Filter.Eq(x => x.PatientId, patientId); 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 query = Collection.Find(filter).SortByDescending(x => x.Time); if (limit.HasValue) query = query.Limit(limit.Value) as IOrderedFindFluent; return await query.ToListAsync(); } /// /// Deletes all pump observations whose recording time is earlier than the specified cutoff date. /// /// The cutoff date; observations with a timestamp before this value are removed. public async Task DeleteBeforeDate(DateTime addDays) { var filter = Builders.Filter.Lt(x => x.Time, addDays); await Collection.DeleteManyAsync(filter); } } }