using Application.Abstractions.Messaging; using Application.Abstractions.Data; using Domain.Entities.Forum.Constants; using Microsoft.EntityFrameworkCore; namespace Application.Features.Admin.Forum.BoardPrefix.Save; internal sealed class Handler(IAppDbContext db) : ICommandHandler { public async Task Handle(Command request, CancellationToken ct) { // 삭제 if (request.DeleteIDs is { Length: > 0 }) { var deleteTargets = await db.BoardPrefix .Where(c => c.BoardID == request.BoardID && request.DeleteIDs.Contains(c.ID)) .ToListAsync(ct); // 게시글이 등록된 말머리는 삭제 불가 var hasPostsTargets = deleteTargets.Where(c => c.Posts > 0).ToList(); if (hasPostsTargets.Count > 0) { throw new InvalidOperationException("게시글이 등록된 말머리는 삭제할 수 없습니다."); } if (deleteTargets.Count > 0) { db.BoardPrefix.RemoveRange(deleteTargets); } } // 수정 if (request.Updates is { Count: > 0 }) { var updateIDs = request.Updates.Select(c => c.ID).ToList(); var updateTargets = await db.BoardPrefix .Where(c => c.BoardID == request.BoardID && updateIDs.Contains(c.ID)) .ToListAsync(ct); var updateByID = updateTargets.ToDictionary(c => c.ID); foreach (var row in request.Updates) { if (!updateByID.TryGetValue(row.ID, out var existing)) { throw new InvalidOperationException($"존재하지 않는 ID: {row.ID}"); } existing.Name = row.Name; existing.Color = row.Color; existing.Order = row.Order; existing.IsActive = row.IsActive; existing.UpdatedAt = DateTime.UtcNow; } } // 신규 추가 if (request.NewItem is not null) { var currentCount = await db.BoardPrefix .AsNoTracking() .CountAsync(c => c.BoardID == request.BoardID, ct); if (currentCount >= BoardConstant.MaxPrefixCount) { throw new InvalidOperationException($"말머리는 최대 {BoardConstant.MaxPrefixCount}개까지 등록할 수 있습니다."); } db.BoardPrefix.Add(new Domain.Entities.Forum.Boards.BoardPrefix { BoardID = request.BoardID, Name = request.NewItem.Name, Color = request.NewItem.Color, Order = request.NewItem.Order }); } await db.SaveChangesAsync(ct); } }