package com.skr.mdm.netty;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.skr.mdm.config.MdmWebsocketChannelFactory;
import com.skr.mdm.constant.UserOnlineConstants;
import com.skr.mdm.dao.DeviceEquipmentDao;
import com.skr.mdm.dao.LogUserOnlineDao;
import com.skr.mdm.dto.LoginUserDTO;
import com.skr.mdm.entity.DeviceEquipmentDO;
import com.skr.mdm.entity.LogUserOnlineDO;
import com.skr.mdm.enums.EquipmentStateEnum;
import com.skr.mdm.util.RedisGetKeyUtil;
import com.skr.mdm.util.RedisUtils;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * @author nfq
 * @date 2020/7/27 17:30
 */
@Component
@Slf4j
public class AfterUserConnectionHandler {

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

    /**
     * 用户上线
     *
     * @param context
     * @param loginUserDTO
     */
    public void userOnline(ChannelHandlerContext context, LoginUserDTO loginUserDTO) {
        // 判断当前设备未更新的channel是否离线，如果未离线，不添加上线日志，如果离线，添加上线日志
//        boolean isOffline = redisUtils.get(RedisGetKeyUtil.getUserOnlineKey(loginUserDTO.getId())) != null && EquipmentStateEnum.OFFLINE.getState().equals(redisUtils.get(RedisGetKeyUtil.getUserOnlineKey(loginUserDTO.getId())));
//        if (redisUtils.get(RedisGetKeyUtil.getUserOnlineKey(loginUserDTO.getId())) == null || isOffline) {
//            // 标识为上线
//            redisUtils.set(RedisGetKeyUtil.getUserOnlineKey(loginUserDTO.getId()), EquipmentStateEnum.WS_ONLINE.getState(), UserOnlineConstants.CHANNEL_OFFLINE_SECONDS);
//            // 添加上线日志
//            LogUserOnlineDO logUserOnlineDO = LogUserOnlineDO.builder()
//                    .equipmentId(loginUserDTO.getId())
//                    .equipmentName(loginUserDTO.getEquipmentName())
//                    .userName(loginUserDTO.getUserName())
//                    .departmentName(loginUserDTO.getDepartmentName())
//                    .logType(1)
//                    .content("上线")
//                    .departmentId(loginUserDTO.getDepartmentId())
//                    .companyId(loginUserDTO.getCompanyId())
//                    .operateTime(new Date())
//                    .build();
//            logUserOnlineDao.insert(logUserOnlineDO);
//        }

        // 判断是否为离线状态 添加上线日志
        Integer equipmentState = equipmentDao.getEquipmentStateById(loginUserDTO.getId());
        if (EquipmentStateEnum.INACTIVATED.getState().equals(equipmentState) || EquipmentStateEnum.OFFLINE.getState().equals(equipmentState)) {
            LogUserOnlineDO logUserOnlineDO = LogUserOnlineDO.builder()
                    .equipmentId(loginUserDTO.getId())
                    .equipmentName(loginUserDTO.getEquipmentName())
                    .userName(loginUserDTO.getUserName())
                    .departmentName(loginUserDTO.getDepartmentName())
                    .logType(1)
                    .content("上线(websocket)")
                    .departmentId(loginUserDTO.getDepartmentId())
                    .companyId(loginUserDTO.getCompanyId())
                    .operateTime(new Date())
                    .build();
            logUserOnlineDao.insert(logUserOnlineDO);
        }

        new LambdaUpdateChainWrapper<>(equipmentDao)
                .set(DeviceEquipmentDO::getEquipmentState, EquipmentStateEnum.WS_ONLINE.getState())
                .set(DeviceEquipmentDO::getWsChannelId, context.channel().id().asShortText())
                .eq(DeviceEquipmentDO::getId, loginUserDTO.getId())
                .update();
        // 添加channel
        MdmWebsocketChannelFactory.addChannel(context, loginUserDTO.getId());
        // 删除离线缓存
        if (redisUtils.get(RedisGetKeyUtil.getUserReadyOfflineKey(loginUserDTO.getId())) != null) {
            redisUtils.del(RedisGetKeyUtil.getUserReadyOfflineKey(loginUserDTO.getId()));
        }
    }

    /**
     * 用户离线
     */
    public void userOffline(ChannelHandlerContext context) {
        // 移除channel
        MdmWebsocketChannelFactory.removeChannel(context);
        String channelId = context.channel().id().asShortText();
        // 添加离线日志
        DeviceEquipmentDO equipmentDO = new LambdaQueryChainWrapper<>(equipmentDao)
                .eq(DeviceEquipmentDO::getWsChannelId, channelId)
                .one();
        if (equipmentDO == null) {
            return;
        }
        log.info("channelId:{} websocket实时离线 用户名：{} 设备ID：{}", channelId, equipmentDO.getUserName(), equipmentDO.getId());
        redisUtils.set(RedisGetKeyUtil.getUserReadyOfflineKey(equipmentDO.getId()), System.currentTimeMillis(), UserOnlineConstants.READY_OFFLINE_SECONDS);
        // 设备是在线状态，添加离线日志 保障上线离线日志一致性
//        if (redisUtils.get(RedisGetKeyUtil.getUserOnlineKey(equipmentDO.getId())) != null && EquipmentStateEnum.WS_ONLINE.getState().equals(redisUtils.get(RedisGetKeyUtil.getUserOnlineKey(equipmentDO.getId())))) {
//            // 标识为离线
//            redisUtils.set(RedisGetKeyUtil.getUserOnlineKey(equipmentDO.getId()), EquipmentStateEnum.OFFLINE.getState(), UserOnlineConstants.CHANNEL_OFFLINE_SECONDS);
//            // 更新离线时间
//            new LambdaUpdateChainWrapper<>(equipmentDao)
//                    .set(DeviceEquipmentDO::getOfflineTime, new Date())
//                    .eq(DeviceEquipmentDO::getId, equipmentDO.getId())
//                    .update();
//            // 添加离线日志
//            LogUserOnlineDO logUserOnlineDO = LogUserOnlineDO.builder()
//                    .equipmentId(equipmentDO.getId())
//                    .equipmentName(equipmentDO.getEquipmentName())
//                    .userName(equipmentDO.getUserName())
//                    .departmentName(equipmentDO.getDepartmentName())
//                    .logType(2)
//                    .content("离线")
//                    .departmentId(equipmentDO.getDepartmentId())
//                    .companyId(equipmentDO.getCompanyId())
//                    .operateTime(new Date())
//                    .build();
//            logUserOnlineDao.insert(logUserOnlineDO);
//        }
    }

}
