package com.xinda.mq.redischannel.consumer;

import com.alibaba.fastjson2.JSONObject;
import com.xinda.base.service.ISessionStore;
import com.xinda.common.constant.XinDaConstant;
import com.xinda.common.core.device.DeviceAndProtocol;
import com.xinda.common.core.mq.DeviceStatusBo;
import com.xinda.common.core.mq.MQSendMessageBo;
import com.xinda.common.core.thingsModel.ThingsModelSimpleItem;
import com.xinda.common.enums.DeviceStatus;
import com.xinda.iot.domain.Device;
import com.xinda.iot.domain.Product;
import com.xinda.iot.model.ThingsModels.ThingsModelShadow;
import com.xinda.iot.service.IDeviceService;
import com.xinda.iot.service.IProductService;
import com.xinda.iot.cache.IDeviceCache;
import com.xinda.iot.util.SnowflakeIdWorker;
import com.xinda.mq.model.ReportDataBo;
import com.xinda.mq.redischannel.producer.MessageProducer;
import com.xinda.mq.service.IMqttMessagePublish;
import com.xinda.mq.service.IRuleEngine;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;

/**
 * 设备状态消息处理类
 *
 * @author gsb
 * @date 2022/10/10 11:02
 */
@Slf4j
@Component
public class DeviceStatusConsumer {

    @Autowired
    private IDeviceCache deviceCache;
    @Resource
    private IRuleEngine ruleEngine;
    @Resource
    private IDeviceService deviceService;
    @Resource
    private IProductService productService;
    @Resource
    private ISessionStore sessionStore;
    @Resource
    private IMqttMessagePublish mqttMessagePublish;
    @Value("${server.broker.enabled}")
    private Boolean enabled;
    private SnowflakeIdWorker snowflakeIdWorker = new SnowflakeIdWorker(2);

    public synchronized void consume(DeviceStatusBo bo) {
        try {
            Device device = deviceService.selectDeviceBySerialNumber(bo.getSerialNumber());
            if (device == null) {//设备不存在，添加设备
                device = new Device();
                device.setDeviceName("设备" + bo.getSerialNumber());
                device.setDeviceId(0L);
                device.setDeviceType(1);
                device.setFirmwareVersion(new BigDecimal(1));
                device.setIsShadow(0);
                device.setIsSimulate(0);
                device.setLocationWay(1);
                device.setProductId(147L);
                device.setProductName("测试");
                device.setSerialNumber(bo.getSerialNumber());
                device.setStatus(1);
                device.setTenantId(1L);
                device.setTenantName("admin");
                device.setGroupId(0L);

                deviceService.insertDeviceTest(device);
                device = deviceService.selectDeviceBySerialNumber(bo.getSerialNumber());
            }
            Product product = productService.selectProductByProductId(device.getProductId());
            if (enabled && product.getDeviceType() != 3) { //如果使用Netty版本 监控设备不走这里
                boolean containsKey = sessionStore.containsKey(bo.getSerialNumber());
                boolean isOnline = device.getStatus() == 3;
                log.info("=>session：{},数据库：{}，更新状态:{}", containsKey, isOnline, bo.getStatus().getCode());
                if (containsKey && !isOnline) {
                    //如果session存在，但数据库状态不在线，则以session为准
                    bo.setStatus(DeviceStatus.ONLINE);
                    device.setDelFlag("0");
                }
                if (!containsKey && isOnline) {
                    bo.setStatus(DeviceStatus.OFFLINE);
                }
//                判断下 项目id
                if(bo.getStatus().getDescription().equals("离线")){
                    if (device.getGroupId().equals(0L) || device.getGroupId() == null) {
                        //设置删除状态 todo
                        device.setDelFlag("2");
                    }
                }
            }
            /*更新设备状态*/

            deviceCache.updateDeviceStatusCache(bo, device);
            //处理影子模式值
            this.handlerShadow(device, bo.getStatus());
            //设备上下线执行规则引擎
            ReportDataBo dataBo = new ReportDataBo();
            dataBo.setRuleEngine(true);
            dataBo.setProductId(device.getProductId());
            dataBo.setType(bo.getStatus().equals(DeviceStatus.ONLINE) ? 5 : 6);
            dataBo.setSerialNumber(bo.getSerialNumber());
            ruleEngine.ruleMatch(dataBo);
        } catch (Exception e) {
            log.error("=>设备状态处理异常", e);
        }
    }

    private void handlerShadow(Device device, DeviceStatus status) {
        //获取设备协议编码
        DeviceAndProtocol dp = deviceService.selectProtocolBySerialNumber(device.getSerialNumber());
        String protocolCode = dp.getProtocolCode();
        /* 设备上线 处理影子值*/
        if (status.equals(DeviceStatus.ONLINE) && device.getIsShadow() == 1) {
            ThingsModelShadow shadow = deviceService.getDeviceShadowThingsModel(device);
            List<ThingsModelSimpleItem> properties = shadow.getProperties();
            List<ThingsModelSimpleItem> functions = shadow.getFunctions();
            //JsonArray组合发送
            if (XinDaConstant.PROTOCOL.JsonArray.equals(protocolCode)) {
                if (!CollectionUtils.isEmpty(properties)) {
                    mqttMessagePublish.publishProperty(device.getProductId(), device.getSerialNumber(), properties, 3);
                }
                if (!CollectionUtils.isEmpty(functions)) {
                    mqttMessagePublish.publishFunction(device.getProductId(), device.getSerialNumber(), functions, 3);
                }
            } else { //其他协议单个发送
                functions.addAll(properties);
                if (!CollectionUtils.isEmpty(functions)) {
                    for (ThingsModelSimpleItem function : functions) {
                        MQSendMessageBo bo = new MQSendMessageBo();
                        bo.setDp(dp);
                        bo.setShadow(false);
                        bo.setIdentifier(function.getId());
                        bo.setSerialNumber(device.getSerialNumber());
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put(function.getId(), function.getValue());
                        bo.setParams(jsonObject);
                        bo.setValue(function.getValue());
                        long id = snowflakeIdWorker.nextId();
                        bo.setMessageId(id + "");
                        //发送到MQ处理
                        MessageProducer.sendFunctionInvoke(bo);
                    }
                }
            }
        }
    }
}
