package com.ktg.system.service.impl;

import com.ktg.common.constant.Constants;
import com.ktg.common.core.domain.model.LoginUser;
import com.ktg.common.core.redis.RedisCache;
import com.ktg.common.utils.StringUtils;
import com.ktg.system.domain.SysUserOnline;
import com.ktg.system.service.ISysUserOnlineService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 在线用户 服务层处理
 *
 * @author guoruan
 */
@Service
public class SysUserOnlineServiceImpl implements ISysUserOnlineService
{

    @Autowired
    private RedisCache redisCache;
    // 获取单个账号在线最大数量
    @Value("${ktg-mes.onlineMax}")
    private Integer onlineMax;

    /**
     * 通过登录地址查询信息
     *
     * @param ipaddr 登录地址
     * @param user 用户信息
     * @return 在线用户信息
     */
    @Override
    public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user)
    {
        if (StringUtils.equals(ipaddr, user.getIpaddr()))
        {
            return loginUserToUserOnline(user);
        }
        return null;
    }

    /**
     * 通过用户名称查询信息
     *
     * @param userName 用户名称
     * @param user 用户信息
     * @return 在线用户信息
     */
    @Override
    public SysUserOnline selectOnlineByUserName(String userName, LoginUser user)
    {
        if (StringUtils.equals(userName, user.getUsername()))
        {
            return loginUserToUserOnline(user);
        }
        return null;
    }

    /**
     * 通过登录地址/用户名称查询信息
     *
     * @param ipaddr 登录地址
     * @param userName 用户名称
     * @param user 用户信息
     * @return 在线用户信息
     */
    @Override
    public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user)
    {
        if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername()))
        {
            return loginUserToUserOnline(user);
        }
        return null;
    }

    /**
     * 设置在线用户信息
     *
     * @param user 用户信息
     * @return 在线用户
     */
    @Override
    public SysUserOnline loginUserToUserOnline(LoginUser user)
    {
        if (StringUtils.isNull(user) || StringUtils.isNull(user.getUser()))
        {
            return null;
        }
        SysUserOnline sysUserOnline = new SysUserOnline();
        sysUserOnline.setTokenId(user.getToken());
        sysUserOnline.setUserName(user.getUsername());
        sysUserOnline.setIpaddr(user.getIpaddr());
        sysUserOnline.setLoginLocation(user.getLoginLocation());
        sysUserOnline.setBrowser(user.getBrowser());
        sysUserOnline.setOs(user.getOs());
        sysUserOnline.setLoginTime(user.getLoginTime());
        if (StringUtils.isNotNull(user.getUser().getDept()))
        {
            sysUserOnline.setDeptName(user.getUser().getDept().getDeptName());
        }
        return sysUserOnline;
    }

    @Override
    public List<SysUserOnline> getOnlineList(String ipaddr, String userName) {
        Collection<String> keys = redisCache.keys(Constants.LOGIN_TOKEN_KEY + "*");
        List<SysUserOnline> userOnlineList = new ArrayList<>();
        for (String key : keys)
        {
            LoginUser user = redisCache.getCacheObject(key);
            if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
            {
                if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername()))
                {
                    userOnlineList.add(selectOnlineByInfo(ipaddr, userName, user));
                }
            }
            else if (StringUtils.isNotEmpty(ipaddr))
            {
                if (StringUtils.equals(ipaddr, user.getIpaddr()))
                {
                    userOnlineList.add(selectOnlineByIpaddr(ipaddr, user));
                }
            }
            else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser()))
            {
                if (StringUtils.equals(userName, user.getUsername()))
                {
                    userOnlineList.add(selectOnlineByUserName(userName, user));
                }
            }
            else
            {
                userOnlineList.add(loginUserToUserOnline(user));
            }
        }
        Collections.reverse(userOnlineList);
        userOnlineList.removeAll(Collections.singleton(null));
        // 进行登陆时间排序，越早登录越在前，不用判断空指针，因为至少当前用户在线
        userOnlineList = userOnlineList.stream().sorted(Comparator.comparingLong(SysUserOnline::getLoginTime)).collect(Collectors.toList());
        return userOnlineList;
    }

    @Override
    public Boolean forceLogout(String tokenId) {
        return redisCache.deleteObject(Constants.LOGIN_TOKEN_KEY + tokenId);
    }

    @Override
    public Boolean forceLogoutByName(String userName) {
        // 获取当前登陆的数据,返回的数据已经根据时间排序好了
        List<SysUserOnline> onlineList = getOnlineList(null, userName);
        // 判断当前的账号是否超过限制，超过了，就把最近没活跃的账号清理掉
        if (onlineMax != null && onlineMax != 0 && onlineList.size() > onlineMax) {
            // 找到对应的开始强制下线删除
            int forceNum = onlineList.size() - onlineMax;
            for (int i = 0; i < forceNum; i++) {
                forceLogout(onlineList.get(i).getTokenId());
            }
        }
        return true;
    }


}
