package com.mortals.xhx.daemon.task;

import com.mortals.framework.ap.GlobalSysInfo;
import com.mortals.framework.exception.AppException;
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.util.WebSocketUtil;
import com.mortals.xhx.base.system.param.service.ParamService;
import com.mortals.xhx.common.code.DeviceOnlineStatusEnum;
import com.mortals.xhx.common.code.DeviceMethodEnum;
import com.mortals.xhx.common.code.DeviceStatusEnum;
import com.mortals.xhx.common.key.ParamKey;
import com.mortals.xhx.module.device.model.*;
import com.mortals.xhx.module.device.service.DeviceLogService;
import com.mortals.xhx.module.device.service.DeviceModuleService;
import com.mortals.xhx.module.device.service.DeviceModuleUseService;
import com.mortals.xhx.module.device.service.DeviceService;
import com.mortals.xhx.module.platform.model.PlatformEntity;
import com.mortals.xhx.module.platform.service.PlatformService;
import com.mortals.xhx.module.product.model.ProductEntity;
import com.mortals.xhx.module.product.service.ProductService;
import lombok.extern.apachecommons.CommonsLog;
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.Map;
import java.util.stream.Collectors;

/**
 * 设备模块使用统计任务
 *
 * @author: zxfei
 * @date: 2022/3/9 15:19
 */
@CommonsLog
@Service("DeviceModuleUseTask")
public class DeviceModuleUseTaskImpl implements ITaskExcuteService {

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

    @Autowired
    private ProductService productService;
    @Autowired
    private PlatformService platformService;
    @Autowired
    private DeviceModuleService moduleService;


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


    /**
     * 统计设备模块使用率
     */
    private void doDeviceModuleUse() {
        Map<String, DeviceModuleEntity> moduleMap = moduleService.find(new DeviceModuleQuery()).stream().collect(Collectors.toMap(x -> x.getModuleMsgCode(), y -> y, (o, n) -> n));
        try {

            // TODO: 2022/7/2 根据每个设备单独查询统计 计算数据量会减少
            List<DeviceModuleUseEntity> moduleUseEntityList = deviceService.getCacheList().stream().flatMap(device -> {
                //查询当前设备日志
                List<DeviceLogEntity> deviceLogList = deviceLogService.find(new DeviceLogQuery().deviceId(device.getId()));
                //分组统计每个模块头使用率
                Map<String, Long> modelCollect = deviceLogList.parallelStream().collect(Collectors.groupingBy(DeviceLogEntity::getMessageHead, Collectors.counting()));
                return modelCollect.entrySet().stream().map(item -> {
                    if (moduleMap.containsKey(item.getKey())) {
                        DeviceModuleUseEntity deviceModuleUseEntity = new DeviceModuleUseEntity();
                        deviceModuleUseEntity.initAttrValue();
                        DeviceModuleEntity deviceModuleEntity = moduleMap.get(item.getKey());

                        deviceModuleUseEntity.setDeviceId(device.getId());
                        deviceModuleUseEntity.setModuleMsgCode(deviceModuleEntity.getModuleMsgCode());
                        deviceModuleUseEntity.setModuleName(deviceModuleEntity.getModuleName());
                        deviceModuleUseEntity.setUseNum(item.getValue());
                        deviceModuleUseEntity.setCreateUserId(1L);
                        deviceModuleUseEntity.setCreateTime(new Date());
                        return deviceModuleUseEntity;
                    }
                    return null;
                }).filter(f -> f != null);
            }).collect(Collectors.toList());


            if (!ObjectUtils.isEmpty(moduleUseEntityList)) {
                //遍历，更新统计数据表 标识 设备id与消息头
                Map<String, DeviceModuleUseEntity> collect = deviceModuleUseService.find(new DeviceModuleUseQuery()).stream().collect(Collectors.toMap(x -> x.getDeviceId() + "#" + x.getModuleMsgCode(), y -> y, (o, n) -> n));
                moduleUseEntityList.stream().forEach(mudule -> {
                    String key = mudule.getDeviceId() + "#" + mudule.getModuleMsgCode();
                    if (collect.containsKey(key)) {
                        //更新
                        DeviceModuleUseEntity deviceModuleUseEntity = collect.get(key);
                        mudule.setId(deviceModuleUseEntity.getId());
                        mudule.setUpdateTime(new Date());
                        mudule.setUpdateUserId(1L);
                        deviceModuleUseService.update(mudule, null);
                    } else {
                        //新增
                        deviceModuleUseService.save(mudule, null);

                    }
                });

            }

        } catch (Exception e) {
            log.error("更新任务异常，结束执行", e);
        }
    }


    /**
     * 统计更新设备状态
     */
    private void doDeviceUpOrDown() {
        int timeout = GlobalSysInfo.getParamIntValue(ParamKey.SYS_PARAM_HEADBEAT_TIMEOUT, 60) * 1000;
        try {
            //获取所有设备，针对每个设备查询最近指定秒的日志，如果没有则更新下线
            deviceService.getCacheList().stream()
                    .filter(f -> f.getDeviceStatus() == DeviceStatusEnum.在线.getValue())
                    .peek(device -> {
                        DeviceLogQuery query = new DeviceLogQuery();
                        query.setCreateTimeStart(DateUtils.getStrDateTime(new Date(System.currentTimeMillis() - timeout)));
                        DeviceLogEntity deviceLogEntity = deviceLogService.selectOne(query);
                        if (ObjectUtils.isEmpty(deviceLogEntity)) {
                            //更新设备下线
                            device.setOfflineTime(new Date());
                            device.setDeviceStatus(DeviceStatusEnum.离线.getValue());
                            deviceService.update(device);
                            String msg = String.format("%s设备:%s  ,离线！", device.getProductName(), device.getDeviceCode());
                            WebSocketUtil.broadcast(SendToAllRequest.TYPE, new SendToAllRequest().setContent(msg));

                            PlatformEntity platformEntity = platformService.get(device.getPlatformId());
                            ProductEntity productEntity = productService.get(device.getProductId());
                            if (!ObjectUtils.isEmpty(platformEntity) && !ObjectUtils.isEmpty(productEntity)) {
                                //新增设备通知第三方平台
                                deviceService.sendThirdParty(device, productEntity, platformEntity, DeviceMethodEnum.OFFLINE);
                            }
                        }
                    }).count();
        } catch (Exception e) {
            log.error("更新设备状态任务异常，结束执行", e);
        }
        log.debug("更新设备状态任务，结束执行");
    }


    /**
     * 定时清除设备日志
     */
    private void doDeviceLogDel() {
        //默认保存30天日志
        int timeout = -GlobalSysInfo.getParamIntValue(ParamKey.SYS_PARAM_LOG_TIME, 30);
        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("设备日志删除任务，结束执行");
    }


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

    }


}
