using adas_core.Application.Repositories.Interfaces;
using adas_core.Domain.Enums;
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-based repository for entities, providing concrete data access functionality defined by the contract.
///
public class PumpAlarmStateRepository : MongoRepository, IPumpAlarmStateRepository
{
private readonly ApiSettings _apiSettings;
public PumpAlarmStateRepository(IOptions apiSettings, IMongoDatabase database)
: base(database)
{
_apiSettings = apiSettings.Value;
}
///
/// Gets the collection name for the pump alarm state, returning the value configured in the API settings or the default "pump_alarm_state" when the configuration is not set.
///
/// The configured collection name, or the default "pump_alarm_state" if the API setting is null.
public override string GetCollectionName()
{
return _apiSettings.PumpAlarmState ?? "pump_alarm_state";
}
public override async Task CreateIndexes()
{
var indexModels = new List>
{
// Clave única de alarma activa
new(
Builders.IndexKeys
.Ascending(x => x.DeviceId)
.Ascending(x => x.AlarmType)
.Ascending(x => x.AlarmCodeMdc),
new CreateIndexOptions { Unique = true, Name = "ux_device_alarm" }),
// Indexado por DeviceId
new(
Builders.IndexKeys.Ascending(x => x.DeviceId),
new CreateIndexOptions { Name = "ix_device" }),
// indexado por PatientId
new(
Builders.IndexKeys.Ascending(x => x.PatientId),
new CreateIndexOptions { Name = "ix_patientId" })
};
await Collection.Indexes.CreateManyAsync(indexModels);
}
///
/// Retrieves the first active matching the specified device and optional alarm criteria.
/// The filter is always constrained by , and additionally by and when those values are provided.
/// Returns null when no matching alarm state is found.
///
/// The identifier of the device whose alarm state should be retrieved. Always applied to the query filter.
/// The optional alarm type used to further narrow the filter. When null, the alarm type is not applied.
/// The optional alarm code (MDC) used to further narrow the filter. Ignored when null, empty, or whitespace.
/// A instance if a matching record is found; otherwise, null.
public async Task FindActiveAsync(string deviceId, PumpEnum.AlarmType? alarmType, string? alarmCodeMdc = null)
{
var filter = Builders.Filter.Eq(x => x.DeviceId, deviceId);
if (alarmType.HasValue)
filter &= Builders.Filter.Eq(x => x.AlarmType, alarmType);
if (!string.IsNullOrWhiteSpace(alarmCodeMdc))
filter &= Builders.Filter.Eq(x => x.AlarmCodeMdc, alarmCodeMdc);
return await Collection.Find(filter).FirstOrDefaultAsync();
}
public async Task UpsertActiveAsync(PumpAlarmState state)
{
var filter =
Builders.Filter.Eq(x => x.DeviceId, state.DeviceId) &
Builders.Filter.Eq(x => x.AlarmType, state.AlarmType) &
Builders.Filter.Eq(x => x.AlarmCodeMdc, state.AlarmCodeMdc);
// Revisar si ya existe un documento activo con esa combinación
var existing = await Collection.Find(filter).FirstOrDefaultAsync();
if (existing != null)
state.Id = existing.Id;
else
if (state.Id == ObjectId.Empty)
state.Id = ObjectId.GenerateNewId();
await Collection.ReplaceOneAsync(
filter,
state,
new ReplaceOptions { IsUpsert = true });
}
///
/// Removes pump alarm state records from the collection that match the specified device identifier, optionally narrowed by alarm type and/or alarm code MDC.
///
/// The identifier of the device whose alarm state records should be removed. Used as a mandatory filter criterion.
/// The optional alarm type to further restrict which records are deleted. When , records of any alarm type for the device are removed.
/// The optional alarm code MDC used to further narrow the deletion. Blank or whitespace values are ignored.
public async Task RemoveAsync(string? deviceId, PumpEnum.AlarmType? alarmType, string? alarmCodeMdc = null)
{
var filter = Builders.Filter.Eq(x => x.DeviceId, deviceId);
if (alarmType.HasValue)
filter &= Builders.Filter.Eq(x => x.AlarmType, alarmType);
if (!string.IsNullOrWhiteSpace(alarmCodeMdc))
filter &= Builders.Filter.Eq(x => x.AlarmCodeMdc, alarmCodeMdc);
await Collection.DeleteManyAsync(filter);
}
///
/// Asynchronously deletes all records associated with the specified patient identifier by removing every document whose PatientId matches the supplied value.
///
/// The unique identifier of the patient whose associated records should be removed.
public async Task DeleteByPatientId(ObjectId patientId)
{
await Collection.DeleteManyAsync(p => p.PatientId == patientId);
}
///
/// Asynchronously retrieves all pump alarm states associated with the specified device identifier.
///
/// The unique identifier of the device whose pump alarm states are being queried.
/// A task that represents the asynchronous operation. The task result contains an with the pump alarm states matching the provided device identifier.
public async Task> FindAllActiveByDeviceAsync(string deviceId)
{
return await Collection.Find(x => x.DeviceId == deviceId).ToListAsync();
}
///
/// Asynchronously updates all documents that match the specified on the given , replacing the value with . Used to bulk rewire references stored on a dynamic field.
///
/// Name of the document field to filter and update.
/// The new value to assign to the field.
/// The existing value used to locate matching documents.
/// The number of documents that were modified by the update operation.
public async Task UpdateManyObjectIdByFieldNameAsync(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;
}
}