using adas_core.Application.Exceptions; using adas_core.Application.Repositories.Interfaces; using adas_core.Application.Services.Interfaces; using adas_core.Domain.Enums; using adas_core.Domain.Models; using adas_core.Domain.Models.MongoModels; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using MongoDB.Bson; namespace adas_core.Application.Services; public class NoticeService( ILogger logger, ISubscribersService subscribersService, INoticeRepository noticeRepository, IClientMessageService clientMessageService, IDisplayService displayService, IHttpContextAccessor httpContextAccessor, ILocalAuditService auditService) : INoticeService { public async Task DeleteNoticeAsync(Notice notice) { await DeleteNoticeByIdAsync(notice.Id); } public async Task DeleteNoticeByIdAsync(ObjectId noticeId) { try { var noticeAux = await noticeRepository.FindById(noticeId); if (noticeAux == null) { logger.LogInformation("Error deleting Notice not found, id: {noticeId} NOT DELETED ", noticeId); return; } await noticeRepository.Delete(noticeId); await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, noticeAux, null); logger.LogInformation("Notice id: {noticeId} DELETED ", noticeId); SendNoticeBroadcast(noticeAux, OperationType.DeleteNotice); } catch (Exception ex) { logger.LogError("Exception deleting notice id:{notice} . Exception: {ex}", noticeId, ex); } } public async Task GetNoticeByIdAsync(ObjectId noticeId) { try { return await noticeRepository.FindById(noticeId); } catch (Exception ex) { logger.LogError("Exception deleting notice id:{notice} . Exception: {ex}", noticeId, ex); return null; } } public async Task?> GetNoticeByTypeAsync(string noticeType) { return await noticeRepository.FindByType(noticeType) ?? throw new NotFoundException(HttpEnum.ErrorMessage.NotFoundResourceMissing); } public async Task> GetNoticesAsync() { return await noticeRepository.FindAll(); } public async Task InsertNotice(Notice notice) { try { notice.Id = new ObjectId(); await noticeRepository.InsertOneAsync(notice); await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, null, notice); logger.LogInformation("Notice: {notice} INSERTED", notice); SendNoticeBroadcast(notice, OperationType.NewNotice); return notice; } catch (Exception ex) { logger.LogError("Exception inserting notice {notice} . Exception: {ex}", notice, ex); return null; } } public async Task UpdateNoticeAsync(Notice notice) { try { var auxNotice = await noticeRepository.FindById(notice.Id) ?? throw new ConflictException(HttpEnum.ErrorMessage.ConflictUpdateFailed); await noticeRepository.Update(notice); await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, auxNotice, notice); SendNoticeBroadcast(notice, OperationType.UpdateNotice); } catch (Exception ex) { logger.LogError("Exception updating notice {notice} . Exception: {ex}", notice, ex); } } public async Task SaveRequest(ApiRequest apiRequest) { try { if (apiRequest.Notice == null) return; switch (apiRequest.Type) { case "NewNotice": { if (string.IsNullOrEmpty(apiRequest.Notice.Description)) { logger.LogDebug("Error saving notice api request. Some values are required. Notice: {notice}", apiRequest.Notice); return; } await InsertNotice(apiRequest.Notice); break; } case "UpdateNotice": { if (string.IsNullOrEmpty(apiRequest.Notice.Description)) { logger.LogDebug("Error updating notice api request. Some values are required. Notice: {notice}", apiRequest.Notice); return; } await UpdateNoticeAsync(apiRequest.Notice); break; } case "DeleteNotice": { await DeleteNoticeAsync(apiRequest.Notice); break; } } } catch (Exception ex) { logger.LogError("Exception updating notice {notice} . Exception: {ex}", apiRequest.Notice, ex); } } public Task SaveRequestAsync(ApiRequest apiRequest) { return Task.FromResult(Task.Run(async () => { await SaveRequest(apiRequest); })); } public async Task?> GetNoticesByDisplayId(ObjectId displayId) { try { return await noticeRepository.FindByDisplayId(displayId); } catch (Exception e) { logger.LogError("Unable to get notice by unit on service Exception: {e}", e); return null; } } private async void SendNoticeBroadcast(Notice notice, OperationType operation) { try { var display = await displayService.GetById(notice.DisplayId); if (display == null) { logger.LogError("Error sending notice broadcast. display is null or empty. Notice: {notice}", notice); return; } var subscribers = subscribersService.GetSubscribers().Where(s => s.DisplayId == display.Id).ToList(); foreach (var subscriber in subscribers) _ = clientMessageService.SendAsync(subscriber.Id, operation, notice); } catch (Exception ex) { logger.LogError("Exception sending notice broadcast. Operation type: {op}. Exception: {ex}", operation.ToString(), ex); } } }