using Application.Abstractions.Messaging; using Application.Abstractions.Data; using Microsoft.EntityFrameworkCore; using SharedKernel.Results; namespace Application.Features.Api.Forum.Comment.Create; public sealed class Handler(IAppDbContext db) : ICommandHandler> { public async Task> Handle(Command request, CancellationToken ct) { if (string.IsNullOrWhiteSpace(request.Content)) { return Result.Failure(Error.Problem("Comment.ContentRequired", "내용을 입력해주세요.")); } var post = await db.Post.FirstOrDefaultAsync(x => x.ID == request.PostID, ct); if (post is null) { return Result.Failure(Error.NotFound("Comment.PostNotFound", "게시글을 찾을 수 없습니다.")); } var member = await db.Member.AsNoTracking().FirstOrDefaultAsync(x => x.ID == request.MemberID, ct); if (member is null) { return Result.Failure(Error.NotFound("Comment.MemberNotFound", "회원 정보를 찾을 수 없습니다.")); } sbyte depth = 0; var isReply = false; if (request.ParentID.HasValue) { var parent = await db.Comment.AsNoTracking().FirstOrDefaultAsync(x => x.ID == request.ParentID.Value, ct); if (parent is null) { return Result.Failure(Error.NotFound("Comment.ParentNotFound", "상위 댓글을 찾을 수 없습니다.")); } depth = (sbyte)(parent.Depth + 1); isReply = true; // 부모 댓글 답글 수 증가 var parentEntity = await db.Comment.FirstOrDefaultAsync(x => x.ID == request.ParentID.Value, ct); if (parentEntity is not null) { parentEntity.Replies++; } } var comment = new Domain.Entities.Forum.Comments.Comment { BoardID = request.BoardID, PostID = request.PostID, MemberID = request.MemberID, ParentID = request.ParentID, Depth = depth, Content = request.Content.Trim(), IsReply = isReply, IsSecret = request.IsSecret, Name = member.Name, SID = member.SID, Email = member.Email }; await db.Comment.AddAsync(comment, ct); // Post 댓글 카운트 증가 post.Comments++; post.LastCommentUpdatedAt = DateTime.UtcNow; // Board 댓글 카운트 증가 var board = await db.Board.FirstOrDefaultAsync(x => x.ID == request.BoardID, ct); if (board is not null) { board.Comments++; board.UpdatedAt = DateTime.UtcNow; } // MemberStats 댓글 수 증가 var memberStats = await db.MemberStats.FirstOrDefaultAsync(x => x.MemberID == request.MemberID, ct); if (memberStats is not null) { memberStats.CommentCount++; } await db.SaveChangesAsync(ct); return comment.ID; } }