package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.ShiroConstants;
import com.ruoyi.common.core.page.MpPageUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.DozerUtils;
import com.ruoyi.platform.mapper.saas.SaaSUserOnlineMapper;
import com.ruoyi.system.domain.SysUserOnline;
import com.ruoyi.system.domain.dto.SysUserOnlineDTO;
import com.ruoyi.system.domain.vo.SysUserOnlineVO;
import com.ruoyi.system.mapper.SysUserOnlineMapper;
import com.ruoyi.system.service.ISysUserOnlineService;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;

/**
 *@Description 在线用户 服务层处理
 *@Author zhushuyong
 *@Date 2021/6/21 22:51
 *@since:
 *@copyright: 版权所有2021 开源组织 gitee(https://gitee.com/jinzheyi)作者：朱述勇<br/>
 *            GitHub(https://github.com/jinzheyi)作者：朱述勇 。
 */
@Service
public class SysUserOnlineServiceImpl extends ServiceImpl<SysUserOnlineMapper, SysUserOnline>
        implements ISysUserOnlineService {
    
    @Autowired
    private EhCacheManager ehCacheManager;

    @Autowired
    private SaaSUserOnlineMapper saaSUserOnlineMapper;

    /**
     * 通过会话序号查询信息
     * 
     * @param sessionId 会话ID
     * @return 在线用户信息
     */
    @Override
    public SysUserOnlineVO selectOnlineById(String sessionId)
    {
        SysUserOnline sysUserOnline = saaSUserOnlineMapper.selectById(sessionId);
        if (Objects.isNull(sysUserOnline)){
            return null;
        }
        return DozerUtils.copyProperties(sysUserOnline, SysUserOnlineVO.class);
    }

    /**
     * 通过会话序号删除信息
     * 
     * @param sessionId 会话ID
     * @return 在线用户信息
     */
    @Override
    public void deleteOnlineById(String sessionId)
    {
        SysUserOnlineVO userOnline = selectOnlineById(sessionId);
        if (StringUtils.isNotNull(userOnline))
        {
            saaSUserOnlineMapper.deleteById(sessionId);
        }
    }

    /**
     * 通过会话序号删除信息
     * 
     * @param sessions 会话ID集合
     * @return 在线用户信息
     */
    @Override
    public void batchDeleteOnline(List<String> sessions)
    {
        for (String sessionId : sessions)
        {
            SysUserOnlineVO userOnline = selectOnlineById(sessionId);
            if (StringUtils.isNotNull(userOnline))
            {
                saaSUserOnlineMapper.deleteById(sessionId);
            }
        }
    }

    /**
     * 保存会话信息
     * 
     * @param online 会话信息
     */
    @Override
    public void saveOnline(SysUserOnlineDTO online)
    {
        if (Objects.isNull(saaSUserOnlineMapper.selectById(online.getId()))) {
            saaSUserOnlineMapper.insert(DozerUtils.copyProperties(online, SysUserOnline.class));
            return;
        }
        saaSUserOnlineMapper.updateById(DozerUtils.copyProperties(online, SysUserOnline.class));
    }

    /**
     * 查询会话集合
     * 
     * @param userOnline 在线用户
     */
    @Override
    public TableDataInfo<SysUserOnlineVO> selectUserOnlinePage(SysUserOnlineDTO userOnline)
    {
        return MpPageUtils.copyPage(this.page(MpPageUtils.intPage(), getWrapper(userOnline)), SysUserOnlineVO.class);
    }

    private LambdaQueryWrapper<SysUserOnline> getWrapper(SysUserOnlineDTO userOnline) {
        return new LambdaQueryWrapper<SysUserOnline>()
                .like(StringUtils.isNotBlank(userOnline.getIpaddr()), SysUserOnline::getIpaddr, userOnline.getIpaddr())
                .like(StringUtils.isNotBlank(userOnline.getLoginName()), SysUserOnline::getLoginName, userOnline.getLoginName());
    }

    /**
     * 强退用户
     * 
     * @param sessionId 会话ID
     */
    @Override
    public void forceLogout(String sessionId)
    {
        saaSUserOnlineMapper.deleteById(sessionId);
    }

    /**
     * 清理用户缓存
     * 
     * @param loginName 登录名称
     * @param sessionId 会话ID
     */
    @Override
    public void removeUserCache(String loginName, String sessionId)
    {
        Cache<String, Deque<Serializable>> cache = ehCacheManager.getCache(ShiroConstants.SYS_USERCACHE);
        Deque<Serializable> deque = cache.get(loginName);
        if (StringUtils.isEmpty(deque) || deque.size() == 0)
        {
            return;
        }
        deque.remove(sessionId);
    }

    /**
     * 查询会话集合
     * 
     * @param expiredDate 失效日期
     */
    @Override
    public List<SysUserOnlineVO> selectOnlineByExpired(Date expiredDate)
    {
        List<SysUserOnline> list = saaSUserOnlineMapper.selectList(new LambdaQueryWrapper<SysUserOnline>()
                .le(SysUserOnline::getLastAccessTime, DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, expiredDate))
                .orderByAsc(SysUserOnline::getLastAccessTime));
        if (!CollUtil.isEmpty(list)) {
            return BeanUtil.copyToList(list, SysUserOnlineVO.class);
        }
        return new ArrayList<>();
    }

}
