ReportCommandService.java

package com.newbit.report.command.application.service;

import java.util.List;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.newbit.post.entity.Comment;
import com.newbit.post.entity.Post;
import com.newbit.post.repository.CommentRepository;
import com.newbit.post.repository.PostRepository;
import com.newbit.report.command.application.dto.request.ReportCreateRequest;
import com.newbit.report.command.application.dto.response.ReportCommandResponse;
import com.newbit.report.command.domain.aggregate.Report;
import com.newbit.report.command.domain.aggregate.ReportStatus;
import com.newbit.report.command.domain.aggregate.ReportType;
import com.newbit.report.command.domain.repository.ReportRepository;
import com.newbit.report.command.domain.repository.ReportTypeRepository;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
@Transactional
public class ReportCommandService {

    private final ReportRepository reportRepository;
    private final ReportTypeRepository reportTypeRepository;
    private final PostRepository postRepository;
    private final CommentRepository commentRepository;

    private static final int REPORT_THRESHOLD = 50;

    public ReportCommandResponse createPostReport(ReportCreateRequest request) {
        if (request.getPostId() == null) {
            throw new IllegalArgumentException("게시글 ID는 필수입니다.");
        }
        
        ReportType reportType = reportTypeRepository.findById(request.getReportTypeId())
                .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 신고 유형입니다."));

        Report report = Report.createPostReport(
                request.getUserId(),
                request.getPostId(),
                reportType,
                request.getContent()
        );
        
        Report savedReport = reportRepository.save(report);
        
        incrementPostReportCount(request.getPostId());
        
        return new ReportCommandResponse(savedReport);
    }

    public ReportCommandResponse createCommentReport(ReportCreateRequest request) {
        if (request.getCommentId() == null) {
            throw new IllegalArgumentException("댓글 ID는 필수입니다.");
        }

        ReportType reportType = reportTypeRepository.findById(request.getReportTypeId())
                .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 신고 유형입니다."));

        Report report = Report.createCommentReport(
                request.getUserId(),
                request.getCommentId(),
                reportType,
                request.getContent()
        );
        
        Report savedReport = reportRepository.save(report);
        
        incrementCommentReportCount(request.getCommentId());
        
        return new ReportCommandResponse(savedReport);
    }
    
    private boolean incrementPostReportCount(Long postId) {
        Post post = postRepository.findById(postId)
                .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 게시글입니다."));
        
        post.setReportCount(post.getReportCount() + 1);
        
        if (post.getReportCount() >= REPORT_THRESHOLD) {
            post.softDelete();
            
            List<Report> reports = reportRepository.findAllByPostId(postId);
            for (Report report : reports) {
                report.updateStatus(ReportStatus.DELETED);
            }
            
            return true;
        }
        
        return false;
    }
    
    private boolean incrementCommentReportCount(Long commentId) {
        Comment comment = commentRepository.findById(commentId)
                .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 댓글입니다."));
        
        comment.setReportCount(comment.getReportCount() + 1);
        
        if (comment.getReportCount() >= REPORT_THRESHOLD) {
            comment.softDelete();
            
            List<Report> reports = reportRepository.findAllByCommentId(commentId);
            for (Report report : reports) {
                report.updateStatus(ReportStatus.DELETED);
            }
            
            return true;
        }
        
        return false;
    }
    
    public ReportCommandResponse processReport(Long reportId, ReportStatus newStatus) {
        Report report = reportRepository.findById(reportId);
        if (report == null) {
            throw new IllegalArgumentException("존재하지 않는 신고입니다.");
        }
        
        report.updateStatus(newStatus);
        
        if (newStatus == ReportStatus.DELETED) {
            if (report.getPostId() != null) {
                Post post = postRepository.findById(report.getPostId())
                        .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 게시글입니다."));
                
                post.softDelete();
            } else if (report.getCommentId() != null) {
                Comment comment = commentRepository.findById(report.getCommentId())
                        .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 댓글입니다."));
                
                comment.softDelete();
            }
        }
        
        return new ReportCommandResponse(report);
    }
}