package com.codvision.base.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.codvision.base.entity.SysNotice;
import com.codvision.base.entity.SysNoticeUserMapper;
import com.codvision.base.entity.dto.SysNoticeDTO;
import com.codvision.base.entity.vo.SysNoticeVO;
import com.codvision.base.enums.DelFlag;
import com.codvision.base.enums.NoticeReadStatusEnum;
import com.codvision.base.enums.NoticeScopeEnum;
import com.codvision.base.enums.NoticeStatusEnum;
import com.codvision.base.mapper.SysNoticeMapper;
import com.codvision.base.mapper.SysNoticeUserMapperMapper;
import com.codvision.base.service.ISysNoticeService;
import com.codvision.base.service.ISysNoticeUserMapperService;
import com.codvision.base.support.WebSocketServer;
import com.codvision.webapi.api.SysUserApi;
import com.codvision.webapi.bean.RemoteSysUser;
import com.codvision.webcore.bean.QueryPage;
import com.codvision.webcore.service.impl.BaseServiceImpl;
import com.codvision.webcore.util.PageUtil;
import com.google.common.base.Preconditions;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统通知 服务实现类
 * </p>
 *
 * @author lingee
 * @since 2023-12-01
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class SysNoticeServiceImpl extends BaseServiceImpl<SysNoticeMapper, SysNotice, SysNoticeVO> implements ISysNoticeService {

    @Resource
    private SysNoticeUserMapperMapper sysNoticeUserMapperMapper;

    @Resource
    private ISysNoticeUserMapperService sysNoticeUserMapperService;

    @Resource
    private SysUserApi sysUserApi;

    @Override
    public SysNoticeVO getDetail(Integer id) {
        SysNoticeVO vo = sysNoticeUserMapperMapper.getDetail(id);
        return vo;
    }

    @Override
    public IPage<SysNoticeVO> getPageResult(QueryPage<SysNotice> queryPage) {
        SysNotice queryBean = queryPage.getCondition();
        IPage<SysNotice> page = queryPage.getPage();
        List<SysNoticeVO> pageResult = this.getBaseMapper().getSysNoticeList(page, queryBean);
        return PageUtil.convertPage(page, pageResult);
    }

    @Override
    public List<SysNoticeVO> listAll(SysNotice queryBean) {
        QueryWrapper<SysNotice> wrapper = PageUtil.initWrapper(queryBean);
        List<SysNotice> list = this.list(wrapper);
        return BeanUtil.copyToList(list, SysNoticeVO.class);
    }

    @Override
    public void saveSysNotice(SysNoticeDTO sysNoticeDTO) {
        SysNotice sysNotice = new SysNotice();
        BeanUtils.copyProperties(sysNoticeDTO, sysNotice);
        //更新通知状态为：已经下发过
        sysNotice.setStatus(NoticeStatusEnum.SEND.getStatus());
        this.save(sysNotice);

        List<Integer> uidList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(sysNoticeDTO.getUidList())) {
            uidList.addAll(sysNoticeDTO.getUidList());
            for (Integer uid : sysNoticeDTO.getUidList()) {
                sysNoticeUserMapperMapper.addNoticeUserMapper(sysNotice.getId(), uid);
            }
        } else {
            if (sysNoticeDTO.getScope() == NoticeScopeEnum.ALL_VISIBLE.getScope()) {
                List<RemoteSysUser> sysUserList = sysUserApi.getAllUserList(null, null, null);
                if (CollectionUtil.isNotEmpty(sysUserList)) {
                    List<Integer> list = sysUserList.stream().map(RemoteSysUser::getId).collect(Collectors.toList());
                    uidList.addAll(list);

                    uidList.addAll(sysNoticeDTO.getUidList());
                    for (RemoteSysUser sysUser : sysUserList) {
                        sysNoticeUserMapperMapper.addNoticeUserMapper(sysNotice.getId(), sysUser.getId());
                    }
                }
            }
        }

        for (Integer uid : uidList) {
            try {
                WebSocketServer.sendInfo(String.valueOf(sysNoticeDTO.getType()), uid);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void deleteSysNotices(List<Integer> ids) {
        sysNoticeUserMapperMapper.delete(Wrappers.<SysNoticeUserMapper>lambdaQuery().in(SysNoticeUserMapper::getNoticeId, ids));
        this.removeByIds(ids);
    }

    @Override
    public void send(SysNoticeDTO sysNoticeDTO) {
        Integer noticeId = sysNoticeDTO.getId();
        SysNotice sysNotice = getById(noticeId);
        Preconditions.checkArgument(sysNotice != null, 30001);

        List<Integer> uidList = sysNoticeDTO.getUidList();
        if (CollectionUtil.isNotEmpty(uidList)) {
            sysNoticeUserMapperService.update(Wrappers.<SysNoticeUserMapper>lambdaUpdate()
                    .eq(SysNoticeUserMapper::getNoticeId, noticeId)
                    .in(SysNoticeUserMapper::getUserId, uidList)
                    .set(SysNoticeUserMapper::getStatus, NoticeReadStatusEnum.UNREAD.getStatus())
                    .set(SysNoticeUserMapper::getFlagDel, DelFlag.NO_DELETED.getFlag()));
            //更新通知状态为：已经下发过
            sysNotice.setStatus(NoticeStatusEnum.SEND.getStatus());
            this.updateById(sysNotice);

            for (Integer uid : uidList) {
                try {
                    WebSocketServer.sendInfo(String.valueOf(sysNotice.getType()), uid);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void revoke(SysNoticeDTO sysNoticeDTO) {
        List<Integer> uidList = sysNoticeDTO.getUidList();
        if (CollectionUtil.isNotEmpty(uidList)) {
            sysNoticeUserMapperService.update(Wrappers.<SysNoticeUserMapper>lambdaUpdate()
                    .eq(SysNoticeUserMapper::getNoticeId, sysNoticeDTO.getId())
                    .in(SysNoticeUserMapper::getUserId, uidList)
                    .set(SysNoticeUserMapper::getFlagDel, DelFlag.DELETED.getFlag()));
        }
    }

    @Override
    public IPage<SysNoticeVO> getListByUidAndType(IPage<SysNotice> page, Integer uid, Integer type) {
        List<SysNoticeVO> records = this.getBaseMapper().getListByUidAndType(page, uid, type);
        return PageUtil.convertPage(page, records);
    }

    @Override
    public Boolean flagUnReadNotice(Integer uid) {
        return this.getBaseMapper().flagUnReadNotice(uid);
    }

}
