using SPMS.Application.DTOs.Notice; using SPMS.Application.DTOs.Notification; using SPMS.Application.Interfaces; using SPMS.Domain.Common; using SPMS.Domain.Enums; using SPMS.Domain.Exceptions; using SPMS.Domain.Interfaces; namespace SPMS.Application.Services; public class NotificationService : INotificationService { private readonly INotificationRepository _notificationRepository; private readonly IUnitOfWork _unitOfWork; public NotificationService( INotificationRepository notificationRepository, IUnitOfWork unitOfWork) { _notificationRepository = notificationRepository; _unitOfWork = unitOfWork; } public async Task GetSummaryAsync(long adminId, NotificationSummaryRequestDto request) { var limit = request.Limit > 0 ? request.Limit : 5; var recentItems = await _notificationRepository.GetRecentAsync(adminId, limit); var unreadCount = await _notificationRepository.GetUnreadCountAsync(adminId); return new NotificationSummaryResponseDto { RecentItems = recentItems.Select(MapToItemDto).ToList(), UnreadCount = unreadCount }; } public async Task GetListAsync(long adminId, NotificationListRequestDto request) { // category 문자열 → enum 파싱 NotificationCategory? category = null; if (!string.IsNullOrWhiteSpace(request.Category)) { if (!Enum.TryParse(request.Category, true, out var parsed)) throw new SpmsException(ErrorCodes.BadRequest, $"유효하지 않은 카테고리: {request.Category}"); category = parsed; } var (items, totalCount) = await _notificationRepository.GetPagedAsync( adminId, category, request.From, request.To, request.IsRead, request.Page, request.Size); var unreadCount = await _notificationRepository.GetUnreadCountAsync(adminId); var totalPages = (int)Math.Ceiling((double)totalCount / request.Size); return new NotificationListResponseDto { Items = items.Select(MapToItemDto).ToList(), Pagination = new PaginationDto { Page = request.Page, Size = request.Size, TotalCount = totalCount, TotalPages = totalPages }, UnreadCount = unreadCount }; } public async Task MarkAsReadAsync(long adminId, NotificationReadRequestDto request) { var notification = await _notificationRepository.GetByIdAndAdminAsync(request.NotificationId, adminId); if (notification == null) throw new SpmsException(ErrorCodes.NotFound, "알림을 찾을 수 없습니다.", 404); // 멱등성: 이미 읽은 알림은 스킵 if (!notification.IsRead) { notification.IsRead = true; notification.ReadAt = DateTime.UtcNow; _notificationRepository.Update(notification); await _unitOfWork.SaveChangesAsync(); } var unreadCount = await _notificationRepository.GetUnreadCountAsync(adminId); return new NotificationReadResponseDto { UnreadCount = unreadCount }; } public async Task MarkAllAsReadAsync(long adminId) { await _notificationRepository.MarkAllAsReadAsync(adminId); return new NotificationReadResponseDto { UnreadCount = 0 }; } private static NotificationItemDto MapToItemDto(Domain.Entities.Notification n) => new() { NotificationId = n.Id, Category = n.Category.ToString().ToLower(), Title = n.Title, Content = n.Content, LinkUrl = n.LinkUrl, IsRead = n.IsRead, ReadAt = n.ReadAt, CreatedAt = n.CreatedAt }; }