package com.xindazhou.business.service.community.post;

import com.xindazhou.business.controller.app.community.post.vo.PostCreateReqVO;
import com.xindazhou.business.controller.app.community.post.vo.PostPageReqVO;
import com.xindazhou.business.controller.app.community.post.vo.PostRespVO;
import com.xindazhou.business.controller.app.community.post.vo.PostUpdateReqVO;
import com.xindazhou.business.controller.admin.community.post.vo.PostUpdateStatusReqVO;
import com.xindazhou.business.convert.community.post.PostConvert;
import com.xindazhou.business.dal.community.dataobject.post.PostDO;
import com.xindazhou.business.dal.community.dataobject.post.PostMediaDO;
import com.xindazhou.business.dal.community.mysql.post.CommunityPostMapper;
import com.xindazhou.business.dal.community.mysql.post.PostMediaMapper;
import com.xindazhou.business.dal.community.mysql.collect.CollectMapper;
import com.xindazhou.business.service.community.like.LikeService;
import com.xindazhou.business.service.community.sensitive.SensitiveWordService;
import com.xindazhou.framework.common.pojo.PageResult;
import com.xindazhou.framework.security.core.util.SecurityFrameworkUtils;
import com.xindazhou.user.api.user.MemberUserApi;
import com.xindazhou.user.api.user.dto.MemberUserRespDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

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

import static com.xindazhou.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.xindazhou.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_FOUND;
import static com.xindazhou.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;

/**
 * 帖子 Service 实现类
 *
 * @author xindazhou
 */
@Service("communityPostServiceImpl")
@Slf4j
@Validated
public class PostServiceImpl implements PostService {

    @Resource
    private CommunityPostMapper communityPostMapper;

    @Resource
    private MemberUserApi memberUserApi;

    @Resource
    private LikeService likeService;

    @Resource
    private CollectMapper collectMapper;

    @Resource
    private PostMediaMapper postMediaMapper;

    @Resource
    private SensitiveWordService sensitiveWordService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createPost(PostCreateReqVO createReqVO) {
        // 获取当前登录用户
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        
        // 敏感词过滤：标题和内容
        String filteredTitle = sensitiveWordService.filterSensitiveWord(createReqVO.getTitle());
        if (filteredTitle == null) {
            throw exception(BAD_REQUEST, "标题包含敏感词，不允许发布");
        }
        createReqVO.setTitle(filteredTitle);
        
        if (createReqVO.getContent() != null && !createReqVO.getContent().trim().isEmpty()) {
            String filteredContent = sensitiveWordService.filterSensitiveWord(createReqVO.getContent());
            if (filteredContent == null) {
                throw exception(BAD_REQUEST, "内容包含敏感词，不允许发布");
            }
            createReqVO.setContent(filteredContent);
        }
        
        // 校验内容类型和媒体列表的匹配
        validateContentTypeAndMedia(createReqVO.getContentType(), createReqVO.getMediaList());
        
        // 校验内容：纯文本和图文混合必须有内容
        if ((createReqVO.getContentType() == 1 || createReqVO.getContentType() == 4) 
                && (createReqVO.getContent() == null || createReqVO.getContent().trim().isEmpty())) {
            throw exception(NOT_FOUND, "纯文本和图文混合类型必须填写内容");
        }
        
        // 插入帖子
        PostDO post = PostConvert.INSTANCE.convert(createReqVO);
        post.setUserId(userId);
        post.setStatus(1); // 1-正常
        post.setViewCount(0);
        post.setLikeCount(0);
        post.setCommentCount(0);
        post.setCollectCount(0);
        post.setIsTop(0);
        post.setIsEssence(0);
        communityPostMapper.insert(post);
        
        // 插入媒体文件
        if (createReqVO.getMediaList() != null && !createReqVO.getMediaList().isEmpty()) {
            savePostMedia(post.getId(), createReqVO.getMediaList());
        }
        
        return post.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePost(PostUpdateReqVO updateReqVO) {
        // 校验帖子存在
        PostDO post = validatePostExists(updateReqVO.getId());
        
        // 校验权限：只能修改自己的帖子
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        if (!post.getUserId().equals(userId)) {
            throw exception(NOT_FOUND, "无权修改该帖子");
        }
        
        // 敏感词过滤：标题和内容
        String filteredTitle = sensitiveWordService.filterSensitiveWord(updateReqVO.getTitle());
        if (filteredTitle == null) {
            throw exception(BAD_REQUEST, "标题包含敏感词，不允许发布");
        }
        updateReqVO.setTitle(filteredTitle);
        
        if (updateReqVO.getContent() != null && !updateReqVO.getContent().trim().isEmpty()) {
            String filteredContent = sensitiveWordService.filterSensitiveWord(updateReqVO.getContent());
            if (filteredContent == null) {
                throw exception(BAD_REQUEST, "内容包含敏感词，不允许发布");
            }
            updateReqVO.setContent(filteredContent);
        }
        
        // 校验内容类型和媒体列表的匹配
        validateContentTypeAndMedia(updateReqVO.getContentType(), updateReqVO.getMediaList());
        
        // 更新帖子
        PostDO updateObj = PostConvert.INSTANCE.convert(updateReqVO);
        communityPostMapper.updateById(updateObj);
        
        // 更新媒体文件：先删除旧的，再插入新的
        if (updateReqVO.getMediaList() != null) {
            postMediaMapper.deleteByPostId(updateReqVO.getId());
            if (!updateReqVO.getMediaList().isEmpty()) {
                savePostMedia(updateReqVO.getId(), updateReqVO.getMediaList());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePost(Long id) {
        // 校验帖子存在
        PostDO post = validatePostExists(id);
        
        // 校验权限：只能删除自己的帖子
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        if (!post.getUserId().equals(userId)) {
            throw exception(NOT_FOUND, "无权删除该帖子");
        }
        
        // 删除（逻辑删除）
        communityPostMapper.deleteById(id);
        
        // 删除关联的媒体文件（逻辑删除）
        postMediaMapper.deleteByPostId(id);
    }

    @Override
    public PostRespVO getPost(Long id) {
        PostDO post = validatePostExists(id);
        
        // 增加浏览数
        incrementViewCount(id);
        
        // 转换为 VO
        PostRespVO respVO = PostConvert.INSTANCE.convert(post);
        
        // 填充用户信息
        fillUserInfo(respVO, post.getUserId());
        
        // 填充媒体文件
        fillMediaList(respVO, id);
        
        // 填充点赞和收藏状态
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        if (userId != null) {
            respVO.setIsLiked(likeService.isLiked(1, id)); // 1-帖子
            respVO.setIsCollected(isCollected(id));
        } else {
            respVO.setIsLiked(false);
            respVO.setIsCollected(false);
        }
        
        return respVO;
    }

    @Override
    public PageResult<PostRespVO> getPostPage(PostPageReqVO reqVO) {
        PageResult<PostDO> pageResult = communityPostMapper.selectPage(reqVO);
        
        // 转换为 VO
        PageResult<PostRespVO> result = PostConvert.INSTANCE.convertPage(pageResult);
        
        // 批量填充用户信息
        fillUserInfoList(result.getList());
        
        // 批量填充媒体文件
        fillMediaListBatch(result.getList());
        
        // 批量填充点赞和收藏状态
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        if (userId != null) {
            fillLikeAndCollectStatus(result.getList(), userId);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void incrementViewCount(Long id) {
        // 使用数据库的增量更新
        PostDO post = communityPostMapper.selectById(id);
        if (post != null) {
            post.setViewCount(post.getViewCount() + 1);
            communityPostMapper.updateById(post);
        }
    }

    /**
     * 填充单个帖子的用户信息
     */
    private void fillUserInfo(PostRespVO respVO, Long userId) {
        if (userId == null) {
            return;
        }
        MemberUserRespDTO user = memberUserApi.getUser(userId).getCheckedData();
        if (user != null) {
            respVO.setUserNickname(user.getNickname());
            respVO.setUserAvatar(user.getAvatar());
        }
    }

    /**
     * 批量填充帖子列表的用户信息
     */
    private void fillUserInfoList(List<PostRespVO> list) {
        if (list == null || list.isEmpty()) {
            return;
        }
        Set<Long> userIds = list.stream()
                .map(PostRespVO::getUserId)
                .filter(userId -> userId != null)
                .collect(Collectors.toSet());
        if (userIds.isEmpty()) {
            return;
        }
        Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
        list.forEach(post -> {
            MemberUserRespDTO user = userMap.get(post.getUserId());
            if (user != null) {
                post.setUserNickname(user.getNickname());
                post.setUserAvatar(user.getAvatar());
            }
        });
    }

    /**
     * 批量填充点赞和收藏状态
     */
    private void fillLikeAndCollectStatus(List<PostRespVO> list, Long userId) {
        if (list == null || list.isEmpty()) {
            return;
        }
        List<Long> postIds = list.stream()
                .map(PostRespVO::getId)
                .collect(Collectors.toList());
        
        // 批量查询点赞状态
        for (PostRespVO post : list) {
            post.setIsLiked(likeService.isLiked(1, post.getId())); // 1-帖子
            post.setIsCollected(isCollected(post.getId()));
        }
    }

    @Override
    public PageResult<com.xindazhou.business.controller.admin.community.post.vo.PostRespVO> getPostPageAdmin(com.xindazhou.business.controller.admin.community.post.vo.PostPageReqVO reqVO) {
        PageResult<PostDO> pageResult = communityPostMapper.selectPageAdmin(reqVO);
        
        // 转换为管理后台VO
        List<com.xindazhou.business.controller.admin.community.post.vo.PostRespVO> adminPosts = pageResult.getList().stream()
                .map(post -> {
                    com.xindazhou.business.controller.admin.community.post.vo.PostRespVO adminPost = new com.xindazhou.business.controller.admin.community.post.vo.PostRespVO();
                    adminPost.setId(post.getId());
                    adminPost.setUserId(post.getUserId());
                    adminPost.setTitle(post.getTitle());
                    adminPost.setContent(post.getContent());
                    adminPost.setContentType(post.getContentType());
                    adminPost.setViewCount(post.getViewCount());
                    adminPost.setLikeCount(post.getLikeCount());
                    adminPost.setCommentCount(post.getCommentCount());
                    adminPost.setCollectCount(post.getCollectCount());
                    adminPost.setStatus(post.getStatus());
                    adminPost.setIsTop(post.getIsTop());
                    adminPost.setIsEssence(post.getIsEssence());
                    adminPost.setTags(post.getTags());
                    adminPost.setCreateTime(post.getCreateTime());
                    adminPost.setUpdateTime(post.getUpdateTime());
                    return adminPost;
                })
                .collect(Collectors.toList());
        
        // 批量填充用户信息
        Set<Long> userIds = adminPosts.stream()
                .map(com.xindazhou.business.controller.admin.community.post.vo.PostRespVO::getUserId)
                .filter(userId -> userId != null)
                .collect(Collectors.toSet());
        if (!userIds.isEmpty()) {
            Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
            adminPosts.forEach(post -> {
                MemberUserRespDTO user = userMap.get(post.getUserId());
                if (user != null) {
                    post.setUserNickname(user.getNickname());
                }
            });
        }
        
        return new PageResult<>(adminPosts, pageResult.getTotal());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePostStatus(PostUpdateStatusReqVO updateReqVO) {
        // 校验帖子存在
        PostDO post = validatePostExists(updateReqVO.getId());
        
        // 更新状态
        PostDO updateObj = new PostDO();
        updateObj.setId(updateReqVO.getId());
        if (updateReqVO.getStatus() != null) {
            updateObj.setStatus(updateReqVO.getStatus());
        }
        if (updateReqVO.getIsTop() != null) {
            updateObj.setIsTop(updateReqVO.getIsTop());
        }
        if (updateReqVO.getIsEssence() != null) {
            updateObj.setIsEssence(updateReqVO.getIsEssence());
        }
        communityPostMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePostAdmin(Long id) {
        // 校验帖子存在
        validatePostExists(id);
        // 删除（逻辑删除）
        communityPostMapper.deleteById(id);
        // 删除关联的媒体文件（逻辑删除）
        postMediaMapper.deleteByPostId(id);
    }

    /**
     * 保存帖子媒体文件
     */
    private void savePostMedia(Long postId, List<PostCreateReqVO.PostMediaVO> mediaList) {
        if (mediaList == null || mediaList.isEmpty()) {
            return;
        }
        for (int i = 0; i < mediaList.size(); i++) {
            PostCreateReqVO.PostMediaVO mediaVO = mediaList.get(i);
            PostMediaDO media = new PostMediaDO();
            media.setPostId(postId);
            media.setMediaType(mediaVO.getMediaType());
            media.setMediaUrl(mediaVO.getMediaUrl());
            media.setCoverUrl(mediaVO.getCoverUrl());
            media.setDuration(mediaVO.getDuration());
            media.setFileSize(mediaVO.getFileSize());
            media.setSort(mediaVO.getSort() != null ? mediaVO.getSort() : i);
            postMediaMapper.insert(media);
        }
    }

    /**
     * 校验内容类型和媒体列表的匹配
     */
    private void validateContentTypeAndMedia(Integer contentType, List<PostCreateReqVO.PostMediaVO> mediaList) {
        if (contentType == null) {
            return;
        }
        
        boolean hasMedia = mediaList != null && !mediaList.isEmpty();
        boolean hasImage = hasMedia && mediaList.stream().anyMatch(m -> m.getMediaType() == 1);
        boolean hasVideo = hasMedia && mediaList.stream().anyMatch(m -> m.getMediaType() == 2);
        
        switch (contentType) {
            case 1: // 纯文本
                if (hasMedia) {
                    throw exception(NOT_FOUND, "纯文本类型不能包含媒体文件");
                }
                break;
            case 2: // 图片
                if (!hasImage) {
                    throw exception(NOT_FOUND, "图片类型必须包含至少一张图片");
                }
                if (hasVideo) {
                    throw exception(NOT_FOUND, "图片类型不能包含视频");
                }
                break;
            case 3: // 视频
                if (!hasVideo) {
                    throw exception(NOT_FOUND, "视频类型必须包含至少一个视频");
                }
                if (mediaList.size() > 1) {
                    throw exception(NOT_FOUND, "视频类型只能包含一个视频");
                }
                break;
            case 4: // 图文混合
                if (!hasImage) {
                    throw exception(NOT_FOUND, "图文混合类型必须包含至少一张图片");
                }
                break;
            default:
                throw exception(NOT_FOUND, "不支持的内容类型");
        }
    }

    /**
     * 填充单个帖子的媒体文件
     */
    private void fillMediaList(PostRespVO respVO, Long postId) {
        List<PostMediaDO> mediaList = postMediaMapper.selectListByPostId(postId);
        if (mediaList == null || mediaList.isEmpty()) {
            respVO.setMediaList(new ArrayList<>());
            return;
        }
        
        List<PostRespVO.PostMediaVO> mediaVOList = mediaList.stream()
                .map(media -> {
                    PostRespVO.PostMediaVO mediaVO = new PostRespVO.PostMediaVO();
                    mediaVO.setMediaType(media.getMediaType());
                    mediaVO.setMediaUrl(media.getMediaUrl());
                    mediaVO.setCoverUrl(media.getCoverUrl());
                    mediaVO.setDuration(media.getDuration());
                    mediaVO.setFileSize(media.getFileSize());
                    return mediaVO;
                })
                .collect(Collectors.toList());
        respVO.setMediaList(mediaVOList);
    }

    /**
     * 批量填充帖子列表的媒体文件
     */
    private void fillMediaListBatch(List<PostRespVO> list) {
        if (list == null || list.isEmpty()) {
            return;
        }
        List<Long> postIds = list.stream()
                .map(PostRespVO::getId)
                .collect(Collectors.toList());
        
        List<PostMediaDO> allMediaList = postMediaMapper.selectListByPostIds(postIds);
        Map<Long, List<PostMediaDO>> mediaMap = allMediaList.stream()
                .collect(Collectors.groupingBy(PostMediaDO::getPostId));
        
        list.forEach(post -> {
            List<PostMediaDO> mediaList = mediaMap.getOrDefault(post.getId(), new ArrayList<>());
            List<PostRespVO.PostMediaVO> mediaVOList = mediaList.stream()
                    .map(media -> {
                        PostRespVO.PostMediaVO mediaVO = new PostRespVO.PostMediaVO();
                        mediaVO.setMediaType(media.getMediaType());
                        mediaVO.setMediaUrl(media.getMediaUrl());
                        mediaVO.setCoverUrl(media.getCoverUrl());
                        mediaVO.setDuration(media.getDuration());
                        mediaVO.setFileSize(media.getFileSize());
                        return mediaVO;
                    })
                    .collect(Collectors.toList());
            post.setMediaList(mediaVOList);
        });
    }

    private PostDO validatePostExists(Long id) {
        PostDO post = communityPostMapper.selectById(id);
        if (post == null) {
            throw exception(NOT_FOUND, "帖子不存在");
        }
        return post;
    }

    /**
     * 查询用户是否已收藏帖子
     */
    private Boolean isCollected(Long postId) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        if (userId == null) {
            return false;
        }
        com.xindazhou.business.dal.community.dataobject.collect.CollectDO collect = 
            collectMapper.selectByUserIdAndPostId(userId, postId);
        return collect != null;
    }

}

