package com.ruoyi.system.service.impl;

import cn.hutool.core.date.DateException;
import cn.hutool.core.thread.ThreadUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.ruoyi.common.constant.MqttConstants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.MqttUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysNotice;
import com.ruoyi.system.domain.SysNoticeUser;
import com.ruoyi.system.domain.vo.NoticeSendUserVo;
import com.ruoyi.system.domain.vo.SysNoticeVo;
import com.ruoyi.system.mapper.SysNoticeMapper;
import com.ruoyi.system.mapper.SysNoticeUserMapper;
import com.ruoyi.system.service.ISysNoticeService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 公告 服务层实现
 *
 * @author ruoyi
 */
@Service
public class SysNoticeServiceImpl extends MPJBaseServiceImpl<SysNoticeMapper, SysNotice> implements ISysNoticeService {

    @Resource
    private SysNoticeUserMapper noticeUserMapper;

    @Resource
    private ISysUserService userService;

    /**
     * 查询公告信息
     *
     * @param noticeId 公告ID
     * @return 公告信息
     */
    @Override
    public SysNotice selectNoticeById(Long noticeId) {
        return getById(noticeId);
    }

    /**
     * 查询公告列表
     *
     * @param notice 公告信息
     * @return 公告集合
     */
    @Override
    public List<SysNotice> selectNoticeList(SysNotice notice) {
        LambdaQueryWrapper<SysNotice> selectNoticeList = new LambdaQueryWrapper<SysNotice>()
                .like(StringUtils.isNotBlank(notice.getNoticeTitle()), SysNotice::getNoticeTitle, notice.getNoticeTitle())
                .eq(StringUtils.isNotBlank(notice.getNoticeType()), SysNotice::getNoticeType, notice.getNoticeType())
                .eq(StringUtils.isNotBlank(notice.getIsSend()),SysNotice::getIsSend,notice.getIsSend())
                .like(StringUtils.isNotBlank(notice.getCreateBy()), SysNotice::getCreateBy, notice.getCreateBy());
        return list(selectNoticeList);
    }

    /**
     * 新增公告
     *
     * @param notice 公告信息
     * @return 结果
     */
    @Override
    public boolean insertNotice(SysNotice notice) {
        return save(notice);
    }

    /**
     * 修改公告
     *
     * @param notice 公告信息
     * @return 结果
     */
    @Override
    public boolean updateNotice(SysNotice notice) {
        return updateById(notice);
    }

    /**
     * 删除公告对象
     *
     * @param noticeId 公告ID
     * @return 结果
     */
    @Override
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public boolean deleteNoticeById(Long noticeId) {

        boolean b = removeById(noticeId);
        if (b){
            noticeUserMapper.delete(new LambdaQueryWrapper<SysNoticeUser>().eq(SysNoticeUser::getNoticeId,noticeId));
        }
        return b;
    }

    /**
     * 批量删除公告信息
     *
     * @param noticeIds 需要删除的公告ID
     * @return 结果
     */
    @Override
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public boolean deleteNoticeByIds(Long[] noticeIds) {
        boolean b = removeBatchByIds(Arrays.asList(noticeIds));
        if (b){
            noticeUserMapper.delete(new LambdaQueryWrapper<SysNoticeUser>().in(SysNoticeUser::getNoticeId,Arrays.asList(noticeIds)));
        }
        return b;
    }

    /**
     * 下发消息
     *
     * @param noticeSendUserVo
     * @return
     */
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public boolean sendMessageToUser(NoticeSendUserVo noticeSendUserVo) {
        String send = "1";
        SysNotice byId = getById(noticeSendUserVo.getNoticeId());
        if (null == byId || send.equals(byId.getIsSend())) {
            throw new DateException("已经下发消息不能再次下发");
        }else if(send.equals(byId.getIsSend())){
            throw new DateException("该消息已经关闭，不能进行下发");
        }

        List<Long> userIds = null;
        if (noticeSendUserVo.getType() == 0L) {
            List<SysUser> sysUsers = userService.selectUserList(new SysUser(), null);
            userIds = sysUsers.stream().map(SysUser::getUserId).collect(Collectors.toList());
        } else if (noticeSendUserVo.getType() == 1L) {
            SysUser user = new SysUser();
            user.setDeptId(noticeSendUserVo.getDeptId());
            List<SysUser> sysUsers = userService.selectUserList(user, null);
            userIds = sysUsers.stream().map(SysUser::getUserId).collect(Collectors.toList());
        } else if (noticeSendUserVo.getType() == 2L) {
            userIds = noticeSendUserVo.getUserIds();
        } else {
            throw new DateException("下发错误");
        }
        userIds.forEach(item -> noticeUserMapper.insert(new SysNoticeUser()
                .setNoticeId(noticeSendUserVo.getNoticeId())
                .setUserId(item)
                .setIsRead("0")));
        sendMessage(userIds);
        //修改下发状态
        updateById(new SysNotice().setNoticeId(noticeSendUserVo.getNoticeId()).setIsSend("1"));

        return true;
    }

    /**
     * 根据用户查询消息
     * @param userId
     * @return
     */
    public List<SysNoticeVo> selectNoticeByUserId(Long userId){
        MPJLambdaWrapper<SysNoticeUser> messageByUserId = new MPJLambdaWrapper<SysNoticeUser>("nu")
                .selectAll(SysNoticeUser.class)
                .selectAs(SysNotice::getNoticeTitle,SysNoticeVo::getNoticeTitle)
                .selectAs(SysNotice::getNoticeContent,SysNoticeVo::getNoticeContent)
                .selectAs(SysNotice::getNoticeType,SysNoticeVo::getNoticeType)
                .leftJoin(SysNotice.class,"n",SysNotice::getNoticeId,SysNoticeUser::getNoticeId)
                .eq(SysNotice::getStatus,"0")
                .eq(SysNoticeUser::getUserId,userId);
        List<SysNoticeVo> sysNoticeVos = noticeUserMapper.selectJoinList(SysNoticeVo.class, messageByUserId);
        return sysNoticeVos;

    }
    /**
     * 根据用户id 消息id 修改已读状态
     * @param userId
     * @param noticeId
     * @return
     */
    public boolean editNoticeByUserId(Long userId,Long noticeId){
        String isRead = "1";
        LambdaQueryWrapper<SysNoticeUser> noticeUserLambdaQueryWrapper = new LambdaQueryWrapper<SysNoticeUser>()
                .eq(SysNoticeUser::getUserId, userId)
                .eq(SysNoticeUser::getNoticeId, noticeId)
                .last("limit 1");
        SysNoticeUser sysNoticeUser = noticeUserMapper.selectOne(noticeUserLambdaQueryWrapper);
        if (null == sysNoticeUser){
            throw new DateException("消息不存在");
        }
        if (!isRead.equals(sysNoticeUser.getIsRead())){
            LambdaUpdateWrapper<SysNoticeUser> editMsgWrapper = new LambdaUpdateWrapper<SysNoticeUser>()
                    .set(SysNoticeUser::getIsRead, "1")
                    .eq(SysNoticeUser::getUserId, userId)
                    .eq(SysNoticeUser::getNoticeId, noticeId);
            noticeUserMapper.update(null,editMsgWrapper);
        }
        return true;
    }
    /**
     * 单独线程执行 避免主线程堵塞
     */
    private void sendMessage(List<Long> userIds) {
        if (null != userIds && userIds.size() > 0) {
            //异步线程执行
            ThreadUtil.execAsync(() -> {
                //推送到前端 前端接收消息
                userIds.forEach(item ->
                        MqttUtil.publish(
                                MqttConstants.YU_MQTT_CLIENT_MESSAGE_ONLINE + item,
                                String.valueOf(System.currentTimeMillis()))
                );
            });
        }
    }

}
