using adas_core.Application.Exceptions; using adas_core.Application.Repositories.Interfaces; using adas_core.Domain.Enums; using adas_core.Domain.Models; using adas_core.Domain.Models.AppSettings; using adas_core.Domain.Models.DTO; using adas_core.Domain.Models.Masters; using adas_core.Domain.Models.MongoModels; using Microsoft.Extensions.Options; using MongoDB.Bson; using MongoDB.Driver; using Serilog; using MongoUtils = adas_core.Infrastructure.Utils.MongoUtils; namespace adas_core.Infrastructure.Repositories; public class DischargeRepository : MongoRepository, IDischargeRepository { private readonly ApiSettings _apiSettings; public DischargeRepository(IOptions apiSettings, IMongoDatabase database) : base(database) { _apiSettings = apiSettings.Value; } public override string GetCollectionName() { return _apiSettings.Discharges; } public override async Task InsertOneAsync(Discharge discharge) { try { discharge.DischargeDate = DateTime.UtcNow; await base.InsertOneAsync(discharge); } catch (Exception e) { Log.Warning("Exception trying to insert discharge: {discharge}. Exception {e}", discharge, e); } } public async Task Delete(ObjectId id) { try { var filter = Builders.Filter.Eq(x => x.Id, id); await Collection.DeleteOneAsync(filter, null); } catch (Exception e) { Log.Error("Exception trying to delete discharge: {id}. Exception {e}", id, e); throw; } } public async Task Update(Discharge discharge) { try { await UpdateOneAsync(discharge.Id, discharge); } catch (Exception e) { Log.Error("Exception trying to update discharge: {discharge}. Exception {e}", discharge, e); throw new ConflictException(HttpEnum.ErrorMessage.ConflictUpdateFailed); } } public async Task UpdateUnit(ObjectId id, string unit) { var filterBuilder = Builders.Filter; var filter = filterBuilder.Eq(p => p.Id, id); var update = Builders.Update .Set(p => p.PatientLocation!.UnitName, unit); await Collection.UpdateOneAsync(filter, update); } public async Task UpdatePatient(ObjectId id, Patient patient) { var filterBuilder = Builders.Filter; var filter = filterBuilder.Eq(p => p.Id, id); var update = Builders.Update .Set(p => p.Patient, patient); await Collection.UpdateOneAsync(filter, update); } public async Task> FindAll() { try { var result = await Collection.FindAsync(_ => true); return await result.ToListAsync(); } catch (Exception ex) { Log.Error("Error getting all discharges. Exception: {ex}", ex); return []; } } public async Task FindById(ObjectId id) { try { var filter = Builders.Filter.Eq(p => p.Id, id); var result = await Collection.FindAsync(filter); return await result.FirstOrDefaultAsync(); } catch (Exception ex) { Log.Error("Error searching discharge by id: {id}. Exception: {ex}", id, ex); return null; } } public async Task?> FindByUnit(string unit) { try { var filter = Builders.Filter.Eq(p => p.PatientLocation!.UnitName, unit); var result = await Collection.FindAsync(filter); return result.ToEnumerable(); } catch (Exception ex) { Log.Error("Error searching discharge by Unit id: {unit}. Exception: {ex}", unit, ex); return null; } } public async Task CountByUnitId(ObjectId unitId) { try { return await Collection.CountDocumentsAsync( Builders.Filter.Eq(p => p.UnitId, unitId)); } catch (Exception e) { Log.Error(e.Message); return 0; } } public async Task?> FindByDestination(string destination) { try { var filter = string.IsNullOrEmpty(destination) ? Builders.Filter.Empty : Builders.Filter.Eq(p => p.Destination, destination); var result = await Collection.FindAsync(filter); return result.ToEnumerable(); } catch (Exception ex) { Log.Error("Error searching discharges by destination: {destination}. Exception: {ex}", destination, ex); return null; } } public async Task?> GetDischargesByUnitIds(IEnumerable? unitIds) { var filterUnit = Builders.Filter.In("unitId", unitIds); return await Collection.Find(filterUnit).ToListAsync(); } public async Task?> FindByPoCId(ObjectId pocId) { try { var filter = Builders.Filter.Eq(p => p.PointOfCareId, pocId); var result = await Collection.FindAsync(filter); return result.ToEnumerable(); } catch (Exception ex) { Log.Error("Error searching discharges by PointOfCare: {destination}. Exception: {ex}", pocId, ex); return null; } } public async Task?> FindByService(string service) { try { var filter = Builders.Filter.Eq(p => p.Service, service); var result = await Collection.FindAsync(filter); return result.ToEnumerable(); } catch (Exception ex) { Log.Error("Error searching discharges by service: {origin}. Exception: {ex}", service, ex); return null; } } public async Task GetDischargeByLocation(PatientLocation location) { try { var filter = Builders.Filter.Eq(p => p.PatientLocation, location); var result = await Collection.FindAsync(filter); return await result.FirstOrDefaultAsync(); } catch (Exception e) { Log.Error($"Unable to get discharge by location on repository Exception: {e}"); return null; } } public async Task GetDischargeByPointOfCareId(ObjectId id) { try { var filter = Builders.Filter.Eq(p => p.PointOfCareId, id); var result = await Collection.FindAsync(filter); return await result.FirstOrDefaultAsync(); } catch (Exception e) { Log.Error($"Unable to get discharge by location on repository Exception: {e}"); return null; } } public Task> UpdateMasterListOption(List unitIds, UpdateOptionMasterListDto opt, string typeName) { var isParsed = Enum.TryParse(typeName, out var parsedTypeName); if (isParsed) switch (parsedTypeName) { case MasterListType.DestinationList: // destination // destinationOption break; case MasterListType.ServiceList: // service break; } return Task.FromResult>(new List()); } public async Task DeleteByUnitId(ObjectId unitId) { try { var filter = Builders.Filter.Where(p => p.UnitId == unitId); await Collection.DeleteManyAsync(filter); return true; } catch (Exception ex) { Log.Error(ex.Message); return false; } } public Task> DeleteMasterListOption(List unitIds, OptionList opt, string typeName) { var isParsed = Enum.TryParse(typeName, out var parsedTypeName); if (isParsed) switch (parsedTypeName) { case MasterListType.DestinationList: // destination // destinationOption break; case MasterListType.ServiceList: // service break; } return Task.FromResult>(new List()); } public async Task GetByPatientId(ObjectId patientId) { try { var filter = Builders.Filter.Eq(p => p.PatientId, patientId); var result = await Collection.FindAsync(filter); return await result.FirstOrDefaultAsync(); } catch (Exception e) { Log.Error($"Unable to get discharge by patient id on repository Exception: {e}"); return null; } } public override async Task CreateIndexes() { var optionsUq = new CreateIndexOptions { Background = true, Unique = true, PartialFilterExpression = Builders.Filter.Exists(p => p.MedicalDischarge) & Builders.Filter.Exists(p => p.AdminDischarge) }; var indexes = new List> { new("{ medicalDischarge: 1 }", optionsUq), new("{ adminDischarge: 1 }", optionsUq) }; await MongoUtils.EnsureIndexes(Collection, indexes); } }