package com.mortals.xhx.daemon.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.json.JsonGeneratorImpl;
import com.mortals.framework.ap.GlobalSysInfo;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.service.ICacheService;
import com.mortals.framework.service.ITask;
import com.mortals.framework.service.ITaskExcuteService;
import com.mortals.framework.util.DateUtils;
import com.mortals.xhx.base.framework.ws.message.SendToAllRequest;
import com.mortals.xhx.base.framework.ws.message.UserJoinNoticeRequest;
import com.mortals.xhx.base.framework.ws.util.WebSocketUtil;
import com.mortals.xhx.common.code.AlarmLevelEnum;
import com.mortals.xhx.common.code.AlarmTypeEnum;
import com.mortals.xhx.common.code.DeviceOnlineStatusEnum;
import com.mortals.xhx.common.code.DeviceSourceEnum;
import com.mortals.xhx.common.key.ParamKey;
import com.mortals.xhx.common.utils.SendTask;
import com.mortals.xhx.common.utils.SendTaskThreadPool;
import com.mortals.xhx.module.device.model.*;
import com.mortals.xhx.module.device.service.DeviceAlarmService;
import com.mortals.xhx.module.device.service.DeviceLogService;
import com.mortals.xhx.module.device.service.DeviceService;
import lombok.extern.apachecommons.CommonsLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.mortals.xhx.common.key.RedisKey.KEY_DEVICE_TYPE_CACHE;

/**
 * 设备状态任务
 *
 * @author: zxfei
 * @date: 2022/3/9 15:19
 */
@Slf4j
@Service("DeviceStatTask")
public class DeviceStatTaskImpl implements ITaskExcuteService {

    @Autowired
    private DeviceService deviceService;
    @Autowired
    private DeviceLogService deviceLogService;

    @Autowired
    private SendTaskThreadPool sendTaskThreadPool;
    @Autowired
    private DeviceAlarmService deviceAlarmService;
    @Autowired
    private ICacheService cacheService;


    @Override
    public void excuteTask(ITask task) throws AppException {
        log.debug("设备状态统计，开始执行");
        doDeviceUpOrDown();
        doDeviceLogDel();
        doDeviceQuery();
        log.debug("设备状态统计，结束执行");
    }

    /**
     * 统计更新设备状态
     */
    private void doDeviceUpOrDown() {
        int timeout = GlobalSysInfo.getParamIntValue(ParamKey.SYS_PARAM_HEADBEAT_TIMEOUT, 180) * 1000;

        try {
            //获取所有设备，针对每个设备查询最近指定秒的日志，如果没有则更新下线
            List<DeviceEntity> collect = deviceService.find(new DeviceQuery().deviceSource(DeviceSourceEnum.大厅.getValue()).deviceOnlineStatus(DeviceOnlineStatusEnum.在线.getValue())).stream()
//                    .filter(f -> f.getDeviceSource() == DeviceSourceEnum.大厅.getValue())
//                    .filter(f -> f.getDeviceOnlineStatus() == DeviceOnlineStatusEnum.在线.getValue())
                    .map(device -> {
                        DeviceLogQuery query = new DeviceLogQuery();
                        query.setDeviceId(device.getId());
                        query.setCreateTimeStart(DateUtils.getStrDateTime(new Date(System.currentTimeMillis() - timeout)));
                        DeviceLogEntity deviceLogEntity = deviceLogService.selectOne(query);
                        if (ObjectUtils.isEmpty(deviceLogEntity)) {
                            //更新设备下线
                            device.setOfflineTime(new Date());
                            device.setDeviceOnlineStatus(DeviceOnlineStatusEnum.离线.getValue());
                            cacheService.del(KEY_DEVICE_TYPE_CACHE + device.getDeviceCode());
                            return device;
                        }
                        return null;
                    }).filter(f -> f != null).collect(Collectors.toList());

            log.info("更新设备下线：{} ,时间:{}", JSON.toJSONString(collect), DateUtils.getStrDateTime(new Date(System.currentTimeMillis() - timeout)));
            deviceService.update(collect, null);

            List<DeviceAlarmEntity> alarmEntityList = collect.stream().map(device -> {
                //新增告警信息
                DeviceAlarmEntity deviceAlarmEntity = new DeviceAlarmEntity();
                deviceAlarmEntity.initAttrValue();
                deviceAlarmEntity.setDeviceId(device.getId());
                deviceAlarmEntity.setDeviceCode(device.getDeviceCode());
                deviceAlarmEntity.setAlarmType(AlarmTypeEnum.离线.getValue());
                deviceAlarmEntity.setAlarmLevel(AlarmLevelEnum.一般.getValue());
                deviceAlarmEntity.setAlarmTime(new Date());
                deviceAlarmEntity.setAlarmContent("当前设备已离线，请注意！");
                deviceAlarmEntity.setCreateTime(new Date());
                deviceAlarmEntity.setCreateUserId(1L);
                return deviceAlarmEntity;
            }).collect(Collectors.toList());
            deviceAlarmService.save(alarmEntityList);
        } catch (Exception e) {
            log.error("更新设备状态任务异常，结束执行", e);
        }
        log.debug("更新设备状态任务，结束执行");
    }


    /**
     * 定时清除设备日志
     */
    private void doDeviceLogDel() {
        //默认保存15天日志
        int timeout = -GlobalSysInfo.getParamIntValue(ParamKey.SYS_PARAM_LOG_TIME, 15);
        try {
            DeviceLogQuery query = new DeviceLogQuery();
            query.setCreateTimeEnd(DateUtils.getStrDateTime(DateUtils.addCurrDate(timeout)));
            Long[] ids = deviceLogService.find(query).stream().map(DeviceLogEntity::getId).toArray(Long[]::new);
            if (!ObjectUtils.isEmpty(ids)) {
                deviceLogService.remove(ids, null);
            }
        } catch (Exception e) {
            log.error("设备日志删除任务异常，结束执行", e);
        }
        log.debug("设备日志删除任务，结束执行");
    }


    /**
     * 定时查询更新其它设备状态
     */
    private void doDeviceQuery() {
        try {
            deviceService.getCacheList().parallelStream()
                    .filter(f -> f.getDeviceSource() == DeviceSourceEnum.其它.getValue())
                    .peek(device -> {
                        String sendUrl = GlobalSysInfo.getParamValue(ParamKey.SYS_PARAM_SEND_QUERY_URL, "http://127.0.0.1:18211/m/test/equipStateQuery");
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("macAddress", device.getDeviceMac());
                        SendTask sendTask = new SendTask(sendUrl, device.getId(), jsonObject.toJSONString(), deviceService);
                        sendTaskThreadPool.execute(sendTask);
                    }).count();
        } catch (Exception e) {
            log.error("查询设备状态任务异常，结束执行", e);
        }
        log.debug("查询设备状态任务，结束执行");
    }


    @Override
    public void stopTask(ITask task) throws AppException {

    }


}
