package com.emotion.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.emotion.common.PageResult;
import com.emotion.dto.request.DiaryCommentCreateRequest;
import com.emotion.dto.request.DiaryCommentPageRequest;
import com.emotion.dto.response.DiaryCommentResponse;
import com.emotion.entity.DiaryComment;
import com.emotion.mapper.DiaryCommentMapper;
import com.emotion.service.DiaryCommentService;
import com.emotion.util.SnowflakeIdGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 日记评论服务实现类
 * 
 * @author huazhongmin
 * @date 2025-07-23
 */
@Service
public class DiaryCommentServiceImpl extends ServiceImpl<DiaryCommentMapper, DiaryComment> implements DiaryCommentService {

    @Autowired
    private SnowflakeIdGenerator snowflakeIdGenerator;

    @Autowired
    private ObjectMapper objectMapper;

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public PageResult<DiaryCommentResponse> getPageWithResponse(DiaryCommentPageRequest request) {
        Page<DiaryComment> page = new Page<>(request.getCurrent(), request.getSize());
        LambdaQueryWrapper<DiaryComment> wrapper = new LambdaQueryWrapper<>();

        // 基础查询条件
        wrapper.eq(DiaryComment::getIsDeleted, 0);

        // 根据请求参数添加查询条件
        if (StringUtils.hasText(request.getDiaryId())) {
            wrapper.eq(DiaryComment::getDiaryId, request.getDiaryId());
        }
        if (StringUtils.hasText(request.getUserId())) {
            wrapper.eq(DiaryComment::getUserId, request.getUserId());
        }
        if (StringUtils.hasText(request.getCommentType())) {
            wrapper.eq(DiaryComment::getCommentType, request.getCommentType());
        }
        if (request.getTopLevelOnly() != null && request.getTopLevelOnly()) {
            wrapper.isNull(DiaryComment::getParentCommentId);
        }

        // 排序
        wrapper.orderByDesc(DiaryComment::getIsTop)
               .orderByDesc(DiaryComment::getPublishTime);

        IPage<DiaryComment> resultPage = this.page(page, wrapper);
        return convertPageToResponse(resultPage);
    }

    @Override
    public DiaryCommentResponse getCommentResponseById(String id) {
        DiaryComment comment = this.getById(id);
        if (comment == null) {
            return null;
        }
        return convertToResponse(comment);
    }

    @Override
    public List<DiaryCommentResponse> getCommentTreeWithResponse(String diaryId) {
        List<DiaryComment> comments = this.getCommentTree(diaryId);
        return comments.stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList());
    }

    @Override
    public DiaryCommentResponse createCommentWithResponse(DiaryCommentCreateRequest request) {
        DiaryComment comment = DiaryComment.builder()
                .id(snowflakeIdGenerator.nextIdAsString()) // 使用雪花算法生成ID
                .diaryId(request.getDiaryId())
                .userId(request.getUserId())
                .content(request.getContent())
                .images(convertListToJson(request.getImages()))
                .parentCommentId(request.getParentCommentId())
                .commentType("user")
                .likeCount(0)
                .replyCount(0)
                .isAnonymous(request.getIsAnonymous())
                .isTop(0)
                .status("published")
                .publishTime(LocalDateTime.now())
                .build();

        this.save(comment);

        // 如果有父评论，更新父评论的回复数
        if (StringUtils.hasText(request.getParentCommentId())) {
            this.incrementReplyCount(request.getParentCommentId());
            this.updateLastReplyTime(request.getParentCommentId());
        }

        return convertToResponse(comment);
    }

    @Override
    public DiaryCommentResponse updateCommentWithResponse(DiaryCommentCreateRequest request) {
        LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(DiaryComment::getId, request.getId())
                .set(StringUtils.hasText(request.getContent()), DiaryComment::getContent, request.getContent())
                .set(request.getImages() != null, DiaryComment::getImages, convertListToJson(request.getImages()))
                .set(DiaryComment::getUpdateTime, LocalDateTime.now());

        boolean updated = this.update(wrapper);
        if (!updated) {
            return null;
        }

        DiaryComment updatedComment = this.getById(request.getId());
        return updatedComment != null ? convertToResponse(updatedComment) : null;
    }

    @Override
    public boolean deleteComment(String commentId) {
        return this.removeById(commentId);
    }

    @Override
    public boolean softDeleteComment(String commentId) {
        LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(DiaryComment::getId, commentId)
                .set(DiaryComment::getIsDeleted, 1)
                .set(DiaryComment::getUpdateTime, LocalDateTime.now());
        return this.update(wrapper);
    }

    @Override
    public boolean restoreComment(String commentId) {
        LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(DiaryComment::getId, commentId)
                .set(DiaryComment::getIsDeleted, 0)
                .set(DiaryComment::getUpdateTime, LocalDateTime.now());
        return this.update(wrapper);
    }

    @Override
    public boolean incrementLikeCount(String commentId) {
        LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(DiaryComment::getId, commentId)
                .setSql("like_count = like_count + 1")
                .set(DiaryComment::getUpdateTime, LocalDateTime.now());
        return this.update(wrapper);
    }

    @Override
    public boolean decrementLikeCount(String commentId) {
        LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(DiaryComment::getId, commentId)
                .setSql("like_count = GREATEST(like_count - 1, 0)")
                .set(DiaryComment::getUpdateTime, LocalDateTime.now());
        return this.update(wrapper);
    }

    @Override
    public boolean setTop(String commentId, Integer isTop) {
        LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(DiaryComment::getId, commentId)
                .set(DiaryComment::getIsTop, isTop)
                .set(DiaryComment::getUpdateTime, LocalDateTime.now());
        return this.update(wrapper);
    }

    /**
     * 获取评论树结构
     */
    private List<DiaryComment> getCommentTree(String diaryId) {
        // 获取所有顶级评论（没有父评论的评论）
        LambdaQueryWrapper<DiaryComment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DiaryComment::getDiaryId, diaryId)
                .isNull(DiaryComment::getParentCommentId)
                .eq(DiaryComment::getIsDeleted, 0)
                .orderByDesc(DiaryComment::getIsTop)
                .orderByDesc(DiaryComment::getPublishTime);

        List<DiaryComment> topComments = this.list(wrapper);

        // 为每个顶级评论加载回复
        return topComments.stream()
                .peek(comment -> {
                    List<DiaryComment> replies = getRepliesByParentId(comment.getId());
                    // 这里可以递归加载更深层的回复，但为了性能考虑，通常只加载一层
                })
                .collect(Collectors.toList());
    }

    /**
     * 根据父评论ID查询回复列表
     */
    private List<DiaryComment> getRepliesByParentId(String parentCommentId) {
        LambdaQueryWrapper<DiaryComment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DiaryComment::getParentCommentId, parentCommentId)
                .eq(DiaryComment::getIsDeleted, 0)
                .orderByAsc(DiaryComment::getPublishTime);
        return this.list(wrapper);
    }

    /**
     * 增加回复数
     */
    private boolean incrementReplyCount(String commentId) {
        LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(DiaryComment::getId, commentId)
                .setSql("reply_count = reply_count + 1")
                .set(DiaryComment::getUpdateTime, LocalDateTime.now());
        return this.update(wrapper);
    }

    /**
     * 减少回复数
     */
    private boolean decrementReplyCount(String commentId) {
        LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(DiaryComment::getId, commentId)
                .setSql("reply_count = GREATEST(reply_count - 1, 0)")
                .set(DiaryComment::getUpdateTime, LocalDateTime.now());
        return this.update(wrapper);
    }

    /**
     * 更新最后回复时间
     */
    private boolean updateLastReplyTime(String commentId) {
        LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(DiaryComment::getId, commentId)
                .set(DiaryComment::getLastReplyTime, LocalDateTime.now())
                .set(DiaryComment::getUpdateTime, LocalDateTime.now());
        return this.update(wrapper);
    }

    /**
     * 转换为响应对象
     */
    private DiaryCommentResponse convertToResponse(DiaryComment comment) {
        DiaryCommentResponse response = new DiaryCommentResponse();
        BeanUtils.copyProperties(comment, response);

        // 转换时间格式
        if (comment.getPublishTime() != null) {
            response.setPublishTime(comment.getPublishTime().format(DATE_TIME_FORMATTER));
        }
        if (comment.getLastReplyTime() != null) {
            response.setLastReplyTime(comment.getLastReplyTime().format(DATE_TIME_FORMATTER));
        }
        if (comment.getCreateTime() != null) {
            response.setCreateTime(comment.getCreateTime().format(DATE_TIME_FORMATTER));
        }
        if (comment.getUpdateTime() != null) {
            response.setUpdateTime(comment.getUpdateTime().format(DATE_TIME_FORMATTER));
        }

        // 转换JSON字段
        try {
            if (comment.getImages() != null) {
                response.setImages(objectMapper.readValue(comment.getImages(), new TypeReference<List<String>>() {
                }));
            }
            if (comment.getMetadata() != null) {
                response.setMetadata(objectMapper.readValue(comment.getMetadata(), Object.class));
            }
        } catch (JsonProcessingException e) {
            // 忽略JSON解析错误
        }

        return response;
    }

    /**
     * 转换分页对象为响应对象
     */
    private PageResult<DiaryCommentResponse> convertPageToResponse(IPage<DiaryComment> page) {
        PageResult<DiaryCommentResponse> responsePage = new PageResult<>();
        responsePage.setCurrent(page.getCurrent());
        responsePage.setSize(page.getSize());
        responsePage.setTotal(page.getTotal());
        responsePage.setPages(page.getPages());
        responsePage.setRecords(
                page.getRecords().stream()
                        .map(this::convertToResponse)
                        .collect(Collectors.toList()));
        return responsePage;
    }

    /**
     * 将List转换为JSON字符串
     */
    private String convertListToJson(List<?> list) {
        if (list == null || list.isEmpty()) {
            return null;
        }
        try {
            return objectMapper.writeValueAsString(list);
        } catch (JsonProcessingException e) {
            return null;
        }
    }
}