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; /// /// Сервис для работы с уведомлениями /// public class NotificationService { private readonly ICrudRepository notificationCategoryRepository; private readonly INotificationRepository notificationRepository; private readonly IEnumerable notificationTransportServices; /// /// Сервис для работы с уведомлениями /// /// /// /// public NotificationService(ICrudRepository notificationCategoryRepository, INotificationRepository notificationRepository, IEnumerable notificationTransportServices) { this.notificationCategoryRepository = notificationCategoryRepository; this.notificationRepository = notificationRepository; this.notificationTransportServices = notificationTransportServices; } /// /// Отправка нового уведомления /// /// /// 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); } /// /// Обновление уведомления /// /// /// /// /// 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); } /// /// Отправка уведомлений, которые не были отправлены /// /// /// /// 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; } }