package com.mcwl.resource.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mcwl.common.constant.QueueConstants;
import com.mcwl.common.core.domain.entity.SysUser;
import com.mcwl.common.utils.SecurityUtils;
import com.mcwl.resource.domain.ModelImage;
import com.mcwl.resource.domain.ModelProduct;
import com.mcwl.resource.domain.SysAdvice;
import com.mcwl.resource.domain.WorkFlow;
import com.mcwl.resource.domain.dto.SysAdviceDto;
import com.mcwl.resource.domain.vo.AdviceVo;
import com.mcwl.resource.domain.vo.AttentionAdviceVo;
import com.mcwl.resource.domain.vo.CommentAdviceVo;
import com.mcwl.resource.domain.vo.LikeAdviceVo;
import com.mcwl.resource.mapper.SysAdviceMapper;
import com.mcwl.resource.service.ISysAdviceService;
import com.mcwl.resource.service.ModelImageService;
import com.mcwl.resource.service.ModelService;
import com.mcwl.resource.service.WorkFlowService;
import com.mcwl.system.domain.enums.AdviceEnum;
import com.mcwl.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 消息管理 业务层处理
 */
@Service
@RequiredArgsConstructor
public class SysAdviceServiceImpl extends ServiceImpl<SysAdviceMapper, SysAdvice> implements ISysAdviceService {

    private final ISysUserService sysUserService;

    private final ModelService modelService;

    private final WorkFlowService workFlowService;

    private final ModelImageService modelImageService;

    private final RabbitTemplate rabbitTemplate;

    private final Map<Long, ModelProduct> modelProductMap = new ConcurrentHashMap<>();
    private final Map<Long, WorkFlow> workFlowMap = new ConcurrentHashMap<>();
    private final Map<Long, ModelImage> modelImageMap = new ConcurrentHashMap<>();

    @Override
    public List<AdviceVo> getAllMsg() {

        // 创建分页对象
        Page<SysAdvice> page = new Page<>(1, 20);

        LambdaQueryWrapper<SysAdvice> lqw = new LambdaQueryWrapper<SysAdvice>()
                .and(wrapper -> wrapper
                        .eq(SysAdvice::getReceiverId, SecurityUtils.getUserId())
                        .or()
                        .isNull(SysAdvice::getReceiverId)
                )
                .orderByDesc(SysAdvice::getCreateTime);

        Page<SysAdvice> sysAdvicePage = baseMapper.selectPage(page, lqw);


        List<SysAdvice> sysAdvices = sysAdvicePage.getRecords();

        return BeanUtil.copyToList(sysAdvices, AdviceVo.class);
    }

    @Override
    public List<CommentAdviceVo> getCommentMsg(Integer productType) {

        this.postConstruct();

        List<SysAdvice> sysAdviceList = baseMapper.selectList(new LambdaQueryWrapper<SysAdvice>()
                .eq(SysAdvice::getType, AdviceEnum.COMMENT_REMIND)
                .eq(SysAdvice::getReceiverId, SecurityUtils.getUserId())
                .eq(productType != 3, SysAdvice::getProductType, productType)
                .orderByDesc(SysAdvice::getCreateTime));


        List<Long> commentUserIdList = new ArrayList<>();
        for (SysAdvice sysAdvice : sysAdviceList) {
            commentUserIdList.add(sysAdvice.getSenderId());
        }
        List<SysUser> sysUsers = sysUserService.listByIds(commentUserIdList);

        Map<Long, SysUser> commentUserMap = new HashMap<>();
        for (SysUser sysUser : sysUsers) {
            commentUserMap.put(sysUser.getUserId(), sysUser);
        }

        List<CommentAdviceVo> commentAdviceVoList = new ArrayList<>();
        for (SysAdvice sysAdvice : sysAdviceList) {
            CommentAdviceVo commentAdviceVo = BeanUtil.copyProperties(sysAdvice, CommentAdviceVo.class);

            Long senderId = sysAdvice.getSenderId();
            SysUser senderUser = commentUserMap.get(senderId);
            if (Objects.nonNull(senderUser)) {
                commentAdviceVo.setUserAvatar(senderUser.getAvatar());
            }
            if (sysAdvice.getProductType() == 0) {
                ModelProduct modelProduct = modelProductMap.get(sysAdvice.getProductId());
                if (Objects.nonNull(modelProduct)) {
                    commentAdviceVo.setProductImag(modelProduct.getSurfaceUrl());
                }
            } else if (sysAdvice.getProductType() == 1) {
                WorkFlow workFlow = workFlowMap.get(sysAdvice.getProductId());
                if (Objects.nonNull(workFlow)) {
                    commentAdviceVo.setProductImag(workFlow.getCoverPath());
                }
            } else if (sysAdvice.getProductType() == 2) {
                ModelImage modelImage = modelImageMap.get(sysAdvice.getProductId());
                if (Objects.nonNull(modelImage)) {
                    commentAdviceVo.setProductImag(modelImage.getImagePaths().split(",")[0]);
                }
            }

            commentAdviceVoList.add(commentAdviceVo);
        }

        return commentAdviceVoList;
    }

    @Override
    public List<LikeAdviceVo> getLikeMsg(Integer productType) {
        this.postConstruct();
        List<SysAdvice> sysAdviceList;
        if (productType == 3) {
            sysAdviceList = baseMapper.selectList(new LambdaQueryWrapper<SysAdvice>()
                    .eq(SysAdvice::getType, AdviceEnum.LIKE_REMIND)
                    .eq(SysAdvice::getReceiverId, SecurityUtils.getUserId())
                    .isNotNull(SysAdvice::getCommentId)
                    .orderByDesc(SysAdvice::getCreateTime));
        } else {
            sysAdviceList = baseMapper.selectList(new LambdaQueryWrapper<SysAdvice>()
                    .eq(SysAdvice::getType, AdviceEnum.LIKE_REMIND)
                    .eq(SysAdvice::getReceiverId, SecurityUtils.getUserId())
                    .eq(productType != 4, SysAdvice::getProductType, productType)
                    .orderByDesc(SysAdvice::getCreateTime));
        }

        List<Long> likeUserIdList = new ArrayList<>();
        for (SysAdvice sysAdvice : sysAdviceList) {
            likeUserIdList.add(sysAdvice.getSenderId());
        }
        List<SysUser> sysUsers = sysUserService.listByIds(likeUserIdList);

        Map<Long, SysUser> likeUserMap = new HashMap<>();
        for (SysUser sysUser : sysUsers) {
            likeUserMap.put(sysUser.getUserId(), sysUser);
        }


        List<LikeAdviceVo> likeAdviceVoList = new ArrayList<>();
        for (SysAdvice sysAdvice : sysAdviceList) {
            LikeAdviceVo likeAdviceVo = BeanUtil.copyProperties(sysAdvice, LikeAdviceVo.class);

            Long senderId = sysAdvice.getSenderId();
            SysUser senderUser = likeUserMap.get(senderId);
            if (Objects.nonNull(senderUser)) {
                likeAdviceVo.setUserAvatar(senderUser.getAvatar());
            }
            if (sysAdvice.getProductType() == 0) {
                ModelProduct modelProduct = modelProductMap.get(sysAdvice.getProductId());
                if (Objects.nonNull(modelProduct)) {
                    likeAdviceVo.setProductImag(modelProduct.getSurfaceUrl());
                }
            } else if (sysAdvice.getProductType() == 1) {
                WorkFlow workFlow = workFlowMap.get(sysAdvice.getProductId());
                if (Objects.nonNull(workFlow)) {
                    likeAdviceVo.setProductImag(workFlow.getCoverPath());
                }
            } else if (sysAdvice.getProductType() == 2) {
                ModelImage modelImage = modelImageMap.get(sysAdvice.getProductId());
                if (Objects.nonNull(modelImage)) {
                    likeAdviceVo.setProductImag(modelImage.getImagePaths().split(",")[0]);
                }
            }

            likeAdviceVoList.add(likeAdviceVo);
        }

        return likeAdviceVoList;
    }

    @Override
    public List<AttentionAdviceVo> getAttentionMsg() {
        List<SysAdvice> sysAdviceList = baseMapper.selectList(new LambdaQueryWrapper<SysAdvice>()
                .eq(SysAdvice::getType, AdviceEnum.FANS_REMIND)
                .eq(SysAdvice::getReceiverId, SecurityUtils.getUserId())
                .orderByDesc(SysAdvice::getCreateTime));

        List<AttentionAdviceVo> attentionAdviceVoList = new ArrayList<>();
        List<Long> atentUserIdList = new ArrayList<>();

        // 通知表中获取所有关注我的用户id
        for (SysAdvice sysAdvice : sysAdviceList) {
            atentUserIdList.add(sysAdvice.getSenderId());
        }

        // 构建map, key为用户id，value为用户信息
        Map<Long, SysUser> attentionUserMap = new HashMap<>();

        // 批量查询用户信息, 并构建映射关系
        List<SysUser> atentUserList = sysUserService.listByIds(atentUserIdList);
        for (SysUser sysUser : atentUserList) {
            attentionUserMap.put(sysUser.getUserId(), sysUser);
        }

        for (SysAdvice sysAdvice : sysAdviceList) {
            AttentionAdviceVo attentionAdviceVo = BeanUtil.copyProperties(sysAdvice, AttentionAdviceVo.class);
            Long senderId = sysAdvice.getSenderId();
            SysUser attentionUser = attentionUserMap.get(senderId);
            if (Objects.nonNull(attentionUser)) {
                attentionAdviceVo.setUserAvatar(attentionUser.getAvatar());
            }
            attentionAdviceVoList.add(attentionAdviceVo);
        }

        return attentionAdviceVoList;
    }

    @Override
    public void read(Long adviceId) {
        SysAdvice sysAdvice = baseMapper.selectById(adviceId);

        if (Objects.isNull(sysAdvice)) {
            return;
        }

        Long receiverId = sysAdvice.getReceiverId();
        if (!Objects.equals(SecurityUtils.getUserId(), receiverId)) {
            return;
        }

        sysAdvice.setIsRead(1);
        baseMapper.updateById(sysAdvice);

    }

    @Override
    public void readAll() {
        List<SysAdvice> sysAdviceList = baseMapper.selectList(new LambdaQueryWrapper<SysAdvice>()
                .eq(SysAdvice::getIsRead, 0)
                .eq(SysAdvice::getReceiverId, SecurityUtils.getUserId()));
        for (SysAdvice sysAdvice : sysAdviceList) {
            sysAdvice.setIsRead(1);
            baseMapper.updateById(sysAdvice);
        }
    }

    @Override
    public List<AdviceVo> getOfficialMsg() {

        List<SysAdvice> sysAdviceList = baseMapper.selectList(new LambdaQueryWrapper<SysAdvice>()
                .eq(SysAdvice::getType, AdviceEnum.SYSTEM_NOTICE)
                .eq(SysAdvice::getReceiverId, SecurityUtils.getUserId()));



        return BeanUtil.copyToList(sysAdviceList, AdviceVo.class);
    }

    @Override
    public void sendSysMsg(SysAdviceDto sysAdviceDto) {

        rabbitTemplate.convertAndSend(QueueConstants.SYS_MSG_QUEUE, sysAdviceDto);

    }

    public void postConstruct() {
        Long userId = SecurityUtils.getUserId();

        // 并行加载数据
        CompletableFuture<List<ModelProduct>> productsFuture = CompletableFuture.supplyAsync(() ->
                modelService.lambdaQuery().eq(ModelProduct::getUserId, userId).list()
        );

        CompletableFuture<List<WorkFlow>> workflowsFuture = CompletableFuture.supplyAsync(() ->
                workFlowService.lambdaQuery().eq(WorkFlow::getUserId, userId).list()
        );

        CompletableFuture<List<ModelImage>> imagesFuture = CompletableFuture.supplyAsync(() ->
                modelImageService.lambdaQuery().eq(ModelImage::getUserId, userId).list()
        );

        // 等待所有任务完成
        CompletableFuture.allOf(productsFuture, workflowsFuture, imagesFuture).join();

        // 更新缓存
        modelProductMap.clear();
        productsFuture.join().forEach(p -> modelProductMap.put(p.getId(), p));

        workFlowMap.clear();
        workflowsFuture.join().forEach(w -> workFlowMap.put(w.getId(), w));

        modelImageMap.clear();
        imagesFuture.join().forEach(i -> modelImageMap.put(i.getId(), i));

    }


}
