package com.test.musichouduan.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.test.musichouduan.dto.CommentDTO;
import com.test.musichouduan.dto.PageResult;
import com.test.musichouduan.dto.UserDTO;
import com.test.musichouduan.entity.Comment;
import com.test.musichouduan.entity.Music;
import com.test.musichouduan.entity.User;
import com.test.musichouduan.exception.BusinessException;
import com.test.musichouduan.repository.CommentRepository;
import com.test.musichouduan.repository.MusicRepository;
import com.test.musichouduan.repository.PlaylistRepository;
import com.test.musichouduan.repository.SingerRepository;
import com.test.musichouduan.repository.UserRepository;
import com.test.musichouduan.service.CommentService;
import org.springframework.messaging.simp.SimpMessagingTemplate; // 添加导入
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.persistence.criteria.Predicate;

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

/**
 * 评论服务实现类
 */
@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private CommentRepository commentRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private MusicRepository musicRepository;

    @Autowired
    private PlaylistRepository playlistRepository;

    @Autowired
    private SingerRepository singerRepository;

    @Autowired
    private SimpMessagingTemplate messagingTemplate; // 注入 SimpMessagingTemplate

    @Override
    public CommentDTO getCommentById(Long id) {
        Comment comment = commentRepository.findById(id)
                .orElseThrow(() -> new BusinessException("评论不存在"));
        return convertToDTO(comment);
    }

    @Override
    public PageResult<CommentDTO> getCommentList(Long targetId, Integer targetType, Integer page, Integer size) {
        // 获取父评论
        Page<Comment> commentPage = commentRepository.findByTargetIdAndTargetTypeAndParentIdIsNullOrderByCreateTimeDesc(
                targetId, targetType, PageRequest.of(page - 1, size)
        );

        // 转换为DTO
        List<CommentDTO> commentDTOs = commentPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());

        // 获取子评论
        for (CommentDTO commentDTO : commentDTOs) {
            List<Comment> children = commentRepository.findByParentIdOrderByCreateTimeAsc(commentDTO.getId());
            if (!children.isEmpty()) {
                commentDTO.setChildren(children.stream()
                        .map(this::convertToDTO)
                        .collect(Collectors.toList()));
            } else {
                commentDTO.setChildren(new ArrayList<>());
            }
        }

        return new PageResult<>(
                commentDTOs,
                commentPage.getTotalElements(),
                page,
                size
        );
    }

    @Override
    @Transactional
    public CommentDTO addComment(CommentDTO commentDTO) {
        // 获取当前登录用户
        Long userId = StpUtil.getLoginIdAsLong();
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new BusinessException("用户不存在"));

        // 创建评论实体
        Comment comment = new Comment();
        comment.setContent(commentDTO.getContent());
        comment.setUser(user);
        comment.setTargetId(commentDTO.getTargetId());
        comment.setTargetType(commentDTO.getTargetType());
        comment.setParentId(commentDTO.getParentId());
        comment.setStatus(1); // 默认状态为正常

        // 保存评论
        Comment savedComment = commentRepository.save(comment);


        // 如果评论的是音乐 (targetType=1, 这个值需要与前端约定好)
        // 通常可以定义一个枚举或常量类来管理这些类型值
        if (savedComment.getTargetType() == 1) {
            musicRepository.findById(savedComment.getTargetId()).ifPresent(music -> {
                // 首先判断类型是否等于1
                if (savedComment.getTargetType() == 1) {
                    // 查询评论表，使用COUNT(id)统计该音乐的评论数量
                    long commentCount = commentRepository.countByTargetIdAndTargetType(savedComment.getTargetId(), 1);
                    // 设置到音乐中
                    music.setCommentCount((int) commentCount);
                    // 保存音乐实体
                    musicRepository.save(music);
                }
            });
        } else if (savedComment.getTargetType() == 2) { // 2 代表歌单
            playlistRepository.findById(savedComment.getTargetId()).ifPresent(playlist -> {
                long commentCount = commentRepository.countByTargetIdAndTargetType(savedComment.getTargetId(), 2);
                playlist.setCommentCount((int) commentCount);
                playlistRepository.save(playlist);
            });
        } else if (savedComment.getTargetType() == 3) { // 3 代表歌手
            singerRepository.findById(savedComment.getTargetId()).ifPresent(singer -> {
                long commentCount = commentRepository.countByTargetIdAndTargetType(savedComment.getTargetId(), 3);
                singer.setCommentCount((int) commentCount);
                singerRepository.save(singer);
            });
        }

        // 将新评论转换为DTO
        CommentDTO savedCommentDTO = convertToDTO(savedComment);

        // 构建 WebSocket 主题路径
        String destination = String.format("/topic/comments/%d/%d", savedComment.getTargetType(), savedComment.getTargetId());

        // 通过 WebSocket 发送新评论
        messagingTemplate.convertAndSend(destination, savedCommentDTO);

        return savedCommentDTO; // 返回转换后的 DTO
    }

    @Override
    @Transactional
    public boolean deleteComment(Long id) {
        // 获取评论
        Comment comment = commentRepository.findById(id)
                .orElseThrow(() -> new BusinessException("评论不存在"));

        // 获取当前登录用户
        Long userId = StpUtil.getLoginIdAsLong();

        // 检查是否是评论作者或管理员
        if (!comment.getUser().getId().equals(userId) && !StpUtil.hasRole("admin")) {
            throw new BusinessException("无权删除该评论");
        }

        // 删除评论
        commentRepository.delete(comment);

        // 更新相关实体的评论数
        if (comment.getTargetType() == 1) {
            musicRepository.findById(comment.getTargetId()).ifPresent(music -> {
                long commentCount = commentRepository.countByTargetIdAndTargetType(comment.getTargetId(), 1);
                music.setCommentCount((int) commentCount);
                musicRepository.save(music);
            });
        } else if (comment.getTargetType() == 2) {
            playlistRepository.findById(comment.getTargetId()).ifPresent(playlist -> {
                long commentCount = commentRepository.countByTargetIdAndTargetType(comment.getTargetId(), 2);
                playlist.setCommentCount((int) commentCount);
                playlistRepository.save(playlist);
            });
        } else if (comment.getTargetType() == 3) {
            singerRepository.findById(comment.getTargetId()).ifPresent(singer -> {
                long commentCount = commentRepository.countByTargetIdAndTargetType(comment.getTargetId(), 3);
                singer.setCommentCount((int) commentCount);
                singerRepository.save(singer);
            });
        }

        // 如果是父评论，同时删除子评论
        if (comment.getParentId() == null) {
            List<Comment> children = commentRepository.findByParentIdOrderByCreateTimeAsc(id);
            if (!children.isEmpty()) {
                commentRepository.deleteAll(children);
            }
        }

        return true;
    }

    @Override
    public PageResult<CommentDTO> getUserCommentList(Long userId, Integer page, Integer size) {
        // 获取用户
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new BusinessException("用户不存在"));

        // 获取用户评论
        Page<Comment> commentPage = commentRepository.findByUserOrderByCreateTimeDesc(
                user, PageRequest.of(page - 1, size)
        );

        // 转换为DTO
        List<CommentDTO> commentDTOs = commentPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());

        return new PageResult<>(
                commentDTOs,
                commentPage.getTotalElements(),
                page,
                size
        );
    }

    @Override
    public PageResult<CommentDTO> getAdminCommentList(Integer page, Integer size, String keyword, Integer targetType, Integer status) {
        // 构建查询条件
        Specification<Comment> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();

            // 关键字搜索
            if (keyword != null && !keyword.isEmpty()) {
                predicates.add(criteriaBuilder.like(root.get("content"), "%" + keyword + "%"));
            }

            // 目标类型筛选
            if (targetType != null) {
                predicates.add(criteriaBuilder.equal(root.get("targetType"), targetType));
            }

            // 状态筛选
            if (status != null) {
                predicates.add(criteriaBuilder.equal(root.get("status"), status));
            }

            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };

        // 执行查询
        Page<Comment> commentPage = commentRepository.findAll(
                spec, PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "createTime"))
        );

        // 转换为DTO
        List<CommentDTO> commentDTOs = commentPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());

        return new PageResult<>(
                commentDTOs,
                commentPage.getTotalElements(),
                page,
                size
        );
    }

    @Override
    @Transactional
    public boolean updateCommentStatus(Long id, Integer status) {
        // 获取评论
        Comment comment = commentRepository.findById(id)
                .orElseThrow(() -> new BusinessException("评论不存在"));

        // 更新状态
        comment.setStatus(status);
        commentRepository.save(comment);

        return true;
    }

    @Override
    @Transactional
    public boolean adminDeleteComment(Long id) {
        // 获取评论
        Comment comment = commentRepository.findById(id)
                .orElseThrow(() -> new BusinessException("评论不存在"));

        // 删除评论
        commentRepository.delete(comment);

        // 更新相关实体的评论数
        if (comment.getTargetType() == 1) {
            musicRepository.findById(comment.getTargetId()).ifPresent(music -> {
                long commentCount = commentRepository.countByTargetIdAndTargetType(comment.getTargetId(), 1);
                music.setCommentCount((int) commentCount);
                musicRepository.save(music);
            });
        } else if (comment.getTargetType() == 2) {
            playlistRepository.findById(comment.getTargetId()).ifPresent(playlist -> {
                long commentCount = commentRepository.countByTargetIdAndTargetType(comment.getTargetId(), 2);
                playlist.setCommentCount((int) commentCount);
                playlistRepository.save(playlist);
            });
        } else if (comment.getTargetType() == 3) {
            singerRepository.findById(comment.getTargetId()).ifPresent(singer -> {
                long commentCount = commentRepository.countByTargetIdAndTargetType(comment.getTargetId(), 3);
                singer.setCommentCount((int) commentCount);
                singerRepository.save(singer);
            });
        }

        // 如果是父评论，同时删除子评论
        if (comment.getParentId() == null) {
            List<Comment> children = commentRepository.findByParentIdOrderByCreateTimeAsc(id);
            if (!children.isEmpty()) {
                commentRepository.deleteAll(children);
            }
        }

        return true;
    }

    /**
     * 将实体转换为DTO
     *
     * @param comment 评论实体
     * @return 评论DTO
     */
    private CommentDTO convertToDTO(Comment comment) {
        CommentDTO commentDTO = new CommentDTO();
        BeanUtils.copyProperties(comment, commentDTO);

        // 设置用户信息
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(comment.getUser(), userDTO);
        
        // 确保头像URL是完整路径
        if (userDTO.getAvatar() != null && !userDTO.getAvatar().startsWith("http")) {
            userDTO.setAvatar("http://localhost:8085" + userDTO.getAvatar());
        }
        
        commentDTO.setUser(userDTO);

        return commentDTO;
    }
}
