package com.yida.data.school.atlas.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.core.toolkit.Wrappers;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.common.core.entity.apply.enums.DelFlagType;
import com.yida.data.common.core.entity.atlas.CoreAtlasAccessRecords;
import com.yida.data.common.core.entity.atlas.CoreAtlasManagement;
import com.yida.data.common.core.entity.atlas.CoreAtlasManagementDetails;
import com.yida.data.common.core.entity.atlas.CoreAtlasManagementDetailsComment;
import com.yida.data.common.core.entity.atlas.CoreAtlasManagementDetailsCommentReply;
import com.yida.data.common.core.entity.atlas.CoreAtlasManagementDetailsLike;
import com.yida.data.common.core.enums.AtlasManagementRedisEnum;
import com.yida.data.common.core.enums.EnableStatusEnum;
import com.yida.data.common.core.enums.LikeMarkEnum;
import com.yida.data.common.core.enums.WorkTypeEnum;
import com.yida.data.rabbit.constant.RabbitConstant;
import com.yida.data.rabbit.util.RabbitUtil;
import com.yida.data.school.atlas.mapper.CoreAtlasAccessRecordsMapper;
import com.yida.data.school.atlas.mapper.CoreAtlasManagementDetailsCommentMapper;
import com.yida.data.school.atlas.mapper.CoreAtlasManagementDetailsCommentReplyMapper;
import com.yida.data.school.atlas.mapper.CoreAtlasManagementDetailsLikeMapper;
import com.yida.data.school.atlas.mapper.CoreAtlasManagementDetailsMapper;
import com.yida.data.school.atlas.mapper.CoreAtlasManagementMapper;
import com.yida.data.school.atlas.service.AppAtlasService;
import com.yida.data.school.atlas.service.CoreAtlasManagementDetailsService;
import com.yida.data.school.atlas.service.CoreAtlasManagementService;
import com.yida.data.school.dto.atlas.AtlasSelectPageDTO;
import com.yida.data.school.dto.atlas.app.AppAtlasInfoDTO;
import com.yida.data.school.dto.atlas.app.AppAtlasWorkCommentReplySaveDTO;
import com.yida.data.school.dto.atlas.app.AppAtlasWorkCommentReplySelectDTO;
import com.yida.data.school.dto.atlas.app.AppAtlasWorkCommentSaveDTO;
import com.yida.data.school.dto.atlas.app.AppAtlasWorkCommentSelectDTO;
import com.yida.data.school.dto.atlas.app.AppAtlasWorkInfoDTO;
import com.yida.data.school.dto.atlas.app.AppAtlasWorkLikeDTO;
import com.yida.data.school.dto.atlas.app.AppAtlasWorkListDTO;
import com.yida.data.school.vo.atlas.AtlasSelectPageVO;
import com.yida.data.school.vo.atlas.app.AppAtlasInfoVO;
import com.yida.data.school.vo.atlas.app.AppAtlasWorkBaseVO;
import com.yida.data.school.vo.atlas.app.AppAtlasWorkCommentPageVO;
import com.yida.data.school.vo.atlas.app.AppAtlasWorkCommentReplyPageVO;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;

import cc.mrbird.febs.common.redis.service.RedisService;
import lombok.RequiredArgsConstructor;

/**
 * 学校图集app接口service层
 *
 * @author ZYJ
 * @date 2021/9/2
 */
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class AppAtlasServiceImpl implements AppAtlasService {

    private final RabbitUtil rabbitUtil;

    private final RedisService redisService;

    private final CoreAtlasManagementService coreAtlasManagementService;

    private final CoreAtlasManagementDetailsService coreAtlasManagementDetailsService;

    private final CoreAtlasManagementMapper coreAtlasManagementMapper;

    private final CoreAtlasManagementDetailsMapper coreAtlasManagementDetailsMapper;

    private final CoreAtlasAccessRecordsMapper coreAtlasAccessRecordsMapper;

    private final CoreAtlasManagementDetailsLikeMapper coreAtlasManagementDetailsLikeMapper;

    private final CoreAtlasManagementDetailsCommentMapper coreAtlasManagementDetailsCommentMapper;

    private final CoreAtlasManagementDetailsCommentReplyMapper coreAtlasManagementDetailsCommentReplyMapper;

    /**
     * 查询图集分页数据接口
     *
     * @param schoolId 学校id
     * @param pageNo   当前页码
     * @param pageSize 页面大小
     * @return com.yida.data.common.core.common.ResultBean<com.baomidou.mybatisplus.core.metadata.IPage < com.yida.data.atlas.vo.AtlasSelectPageVO>>
     * @author ZYJ
     * @date 2021/9/2 17:42
     */
    @Override
    public ResultBean<IPage<AtlasSelectPageVO>> listAtlasPage(Long schoolId, Integer pageNo, Integer pageSize) {
        return this.coreAtlasManagementService.listAtlasPage(AtlasSelectPageDTO.builder()
                .schoolId(schoolId)
                .pageNum(pageNo)
                .pageSize(pageSize)
                .enableStatus(EnableStatusEnum.ENABLE_STATUS.getStatus())
                .build());
    }

    /**
     * 获取图集详情接口
     *
     * @param appAtlasInfoDTO app获取图集详情接口请求类
     * @return com.yida.data.common.core.common.ResultBean<com.yida.data.atlas.vo.app.AppAtlasInfoVO>
     * @author ZYJ
     * @date 2021/9/6 10:59
     */
    @Override
    public ResultBean<AppAtlasInfoVO> getAtlasInfo(AppAtlasInfoDTO appAtlasInfoDTO) {
        // 返回数据
        AppAtlasInfoVO appAtlasInfoVO = new AppAtlasInfoVO();
        // 查询图集详情
        CoreAtlasManagement coreAtlasManagement = this.coreAtlasManagementService.getById(appAtlasInfoDTO.getAtlasId());
        BeanUtils.copyProperties(coreAtlasManagement, appAtlasInfoVO);
        // 先判断当前用户是否查看过改图集, 有则不添加访问量
        List<CoreAtlasAccessRecords> list =
                this.coreAtlasAccessRecordsMapper.selectList(
                        Wrappers.lambdaQuery(new CoreAtlasAccessRecords())
                                .eq(CoreAtlasAccessRecords::getCoreAtlasManagementId, appAtlasInfoDTO.getAtlasId())
                                .eq(CoreAtlasAccessRecords::getUserId, appAtlasInfoDTO.getUserId()));
        if (CollectionUtils.isEmpty(list)) {
            // 添加访问记录，并增加图集访问数
            CoreAtlasAccessRecords atlasAccessRecords = new CoreAtlasAccessRecords();
            BeanUtils.copyProperties(appAtlasInfoDTO, atlasAccessRecords);
            atlasAccessRecords.setCoreAtlasManagementId(appAtlasInfoDTO.getAtlasId());
            atlasAccessRecords.setCreateDate(LocalDateTime.now());
            this.coreAtlasAccessRecordsMapper.insert(atlasAccessRecords);
            // 增加图集访问数
            this.coreAtlasManagementService.update(new LambdaUpdateWrapper<>(new CoreAtlasManagement())
                    .eq(CoreAtlasManagement::getId, appAtlasInfoDTO.getAtlasId())
                    .set(CoreAtlasManagement::getAccessNum, coreAtlasManagement.getAccessNum() + 1));
        }
        // 处理图集作品数据
        List<CoreAtlasManagementDetails> detailsList =
                this.coreAtlasManagementDetailsService.list(new LambdaQueryWrapper<>(new CoreAtlasManagementDetails())
                        .eq(CoreAtlasManagementDetails::getCoreAtlasManagementId, appAtlasInfoDTO.getAtlasId())
                        .eq(CoreAtlasManagementDetails::getDelFlag, DelFlagType.NORMAL_TYPE.getValue())
                        .orderByDesc(CoreAtlasManagementDetails::getCreateDate));
        if (!CollectionUtils.isEmpty(detailsList)) {
            detailsList.forEach(details -> {
                List<CoreAtlasManagementDetailsLike> detailsLikeList = coreAtlasManagementDetailsLikeMapper.selectList(new LambdaQueryWrapper<>(new CoreAtlasManagementDetailsLike())
                        .eq(CoreAtlasManagementDetailsLike::getCoreAtlasManagementDetailsId, details.getId())
                        .eq(CoreAtlasManagementDetailsLike::getUserId, appAtlasInfoDTO.getUserId())
                        .eq(CoreAtlasManagementDetailsLike::getDelFlag, DelFlagType.NORMAL_TYPE.getValue()));
                // 设置是否已经点赞的状态
                details.setLikeMark(CollectionUtils.isEmpty(detailsLikeList) ? LikeMarkEnum.NOT_LIKED_STATUS.getStatus() : LikeMarkEnum.LIKED_STATUS.getStatus());
            });
            Map<String, List<AppAtlasWorkBaseVO>> map = detailsList.parallelStream().collect(
                    Collectors.groupingBy(CoreAtlasManagementDetails::getType,
                            Collectors.mapping(atlasManagementDetails -> {
                                AppAtlasWorkBaseVO appAtlasWorkBaseVO = new AppAtlasWorkBaseVO();
                                BeanUtils.copyProperties(atlasManagementDetails, appAtlasWorkBaseVO);
                                return appAtlasWorkBaseVO;
                            }, Collectors.toList())));
            // 处理图片数据
            appAtlasInfoVO.setPictureList(Objects.isNull(map.get(WorkTypeEnum.PICTURE_TYPE.getType())) ? new ArrayList<>() : map.get(WorkTypeEnum.PICTURE_TYPE.getType()));
            // 处理视频数据
            appAtlasInfoVO.setVideoList(Objects.isNull(map.get(WorkTypeEnum.VIDEO_TYPE.getType())) ? new ArrayList<>() : map.get(WorkTypeEnum.VIDEO_TYPE.getType()));
        }
        return ResultBean.buildSuccess(appAtlasInfoVO);
    }

    /**
     * 根据类型查询图集作品分页数据接口
     *
     * @param appAtlasWorkListDTO app根据类型查询图集作品分页数据请求类
     * @return com.yida.data.common.core.common.ResultBean<com.baomidou.mybatisplus.core.metadata.IPage < com.yida.data.atlas.vo.app.AppAtlasWorkBaseVO>>
     * @author ZYJ
     * @date 2021/9/6 17:29
     */
    @Override
    public ResultBean<IPage<AppAtlasWorkBaseVO>> listAtlasWorkByType(AppAtlasWorkListDTO appAtlasWorkListDTO) {
        IPage<AppAtlasWorkBaseVO> page =
                this.coreAtlasManagementDetailsService.listAtlasWorkByType(appAtlasWorkListDTO.toPage(),
                        appAtlasWorkListDTO);
        return ResultBean.buildSuccess(page);
    }

    /**
     * 获取图集作品作品详情接口
     *
     * @param appAtlasWorkInfoDTO app获取图集作品详情接口请求类
     * @return com.yida.data.common.core.common.ResultBean<com.yida.data.atlas.vo.app.AppAtlasWorkBaseVO>
     * @author ZYJ
     * @date 2021/9/6 17:46
     */
    @Override
    public ResultBean<AppAtlasWorkBaseVO> getAtlasWorkInfo(AppAtlasWorkInfoDTO appAtlasWorkInfoDTO) {
        CoreAtlasManagementDetails coreAtlasManagementDetails = this.coreAtlasManagementDetailsService.getById(appAtlasWorkInfoDTO.getAtlasDetailsId());
        // 返回数据
        AppAtlasWorkBaseVO appAtlasWorkBaseVO = new AppAtlasWorkBaseVO();
        Optional.ofNullable(coreAtlasManagementDetails).ifPresent(details -> {
            BeanUtils.copyProperties(coreAtlasManagementDetails, appAtlasWorkBaseVO);
            // 从redis中获取之前的点赞记录信息
            Object o = redisService.hget(AtlasManagementRedisEnum.ATLAS_MANAGEMENT_DETAILS_LIKE_DETAILS.
                    getValue() + ":" + appAtlasWorkInfoDTO.getAtlasDetailsId(), String.valueOf(appAtlasWorkInfoDTO.getUserId()));
            // 设置点赞状态
            appAtlasWorkBaseVO.setLikeMark(Objects.isNull(o) ? LikeMarkEnum.NOT_LIKED_STATUS.getStatus()
                    : LikeMarkEnum.LIKED_STATUS.getStatus());
        });
        return ResultBean.buildSuccess(appAtlasWorkBaseVO);
    }

    /**
     * 图集作品点赞接口
     *
     * @param appAtlasWorkLikeDTO app图集作品点赞接口请求类
     * @return com.yida.data.common.core.common.ResultBean<java.lang.String>
     * @author ZYJ
     * @date 2021/9/7 9:51
     */
    @Override
    public ResultBean<String> likeAtlasWork(AppAtlasWorkLikeDTO appAtlasWorkLikeDTO) {
        // 增加当前图片或视频的点赞数并保存进入redis
        redisService.hashIncrement(AtlasManagementRedisEnum.ATLAS_MANAGEMENT_DETAILS_LIKE_NUM.getValue(),
                String.valueOf(appAtlasWorkLikeDTO.getAtlasDetailsId()), 1L);
        // 同步增加图集点赞数更新redis
        redisService.hashIncrement(AtlasManagementRedisEnum.ATLAS_MANAGEMENT_LIKE_NUM.getValue(),
                String.valueOf(appAtlasWorkLikeDTO.getAtlasId()), 1L);
        // 同步保存当前用户对当前图片或视频的点赞记录进入redis
        // 需要生成唯一标识，以方便后续取消点赞
        String mark = UUID.randomUUID().toString().replace("-", "");
        CoreAtlasManagementDetailsLike coreAtlasManagementDetailsLike =
                CoreAtlasManagementDetailsLike.builder()
                        .coreAtlasManagementDetailsId(appAtlasWorkLikeDTO.getAtlasDetailsId())
                        .mark(mark)
                        .createDate(LocalDateTime.now())
                        .delFlag(DelFlagType.NORMAL_TYPE.getValue())
                        .userId(appAtlasWorkLikeDTO.getUserId())
                        .userName(appAtlasWorkLikeDTO.getUserName())
                        .nickName(appAtlasWorkLikeDTO.getNickName())
                        .build();
        redisService.hset(AtlasManagementRedisEnum.ATLAS_MANAGEMENT_DETAILS_LIKE_DETAILS.getValue()
                        + ":" + appAtlasWorkLikeDTO.getAtlasDetailsId(),
                String.valueOf(appAtlasWorkLikeDTO.getUserId()), coreAtlasManagementDetailsLike);
        // 发送mq点赞消息
        rabbitUtil.convertAndSendMsg(RabbitConstant.ATLAS_LIKE_EXCHANGE, RabbitConstant.ATLAS_LIKE_KEY,
                coreAtlasManagementDetailsLike);
        return ResultBean.buildSuccess();
    }

    /**
     * 图集作品取消点赞接口
     *
     * @param appAtlasWorkLikeDTO app图集作品点赞/取消点赞请求类
     * @return com.yida.data.common.core.common.ResultBean<java.lang.String>
     * @author ZYJ
     * @date 2021/9/7 15:56
     */
    @Override
    public ResultBean<String> cancelLikeAtlasWork(AppAtlasWorkLikeDTO appAtlasWorkLikeDTO) {
        // 从redis中获取之前的点赞记录信息
        CoreAtlasManagementDetailsLike coreAtlasManagementDetailsLike =
                (CoreAtlasManagementDetailsLike) redisService.hget(AtlasManagementRedisEnum.ATLAS_MANAGEMENT_DETAILS_LIKE_DETAILS.
                        getValue() + ":" + appAtlasWorkLikeDTO.getAtlasDetailsId(), String.valueOf(appAtlasWorkLikeDTO.getUserId()));
        Optional.ofNullable(coreAtlasManagementDetailsLike).ifPresent(detailsLike -> {
            detailsLike.setDelFlag(DelFlagType.DELETE_TYPE.getValue());
            // 减少当前图片或视频的点赞数并保存进入redis
            redisService.hashIncrement(AtlasManagementRedisEnum.ATLAS_MANAGEMENT_DETAILS_LIKE_NUM.getValue(),
                    String.valueOf(appAtlasWorkLikeDTO.getAtlasDetailsId()), -1L);
            // 同步减少图集点赞数更新redis
            redisService.hashIncrement(AtlasManagementRedisEnum.ATLAS_MANAGEMENT_LIKE_NUM.getValue(),
                    String.valueOf(appAtlasWorkLikeDTO.getAtlasId()), -1L);
            // 发送mq取消点赞消息
            rabbitUtil.convertAndSendMsg(RabbitConstant.ATLAS_LIKE_EXCHANGE, RabbitConstant.ATLAS_LIKE_KEY,
                    detailsLike);
        });
        return ResultBean.buildSuccess();
    }

    /**
     * app分页查询图集作品评论列表接口
     *
     * @param appAtlasWorkCommentSelectDTO app分页查询图集作品评论列表接口请求类
     * @return com.yida.data.common.core.common.ResultBean<com.baomidou.mybatisplus.core.metadata.IPage < com.yida.data.atlas.vo.app.AppAtlasWorkCommentPageVO>>
     * @author ZYJ
     * @date 2021/9/7 16:44
     */
    @Override
    public ResultBean<IPage<AppAtlasWorkCommentPageVO>> listAtlasWorkCommentPage(AppAtlasWorkCommentSelectDTO appAtlasWorkCommentSelectDTO) {
        // TODO 2021/9/7 需要查询评论回复数量
        IPage<AppAtlasWorkCommentPageVO> page =
                this.coreAtlasManagementDetailsCommentMapper.appListAtlasWorkCommentPage(appAtlasWorkCommentSelectDTO.toPage(), appAtlasWorkCommentSelectDTO);
        return ResultBean.buildSuccess(page);
    }

    /**
     * app保存图集作品评论接口
     *
     * @param appAtlasWorkCommentSaveDTO app保存图集作品评论接口请求类
     * @return com.yida.data.common.core.common.ResultBean<java.lang.String>
     * @author ZYJ
     * @date 2021/9/7 17:00
     */
    @Override
    public ResultBean<String> saveAtlasWorkComment(AppAtlasWorkCommentSaveDTO appAtlasWorkCommentSaveDTO) {
        // 设置评论保存数据
        CoreAtlasManagementDetailsComment coreAtlasManagementDetailsComment = new CoreAtlasManagementDetailsComment();
        BeanUtils.copyProperties(appAtlasWorkCommentSaveDTO, coreAtlasManagementDetailsComment);
        coreAtlasManagementDetailsComment.setCreateDate(LocalDateTime.now());
        // 保存评论
        this.coreAtlasManagementDetailsCommentMapper.insert(coreAtlasManagementDetailsComment);
        return ResultBean.buildSuccess();
    }

    /**
     * app分页查询评论回复列表接口
     *
     * @param appAtlasWorkCommentReplySelectDTO app分页查询评论回复列表接口请求类
     * @return com.yida.data.common.core.common.ResultBean<com.baomidou.mybatisplus.core.metadata.IPage < com.yida.data.atlas.vo.app.AppAtlasWorkCommentReplyPageVO>>
     * @author ZYJ
     * @date 2021/9/7 17:32
     */
    @Override
    public ResultBean<IPage<AppAtlasWorkCommentReplyPageVO>> listAtlasWorkCommentReplyPage(AppAtlasWorkCommentReplySelectDTO appAtlasWorkCommentReplySelectDTO) {
        IPage<AppAtlasWorkCommentReplyPageVO> page =
                this.coreAtlasManagementDetailsCommentReplyMapper.listAtlasWorkCommentReplyPage(appAtlasWorkCommentReplySelectDTO.toPage(), appAtlasWorkCommentReplySelectDTO);
        return ResultBean.buildSuccess(page);
    }

    /**
     * app保存评论回复接口
     *
     * @param appAtlasWorkCommentReplySaveDTO app保存评论回复接口请求类
     * @return com.yida.data.common.core.common.ResultBean<java.lang.String>
     * @author ZYJ
     * @date 2021/9/7 17:37
     */
    @Override
    public ResultBean<String> saveAtlasWorkCommentReply(AppAtlasWorkCommentReplySaveDTO appAtlasWorkCommentReplySaveDTO) {
        // 设置评论回复保存数据
        CoreAtlasManagementDetailsCommentReply coreAtlasManagementDetailsCommentReply = new CoreAtlasManagementDetailsCommentReply();
        BeanUtils.copyProperties(appAtlasWorkCommentReplySaveDTO, coreAtlasManagementDetailsCommentReply);
        coreAtlasManagementDetailsCommentReply.setCreateDate(LocalDateTime.now());
        // 保存评论回复
        this.coreAtlasManagementDetailsCommentReplyMapper.insert(coreAtlasManagementDetailsCommentReply);
        return ResultBean.buildSuccess();
    }
}
