package online.wesal.wesal.service;

import online.wesal.wesal.dto.CommentResponseDTO;
import online.wesal.wesal.entity.Comment;
import online.wesal.wesal.entity.Post;
import online.wesal.wesal.entity.User;
import online.wesal.wesal.repository.CommentRepository;
import online.wesal.wesal.repository.PostRepository;
import online.wesal.wesal.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CommentService {
    
    @Autowired
    private CommentRepository commentRepository;
    
    @Autowired
    private PostRepository postRepository;
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private SubscriptionNotificationService subscriptionNotificationService;
    
    @Transactional
    public CommentResponseDTO createComment(Long postId, String body, Long replyComment) {
        User currentUser = userService.getCurrentUser();
        
        Post post = postRepository.findById(postId)
                .orElseThrow(() -> new RuntimeException("Post not found"));
        
        Comment comment;
        User replyUser = null;
        
        if (replyComment == null) {
            comment = new Comment(postId, currentUser.getId(), body);
        } else {
            Comment parentComment = commentRepository.findByIdAndPostId(replyComment, postId)
                    .orElseThrow(() -> new RuntimeException("Parent comment not found"));
            
            replyUser = userRepository.findById(parentComment.getCreatorId())
                    .orElseThrow(() -> new RuntimeException("Parent comment creator not found"));
            
            Integer newLevel;
            Long displayReplyComment;
            
            if (parentComment.getLevel() >= 3) {
                newLevel = 3;
                Comment rootComment = findRootCommentForLevel3(parentComment);
                displayReplyComment = rootComment.getId();
            } else {
                newLevel = parentComment.getLevel() + 1;
                displayReplyComment = replyComment;
            }
            
            comment = new Comment(postId, currentUser.getId(), body, replyComment, displayReplyComment, replyUser.getId(), newLevel);
        }
        
        comment = commentRepository.save(comment);
        
        post.setComments(post.getComments() + 1);
        postRepository.save(post);
        
        // Send notification to post creator if they're subscribed to "postcomments" and it's not their own comment
        User postCreator = userRepository.findById(post.getCreatorId()).orElse(null);
        if (postCreator != null && !postCreator.getId().equals(currentUser.getId())) {
            String title = String.format("%s replied to your post", currentUser.getDisplayName());
            String excerpt = subscriptionNotificationService.truncateText(body, 60);
            subscriptionNotificationService.sendNotificationToUser(postCreator, "postcomments", title, excerpt);
        }
        
        return new CommentResponseDTO(comment, currentUser, replyUser);
    }
    
    private Comment findRootCommentForLevel3(Comment comment) {
        if (comment.getLevel() <= 2) {
            return comment;
        }
        
        if (comment.getReplyComment() != null) {
            Comment parentComment = commentRepository.findById(comment.getReplyComment())
                    .orElse(comment);
            return findRootCommentForLevel3(parentComment);
        }
        
        return comment;
    }
    
    public List<CommentResponseDTO> getCommentsByPostId(Long postId) {
        List<Comment> comments = commentRepository.findByPostIdOrderByCreationDateAsc(postId);
        
        List<Long> creatorIds = comments.stream()
                .map(Comment::getCreatorId)
                .distinct()
                .collect(Collectors.toList());
        
        List<Long> replyUserIds = comments.stream()
                .map(Comment::getReplyUser)
                .filter(id -> id != null)
                .distinct()
                .collect(Collectors.toList());
        
        creatorIds.addAll(replyUserIds);
        
        Map<Long, User> users = userRepository.findAllById(creatorIds.stream().distinct().collect(Collectors.toList())).stream()
                .collect(Collectors.toMap(User::getId, user -> user));
        
        Map<Long, CommentResponseDTO> commentMap = comments.stream()
                .collect(Collectors.toMap(
                    Comment::getId,
                    comment -> new CommentResponseDTO(comment, 
                        users.get(comment.getCreatorId()),
                        comment.getReplyUser() != null ? users.get(comment.getReplyUser()) : null)
                ));
        
        List<CommentResponseDTO> rootComments = new ArrayList<>();
        
        for (Comment comment : comments) {
            CommentResponseDTO dto = commentMap.get(comment.getId());
            
            if (comment.getDisplayReplyComment() == null) {
                rootComments.add(dto);
            } else {
                CommentResponseDTO parent = commentMap.get(comment.getDisplayReplyComment());
                if (parent != null) {
                    parent.getReplies().add(dto);
                } else {
                    rootComments.add(dto);
                }
            }
        }
        
        return rootComments;
    }
}