using System; using System.Collections.Generic; using System.Linq; using System.Net.Mail; using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudApp.Exceptions; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; namespace AsbCloudApp.Services.Notifications; /// <summary> /// Сервис для работы с уведомлениями /// </summary> public class NotificationService { private readonly ICrudRepository<NotificationCategoryDto> notificationCategoryRepository; private readonly INotificationRepository notificationRepository; private readonly IEnumerable<INotificationTransportService> notificationTransportServices; /// <summary> /// Сервис для работы с уведомлениями /// </summary> /// <param name="notificationCategoryRepository"></param> /// <param name="notificationRepository"></param> /// <param name="notificationTransportServices"></param> public NotificationService(ICrudRepository<NotificationCategoryDto> notificationCategoryRepository, INotificationRepository notificationRepository, IEnumerable<INotificationTransportService> notificationTransportServices) { this.notificationCategoryRepository = notificationCategoryRepository; this.notificationRepository = notificationRepository; this.notificationTransportServices = notificationTransportServices; } /// <summary> /// Отправка нового уведомления /// </summary> /// <param name="request"></param> /// <param name="cancellationToken"></param> public async Task NotifyAsync(NotifyRequest request, CancellationToken cancellationToken) { var notificationCategory = await notificationCategoryRepository.GetOrDefaultAsync(request.IdNotificationCategory, cancellationToken) ?? throw new ArgumentInvalidException(nameof(request.IdNotificationCategory), "Категория уведомления не найдена"); var notification = new NotificationDto { IdUser = request.IdUser, RegistrationDate = DateTimeOffset.UtcNow, IdNotificationCategory = notificationCategory.Id, Title = request.Title, Message = request.Message, IdTransportType = request.IdTransportType, }; notification.Id = await notificationRepository.InsertAsync(notification, cancellationToken); notification.NotificationCategory = notificationCategory; var notificationTransportService = GetTransportService(request.IdTransportType); //todo Добавить задачу в WorkToSendEmail try { await notificationTransportService.SendAsync(notification, cancellationToken); } catch (SmtpException ex) { Console.WriteLine(ex.Message); } notification.SentDate = DateTimeOffset.UtcNow; await notificationRepository.UpdateAsync(notification, cancellationToken); } /// <summary> /// Обновление уведомления /// </summary> /// <param name="idNotification"></param> /// <param name="isRead"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task UpdateAsync(int idNotification, bool isRead, CancellationToken cancellationToken) { var notification = await notificationRepository.GetOrDefaultAsync(idNotification, cancellationToken) ?? throw new ArgumentInvalidException(nameof(idNotification), "Уведомление не найдено"); if(isRead && !notification.SentDate.HasValue) throw new ArgumentInvalidException(nameof(isRead), "Уведомление не может быть прочитано"); notification.ReadDate = isRead ? DateTimeOffset.UtcNow : null; await notificationRepository.UpdateAsync(notification, cancellationToken); } /// <summary> /// Отправка уведомлений, которые не были отправлены /// </summary> /// <param name="idUser"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task RenotifyAsync(int idUser, CancellationToken cancellationToken) { const int idTransportType = 0; var notifications = await notificationRepository.GetAllAsync(idUser, false, idTransportType, cancellationToken); var notificationTransportService = GetTransportService(idTransportType); await notificationTransportService.SendRangeAsync(notifications, cancellationToken); var tasks = notifications.Select(notification => { notification.SentDate = DateTimeOffset.UtcNow; return notificationRepository.UpdateAsync(notification, cancellationToken); }); await Task.WhenAll(tasks); } private INotificationTransportService GetTransportService(int idTransportType) { var notificationTransportService = notificationTransportServices .FirstOrDefault(s => s.IdTransportType == idTransportType) ?? throw new ArgumentInvalidException(nameof(idTransportType), "Доставщик уведомлений не найден"); return notificationTransportService; } }