package com.skr.mdm.task;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.skr.mdm.constant.UserOnlineConstants;
import com.skr.mdm.dao.DeviceEquipmentDao;
import com.skr.mdm.dao.LogUserOnlineDao;
import com.skr.mdm.entity.DeviceEquipmentDO;
import com.skr.mdm.entity.LogUserOnlineDO;
import com.skr.mdm.enums.DeleteStateEnum;
import com.skr.mdm.enums.EquipmentStateEnum;
import com.skr.mdm.util.RedisGetKeyUtil;
import com.skr.mdm.util.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

/**
 * 检测用户离线后未上线导致的离线状态和离线日志未记录的问题
 *
 * @author nfq
 * @date 2020/9/14 11:07
 */
@Component
@EnableScheduling
@EnableAsync
@Slf4j
public class UserOfflineTask {

    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private DeviceEquipmentDao equipmentDao;
    @Autowired
    private LogUserOnlineDao logUserOnlineDao;

    @Scheduled(fixedRate = UserOnlineConstants.HEARTBEAT_CHECK_MS)
    public void run() {
        TimeInterval timer = DateUtil.timer();
        List<DeviceEquipmentDO> equipmentDOList = new LambdaQueryChainWrapper<>(equipmentDao)
                .eq(DeviceEquipmentDO::getIsDelete, DeleteStateEnum.NON_DELETE.getState())
                .eq(DeviceEquipmentDO::getEquipmentState, EquipmentStateEnum.WS_ONLINE.getState())
                .list();
        if (CollectionUtils.isEmpty(equipmentDOList)) {
            return;
        }
        equipmentDOList.forEach(equipmentDO -> {
            if (redisUtils.get(RedisGetKeyUtil.getUserReadyOfflineKey(equipmentDO.getId())) != null) {
                long readOfflineTime = Long.parseLong(redisUtils.get(RedisGetKeyUtil.getUserReadyOfflineKey(equipmentDO.getId())).toString());
                if (System.currentTimeMillis() - readOfflineTime > UserOnlineConstants.OFFLINE_MS) {
                    // 添加离线日志
                    LogUserOnlineDO logUserOnlineDO = LogUserOnlineDO.builder()
                            .equipmentId(equipmentDO.getId())
                            .equipmentName(equipmentDO.getEquipmentName())
                            .userName(equipmentDO.getUserName())
                            .departmentName(equipmentDO.getDepartmentName())
                            .logType(2)
                            .content("离线（websocket）")
                            .departmentId(equipmentDO.getDepartmentId())
                            .companyId(equipmentDO.getCompanyId())
                            .operateTime(new Date())
                            .build();
                    logUserOnlineDao.insert(logUserOnlineDO);
                    // 更新用户离线状态
                    new LambdaUpdateChainWrapper<>(equipmentDao)
                            .set(DeviceEquipmentDO::getEquipmentState, EquipmentStateEnum.OFFLINE.getState())
                            .set(DeviceEquipmentDO::getOfflineTime, new Date())
                            .eq(DeviceEquipmentDO::getId, equipmentDO.getId())
                            .update();
                    redisUtils.del(RedisGetKeyUtil.getUserReadyOfflineKey(equipmentDO.getId()));
                    log.info("websocket离线定时检测 用户：{} 设备：{}离线", equipmentDO.getUserName(), equipmentDO.getEquipmentName());
                }
            }
        });
        log.info("websocket离线定时检测结束 耗时：{}秒", timer.intervalSecond());
    }
}
