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.Enums; using adas_core.Domain.Models.AppSettings; using adas_core.Domain.Models.MongoModels; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using MongoDB.Bson; using Moq; using static NUnit.Framework.Assert; using Options = Microsoft.Extensions.Options.Options; namespace adas_core.Test.Services; [TestFixture] public class DisplayServiceTest { private Mock _mockCacheService = null!; private Mock _mockDisplayRepository = null!; private Mock _mockPointOfCareService = null!; private Mock _mockDisplayConfigService = null!; private Mock _mockUserRepository = null!; private Mock _authServiceMock = null!; private Mock _mockSubscribersService = null!; private Mock _mockClientMessageService = null!; private Mock> _mockUnitService = null!; private Mock _mockPermissionService = null!; private Lazy _lazyMockPermission = null!; private Mock> _mockLogger = null!; private readonly Mock _httpContextAccessorMock = new(); private readonly Mock _auditServiceMock = new(); private DisplayService _displayService = null!; [SetUp] public void SetUp() { _mockCacheService = new Mock(); _mockDisplayRepository = new Mock(); _mockPointOfCareService = new Mock(); _mockDisplayConfigService = new Mock(); _mockUserRepository = new Mock(); _authServiceMock = new Mock(); _mockSubscribersService = new Mock(); _mockClientMessageService = new Mock(); _mockUnitService = new Mock>(); _mockPermissionService = new Mock(); _lazyMockPermission = new Lazy(() => _mockPermissionService.Object); _mockLogger = new Mock>(); var claims = new ClaimsPrincipal( new ClaimsIdentity([new Claim(ClaimTypes.Name, "TestUser")], "mock")); _httpContextAccessorMock.Setup(a => a.HttpContext).Returns(new DefaultHttpContext { User = claims }); var cacheSettings = Options.Create(new CacheSettings()); _displayService = new DisplayService( _mockDisplayRepository.Object, _mockPointOfCareService.Object, _mockUnitService.Object, _mockDisplayConfigService.Object, _mockSubscribersService.Object, _mockClientMessageService.Object, _mockUserRepository.Object, _authServiceMock.Object, _mockLogger.Object, _httpContextAccessorMock.Object, _auditServiceMock.Object, _lazyMockPermission, _mockCacheService.Object, cacheSettings ); } // ----------------------------------------------------------- // InsertOne // ----------------------------------------------------------- [Test] public async Task InsertOne_ShouldInsertDisplay() { var display = new Display { Name = "Test Display", Type = DisplayConfigEnums.DisplayType.DisplayNurse }; var defaultCfg = new DisplayConfig { Id = ObjectId.GenerateNewId(), Type = display.Type }; _mockDisplayConfigService.Setup(s => s.GetDefaultConfig(display.Type)).ReturnsAsync(defaultCfg); _mockDisplayRepository.Setup(r => r.InsertOneAsync(display)) .Returns(Task.CompletedTask); var result = await _displayService.InsertOne(display); That(result, Is.EqualTo(display)); _mockDisplayRepository.Verify(r => r.InsertOneAsync(display), Times.Once); } // ----------------------------------------------------------- // GetById // ----------------------------------------------------------- [Test] public async Task GetById_ShouldReturnDisplay() { var id = ObjectId.GenerateNewId(); var d = new Display { Id = id, Name = "D1" }; _mockDisplayRepository.Setup(r => r.GetById(id)).ReturnsAsync(d); var result = await _displayService.GetById(id); That(result, Is.EqualTo(d)); } // ----------------------------------------------------------- // GetAllByUser - userName null // ----------------------------------------------------------- [Test] public async Task GetAllByUser_ShouldReturnEmpty_WhenUserNameNull() { var result = await _displayService.GetAllByUser(null); That(result, Is.Empty); } // ----------------------------------------------------------- // GetAllByUser - Admin case // ----------------------------------------------------------- [Test] public async Task GetAllByUser_ShouldReturnDisplays_WhenAdmin() { // Arrange const string userName = "admin"; var adminId = ObjectId.GenerateNewId(); var unitId = ObjectId.GenerateNewId(); var user = new User { Id = adminId, UserName = userName, Authorization = [ new Authorization { UnitId = unitId.ToString(), Rol = nameof(PermissionEnum.RolesType.AuthAdmin) } ] }; // 1) Usuario + authorities _mockUserRepository.Setup(r => r.GetByUserAndAuthoritesName(userName)) .ReturnsAsync(user); _authServiceMock.Setup(a => a.GetUserAuthorities(adminId)) .ReturnsAsync(user.Authorization); // 2) Displays por UnitId var d1 = new Display { Id = ObjectId.GenerateNewId(), Name = "D1", UnitId = unitId }; var d2 = new Display { Id = ObjectId.GenerateNewId(), Name = "D2", UnitId = unitId }; var displays = new List { d1, d2 }; _mockDisplayRepository.Setup(r => r.GetByUnitId(unitId)) .ReturnsAsync(displays); // 3) GetInfo (rama base) → caché debe devolver el display haciendo el factory _mockDisplayRepository.Setup(r => r.GetById(d1.Id)).ReturnsAsync(d1); _mockDisplayRepository.Setup(r => r.GetById(d2.Id)).ReturnsAsync(d2); _mockCacheService .Setup(c => c.GetOrSetObjectAsync( It.IsAny(), It.IsAny>>(), It.IsAny(), It.IsAny())) .Returns((string _, Func> factory, TimeSpan? _, CancellationToken _) => factory()); // 4) Permisos (si es null, el servicio NO añade el display) _mockPermissionService .Setup(p => p.GetPermissionsForUnit(unitId.ToString(), user)) .ReturnsAsync(new DisplayPermissionTypes( new UserActions(true,true,true,true,true), new UserActions(true,true,true,true,true), new UserActions(true,true,true,true,true), new UserActions(true,true,true,true,true), new UserActions(true,true,true,true,true), new UserActions(true,true,true,true,true), new UserActions(true,true,true,true,true), true )); // Act var result = await _displayService.GetAllByUser(userName); // Assert That(result, Has.Count.EqualTo(2)); using (Assert.EnterMultipleScope()) { That(result.Any(r => r.Display != null && r.Display.Id == d1.Id), Is.True); That(result.Any(r => r.Display != null && r.Display.Id == d2.Id), Is.True); } } // ----------------------------------------------------------- // GetByType // ----------------------------------------------------------- [Test] public async Task GetByType_ShouldReturnDisplays() { var cfgId = ObjectId.GenerateNewId(); var cfg = new DisplayConfig { Id = cfgId, Type = DisplayConfigEnums.DisplayType.DisplayNurse }; var display = new Display { Id = ObjectId.GenerateNewId(), DisplayConfigId = cfgId, Name = "D" }; _mockDisplayConfigService.Setup(s => s.GetByType(cfg.Type)) .ReturnsAsync([cfg]); _mockDisplayRepository.Setup(r => r.GetByConfigId(cfgId)) .ReturnsAsync([display]); var result = await _displayService.GetByType(cfg.Type); That(result.Count, Is.EqualTo(1)); That(result[0], Is.EqualTo(display)); } [Test] public async Task GetByType_ShouldReturnEmpty_WhenNoConfigsFound() { _mockDisplayConfigService.Setup(s => s.GetByType(It.IsAny())) .ReturnsAsync([]); var result = await _displayService.GetByType(DisplayConfigEnums.DisplayType.DisplayNurse); That(result, Is.Empty); } // ----------------------------------------------------------- // GetByPointOfCare // ----------------------------------------------------------- [Test] public async Task GetByPointOfCare_ShouldReturnDisplays() { var poc = new PointOfCare { Id = ObjectId.GenerateNewId() }; var d = new Display { Id = ObjectId.GenerateNewId(), Name = "Display" }; _mockDisplayRepository.Setup(r => r.GetByPointOfCare(poc)) .ReturnsAsync([d]); var result = await _displayService.GetByPointOfCare(poc); That(result, Has.Count.EqualTo(1)); } // ----------------------------------------------------------- // GetByConfigId // ----------------------------------------------------------- [Test] public async Task GetByConfigId_ShouldReturnDisplays() { var cfgId = ObjectId.GenerateNewId(); var d = new Display { Id = ObjectId.GenerateNewId(), DisplayConfigId = cfgId, Name = "display1"}; _mockDisplayRepository.Setup(r => r.GetByConfigId(cfgId)) .ReturnsAsync([d]); var result = await _displayService.GetByConfigId(cfgId); That(result, Has.Count.EqualTo(1)); } // ----------------------------------------------------------- // GetByName // ----------------------------------------------------------- [Test] public void GetByName_ShouldThrow_WhenNotFound() { _mockDisplayRepository.Setup(r => r.GetByName("X")) .ReturnsAsync((Display?)null); Func act = () => _displayService.GetByName("X"); Assert.ThrowsAsync(act); } // ----------------------------------------------------------- // GetInfo // ----------------------------------------------------------- [Test] public async Task GetInfo_ShouldReturnDisplayWithPoc() { var id = ObjectId.GenerateNewId(); var cfgId = ObjectId.GenerateNewId(); var pocId = ObjectId.GenerateNewId(); var display = new Display { Id = id, Name = "Display", DisplayConfigId = cfgId, PointOfCareIdList = [pocId] }; _mockCacheService .Setup(c => c.GetOrSetObjectAsync( It.IsAny(), It.IsAny>>(), It.IsAny(), It.IsAny())) .Returns((string _, Func> factory, TimeSpan? _, CancellationToken _) => factory()); _mockDisplayRepository.Setup(r => r.GetById(id)).ReturnsAsync(display); _mockDisplayConfigService.Setup(s => s.GetById(cfgId)) .ReturnsAsync(new DisplayConfig { Id = cfgId }); var poc = new PointOfCare { Id = pocId }; _mockPointOfCareService.Setup(s => s.GetInfo(pocId, null, true, It.IsAny())) .ReturnsAsync(poc); var result = await _displayService.GetInfo(id, "user", [], null, true, true, false); That(result, Is.Not.Null); That(result!.PointOfCares.First(), Is.EqualTo(poc)); } // ----------------------------------------------------------- // GetByUnitId // ----------------------------------------------------------- [Test] public async Task GetByUnitId_ShouldReturnDisplays() { var id = ObjectId.GenerateNewId(); var d = new Display { Id = ObjectId.GenerateNewId(), UnitId = id , Name = "display1"}; _mockDisplayRepository.Setup(r => r.GetByUnitId(id)) .ReturnsAsync([d]); var result = await _displayService.GetByUnitId(id); That(result, Has.Count.EqualTo(1)); } // ----------------------------------------------------------- // UpdatePointOfCareList // ----------------------------------------------------------- [Test] public void UpdatePointOfCareList_ShouldThrow_WhenDisplayNotFound() { var id = ObjectId.GenerateNewId(); _mockDisplayRepository.Setup(r => r.GetById(id)) .ReturnsAsync((Display?)null); Func act = () => _displayService.UpdatePointOfCareList(id, []); Assert.ThrowsAsync(act); } // ----------------------------------------------------------- // UpdateConfigPreset // ----------------------------------------------------------- [Test] public void UpdateConfigPreset_ShouldThrow_WhenUpdateFails() { var id = ObjectId.GenerateNewId(); var cfgId = ObjectId.GenerateNewId(); _mockDisplayRepository.Setup(r => r.UpdateConfigPreset(id, cfgId)) .ReturnsAsync((Display?)null); Func act = () => _displayService.UpdateConfigPreset(id, cfgId); Assert.ThrowsAsync(act); } }