package com.yonge.cooleshow.bbs.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.bbs.dao.BbsArticleDao;
import com.yonge.cooleshow.bbs.dao.BbsAuthRecordDao;
import com.yonge.cooleshow.bbs.dto.search.BbsArticleSearch;
import com.yonge.cooleshow.bbs.dto.search.BbsReplySearch;
import com.yonge.cooleshow.bbs.entity.BbsArticle;
import com.yonge.cooleshow.bbs.entity.BbsAuthRecord;
import com.yonge.cooleshow.bbs.enums.ArticleEnum;
import com.yonge.cooleshow.bbs.enums.YesOrNoEnum;
import com.yonge.cooleshow.bbs.service.BbsArticleService;
import com.yonge.cooleshow.bbs.vo.BbsArticleVo;
import com.yonge.cooleshow.bbs.vo.BbsReplyVo;
import com.yonge.cooleshow.common.enums.SysUserType;
import com.yonge.toolset.base.exception.BizException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class BbsArticleServiceImpl extends ServiceImpl<BbsArticleDao, BbsArticle> implements BbsArticleService {
    private final static Logger log = LoggerFactory.getLogger(BbsArticleServiceImpl.class);
    private final static String VIEW = "view";

    @Resource(name = "redis1")
    private RedisTemplate redisTemplate;
    @Autowired
    private BbsAuthRecordDao authRecordDao;

    /**
     * @Description: 详情-发布文章
     * @Author: cy
     * @Date: 2022/6/11
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addArticle(BbsArticle bbsArticle) {
        //状态为null,默认审核中,否则为草稿
        if (bbsArticle.getStatus() == null) {
            bbsArticle.setStatus(ArticleEnum.DOING);
            baseMapper.addArticle(bbsArticle);

            //新增审核记录
            BbsAuthRecord authRecord = new BbsAuthRecord();
            authRecord.setVerifyUserId(bbsArticle.getUserId());
            authRecord.setArticleId(bbsArticle.getId());
            authRecord.setAuditState(ArticleEnum.DOING);
            authRecordDao.insert(authRecord);
        } else {
            bbsArticle.setStatus(ArticleEnum.DRAFT);
            baseMapper.addArticle(bbsArticle);
        }
    }

    /**
     * @Description: 详情-修改文章
     * @Author: cy
     * @Date: 2022/6/11
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateArticle(BbsArticle bbsArticle, Long userId) {
        BbsArticle article = baseMapper.selectById(bbsArticle.getId());
        if (article == null) {
            throw new BizException("文章不存在");
        }
        if (!userId.equals(article.getUserId())) {
            throw new BizException("只能修改自己的文章");
        }

        bbsArticle.setStatus(ArticleEnum.DOING);
        baseMapper.updateById(bbsArticle);

        //删除原审核记录
        authRecordDao.delete(Wrappers.<BbsAuthRecord>lambdaQuery()
                .eq(BbsAuthRecord::getArticleId, bbsArticle.getId())
                .eq(BbsAuthRecord::getAuditState, ArticleEnum.DOING));

        //新增审核记录
        BbsAuthRecord authRecord = new BbsAuthRecord();
        authRecord.setVerifyUserId(bbsArticle.getUserId());
        authRecord.setArticleId(bbsArticle.getId());
        authRecord.setAuditState(ArticleEnum.DOING);
        authRecordDao.insert(authRecord);
    }

    /**
     * @Description: 详情-删除文章
     * @Author: cy
     * @Date: 2022/6/11
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteArticle(Map<String, List<Long>> ids, SysUser user) {
        List<Long> list = ids.get("ids");
        if (CollectionUtils.isEmpty(list)) {
            throw new BizException("文章id不能为空");
        }

        //当前用户为管理员
        if (user.getUserType().contains(SysUserType.SYSTEM.getCode())) {
            baseMapper.deleteArticle(list);
        } else {
            List<BbsArticle> articles = baseMapper.selectBatchIds(list);
            List<Long> idList = articles.stream().map(BbsArticle::getUserId).distinct().collect(Collectors.toList());
            if (idList.size() != 1 || !user.getId().equals(idList.get(0))) {
                throw new BizException("无法删除他人文章");
            }
            baseMapper.deleteArticle(list);
        }
    }

    /**
     * @Description: 后台管理-置顶文章
     * @Author: cy
     * @Date: 2022/6/11
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void articleTop(BbsArticle article) {
        BbsArticle bbsArticle = baseMapper.selectById(article.getId());
        YesOrNoEnum topFlag = bbsArticle.getTopFlag();
        if (topFlag.getCode() == 0) {
            article.setTopFlag(YesOrNoEnum.YES);//未置顶 -> 置顶
        } else {
            article.setTopFlag(YesOrNoEnum.NO);//置顶 -> 未置顶
        }
        baseMapper.updateById(article);
    }

    @Override
    public IPage<BbsArticleVo> selectPage(IPage<BbsArticleVo> page, BbsArticleSearch query) {
        return page.setRecords(baseMapper.selectPage(page, query));
    }

    /**
     * @Description: 查询文章详情
     * @Author: cy
     * @Date: 2022/6/14
     */
    @Override
    public BbsArticleVo articleInfo(Long articleId) {
        BbsArticleVo bbsArticle = baseMapper.articleInfo(articleId);
        redisTemplate.opsForHash().increment(VIEW, String.valueOf(articleId), 1);
        return bbsArticle;
    }

    /**
     * @Description: 文章评论列表
     * @Author: cy
     * @Date: 2022/6/14
     */
    @Override
    public IPage<BbsReplyVo> articleReply(IPage<BbsReplyVo> page, BbsReplySearch query) {
        query.setStatus(ArticleEnum.PASS);
        List<BbsReplyVo> allReply = baseMapper.articleReply(null, query);

        List<BbsReplyVo> tree = allReply.stream().filter((parentReply) -> {
            return parentReply.getParentId() == 0;
        }).map((p) -> {
            List<BbsReplyVo> list = new ArrayList<>();


            List<BbsReplyVo> childrens = getChildren(p, allReply, list);
            List<BbsReplyVo> collect = childrens.stream().sorted(Comparator.comparing(BbsReplyVo::getCreatedTime)).collect(Collectors.toList());
            p.setChildren(collect);
            return p;
        }).collect(Collectors.toList());
        return page.setRecords(tree);
    }

    private List<BbsReplyVo> getChildren(BbsReplyVo rootReply, List<BbsReplyVo> allReply, List<BbsReplyVo> list) {
        allReply.stream().filter(categoryEntity -> {
            return categoryEntity.getParentId().equals(rootReply.getId());
        }).map(child -> {
            list.add(child);
            getChildren(child, allReply, list);
            return child;
        }).collect(Collectors.toList());
        return list;
    }
}