using System.Security.Claims;
using adas_core.Application.Exceptions;
using adas_core.Application.Repositories.Interfaces;
using adas_core.Application.Services;
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Models;
using adas_core.Domain.Models.MongoModels;
using adas_core.Test.Utilities;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using MongoDB.Bson;
using Moq;
namespace adas_core.Test.Services;
///
/// Provides unit tests for the class, verifying the behavior and correctness of discharge-related operations.
///
public class DischargeServiceTest
{
private readonly Mock _auditServiceMock = new();
private readonly Mock _clientMessageServiceMock = new();
private readonly Mock _dischargeRepositoryMock = new();
private readonly Mock _httpContextAccessorMock = new();
private readonly Mock> _loggerMock = new();
private readonly Mock _masterMock = new();
private readonly Mock> _patientServiceLazyMock = new();
private readonly Mock _pointOfCareServiceMock = new();
private readonly Mock _subscribersServiceMock = new();
private readonly Mock _unitServiceMock = new();
private DischargeService _dischargeService = null!;
///
/// Sets up the test environment by creating a mock authenticated user context and instantiating the with its required dependencies for use in unit tests.
///
[SetUp]
public void Setup()
{
var userClaims = new ClaimsPrincipal(new ClaimsIdentity([
new Claim(ClaimTypes.Name, "TestUser")
], "mock"));
var httpContextMock = new DefaultHttpContext
{
User = userClaims
};
_httpContextAccessorMock.Setup(accessor => accessor.HttpContext)
.Returns(httpContextMock);
_dischargeService = new DischargeService(
_loggerMock.Object,
_subscribersServiceMock.Object,
_dischargeRepositoryMock.Object,
_patientServiceLazyMock.Object,
_clientMessageServiceMock.Object,
_pointOfCareServiceMock.Object,
_httpContextAccessorMock.Object,
_auditServiceMock.Object,
_unitServiceMock.Object,
_masterMock.Object);
}
///
/// Verifies that successfully deletes a discharge
/// when it exists in the repository.
///
/// The discharge entity expected to be deleted; its identifier is used to invoke the repository delete operation.
[Test]
public async Task DeleteDischargeAsync_WhenDischargeExists_DeletesDischarge()
{
// Arrange
var dischargeId = ObjectId.GenerateNewId();
var discharge = new Discharge { Id = dischargeId };
_dischargeRepositoryMock.Setup(repo => repo.FindById(dischargeId)).ReturnsAsync(discharge);
// Act
await _dischargeService.DeleteDischargeAsync(discharge);
// Assert
_dischargeRepositoryMock.Verify(repo => repo.Delete(dischargeId), Times.Once);
}
//necesita el pocservice
// [Test]
// public async Task GetDischargeByIdAsync_WhenDischargeExists_ReturnsDischarge()
// {
// // Arrange
// var dischargeId = ObjectId.GenerateNewId();
// var discharge = new Discharge { Id = dischargeId };
// _dischargeRepositoryMock.Setup(repo => repo.FindById(dischargeId)).ReturnsAsync(discharge);
//
// // Act
// var result = await _dischargeService.GetDischargeByIdAsync(dischargeId);
//
// // Assert
// Assert.That(result, Is.EqualTo(discharge));
// }
///
/// Verifies that throws a when the requested discharge is not found.
///
[Test]
public void GetDischargeByIdAsync_WhenExceptionOccurs_ReturnsNullAndLogsError()
{
// Arrange
var dischargeId = ObjectId.GenerateNewId();
// Act and assert
Func act = async () => await _dischargeService.GetDischargeByIdAsync(dischargeId);
Assert.ThrowsAsync(act);
}
///
/// Verifies that the discharge service returns the expected discharges retrieved from the repository when the underlying repository call completes successfully without exceptions.
///
/// A representing the asynchronous test execution.
[Test]
public async Task GetDischargesAsync_WhenNoException_ReturnsDischarges()
{
// Arrange
var discharge = TestUtilities.CreateValidDischarge();
var discharges = new List { discharge };
_dischargeRepositoryMock.Setup(repo => repo.FindAll()).ReturnsAsync(discharges);
// Act
var result = await _dischargeService.GetDischargesAsync();
var resultList = result.ToList();
// Assert
Assert.That(resultList.First().Id, Is.EqualTo(discharges.First().Id));
}
//necesita el pocservice
// [Test]
// public async Task GetDischargeByPatientId_WhenDischargeExists_ReturnsDischarge()
// {
// // Arrange
// var discharge = TestUtilities.CreateValidDischarge();
// _dischargeRepositoryMock.Setup(repo => repo.GetByPatientId(discharge.PatientId)).ReturnsAsync(discharge);
//
// // Act
// var result = await _dischargeService.GetDischargeByPatientId(discharge.PatientId);
//
// // Assert
// Assert.That(result?.Id, Is.EqualTo(discharge.Id));
// }
///
/// Verifies that returns the inserted discharge
/// when the underlying repository successfully completes the insertion and the entity can be retrieved by its identifier.
///
[Test]
public async Task InsertDischarge_WhenInsertionSuccessful_ReturnsInsertedDischarge()
{
// Arrange
var dischargeId = ObjectId.GenerateNewId();
var discharge = new Discharge { Id = dischargeId };
_dischargeRepositoryMock.Setup(repo => repo.InsertOneAsync(discharge)).Returns(Task.CompletedTask);
_dischargeRepositoryMock.Setup(repo => repo.FindById(dischargeId)).ReturnsAsync(discharge);
// Act
var result = await _dischargeService.InsertDischarge(discharge);
// Assert
Assert.That(result, Is.EqualTo(discharge));
}
///
/// Verifies that handles repository insertion failures by propagating the exception thrown by the underlying data store.
///
[Test]
public void InsertDischarge_WhenInsertionFails_ReturnsNullAndLogsError()
{
// Arrange
var discharge = new Discharge { Id = ObjectId.GenerateNewId() };
var exception = new Exception("Failed to insert discharge");
_dischargeRepositoryMock.Setup(repo => repo.InsertOneAsync(discharge)).ThrowsAsync(exception);
// Assert
Func act = async () => await _dischargeService.InsertDischarge(discharge);
Assert.ThrowsAsync(act);
}
///
/// Verifies that returns the discharge
/// retrieved from the repository when a discharge exists for the specified patient location.
///
[Test]
public async Task GetDischargeByLocation_WhenDischargeExists_ReturnsDischarge()
{
// Arrange
var location = new PatientLocation("UnitName", "Bed", "Room");
var discharge = new Discharge();
_dischargeRepositoryMock.Setup(repo => repo.GetDischargeByLocation(location)).ReturnsAsync(discharge);
// Act
var result = await _dischargeService.GetDischargeByLocation(location);
// Assert
Assert.That(result, Is.EqualTo(discharge));
}
///
/// Verifies that returns null when the underlying discharge repository throws an exception while retrieving the discharge record for the specified patient location.
///
[Test]
public async Task GetDischargeByLocation_WhenExceptionOccurs_ReturnsNullAndLogsError()
{
// Arrange
var location = new PatientLocation("UnitName", "Bed", "Room");
var exception = new Exception("Failed to retrieve discharge by location");
_dischargeRepositoryMock.Setup(repo => repo.GetDischargeByLocation(location)).ThrowsAsync(exception);
// Act
var result = await _dischargeService.GetDischargeByLocation(location);
// Assert
Assert.That(result, Is.Null);
}
// [Test]
// public async Task GetDischargeByPointOfCareId_WhenDischargeExists_ReturnsDischarge()
// {
// // Arrange
// var discharge = TestUtilities.CreateValidDischarge();
// _dischargeRepositoryMock.Setup(repo => repo.GetDischargeByPointOfCareId(discharge.PointOfCareId)).ReturnsAsync(discharge);
//
// // Act
// var result = await _dischargeService.GetDischargeByPointOfCareId(discharge.PointOfCareId);
//
// // Assert
// Assert.That(result, Is.EqualTo(discharge));
// }
///
/// Verifies that returns null when the underlying repository throws an exception while attempting to retrieve a discharge by its point-of-care identifier.
///
[Test]
public async Task GetDischargeByPointOfCareId_WhenExceptionOccurs_ReturnsNullAndLogsError()
{
// Arrange
var poc = ObjectId.GenerateNewId();
var exception = new Exception("Failed to retrieve discharge by PointOfCareId");
_dischargeRepositoryMock.Setup(repo => repo.GetDischargeByPointOfCareId(poc)).ThrowsAsync(exception);
// Act
var result = await _dischargeService.GetDischargeByPointOfCareId(poc);
// Assert
Assert.That(result, Is.Null);
}
}