package com.fastbee.mq.redischannel.consumer;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.fastbee.common.constant.FastBeeConstant;
import com.fastbee.common.core.mq.DeviceReportBo;
import com.fastbee.iot.domain.DeviceReportInfo;
import com.fastbee.iot.mapper.DeviceReportInfoMapper;
import com.fastbee.mq.redischannel.producer.IssueInstructionsProducer;
import com.fastbee.mq.service.impl.DeviceOtherMsgHandler;
import com.fastbee.mqttclient.PubMqttClient;
import com.fastbee.rechargecard.domain.NgWaterPumpUsageRecords;
import com.fastbee.rechargecard.mapper.NgWaterPumpUsageRecordsMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author gsb
 * @date 2023/2/27 14:33
 */
@Slf4j
@Component
public class DeviceOtherMsgConsumer {

    @Resource
    private DeviceOtherMsgHandler otherMsgHandler;

    @Autowired
    private IssueInstructionsProducer issueInstructionsProducer;

    @Autowired
    private DeviceReportInfoMapper deviceReportInfoMapper;

    @Autowired
    private NgWaterPumpUsageRecordsMapper ngWaterPumpUsageRecordsMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private PubMqttClient pubMqttClient;

    @Async(FastBeeConstant.TASK.DEVICE_OTHER_TASK)
    public void consume(DeviceReportBo bo){
        try {
             //处理emq订阅的非 property/post 属性上报的消息 ，因为其他消息量小，放在一起处理
            Long productId;//产品id,设备所属产品
            Long packetId;//包号
            byte[] data = bo.getData();//数据
            String topic=bo.getTopicName();//主题
            //从主题中解析出产品id
            String[] split = topic.split("/");
            productId= Long.valueOf(split[1]);
            //从主题中解析出设备序列号
            String serialNumber= split[2];//设备序列号

            // System.err.println("主题："+topic+"--产品id:"+productId+"--设备序列号:"+serialNumber);
            //设备上报数据消息---------------------------------------------------------------------------------
            if(topic.endsWith("/info/up")){
                deviceDataReportHandler(new String(data));
                //更新设备在线状态
                updateDeviceOnlineStatus( productId,serialNumber);//拼成一个唯一的key，只要key存在，则设备在线
                // updateDeviceOnlineStatusDb(serialNumber);
                //保存使用记录
                NgWaterPumpUsageRecords pumpUsageRecords=new NgWaterPumpUsageRecords();
                pumpUsageRecords.setDeviceNumber(serialNumber);
                JSONObject jsonObject = JSONUtil.parseObj(data);
                jsonObject.set("time", (LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));//收到消息的当地时间
                if(jsonObject.getStr("type")!=null){
                    if(jsonObject.getStr("type").equals("waterEleData")){
                        String data1 = jsonObject.getStr("data");
                        //收到定时报文
                        if(JSONUtil.parseObj(data1).get("action").equals("timeMsg")){
                            pumpUsageRecords.setMessageContent(JSONUtil.toJsonStr(jsonObject));
                            // int i = ngWaterPumpUsageRecordsMapper.insertNgWaterPumpUsageRecords(pumpUsageRecords);
                            // if(i<1){
                            //     System.err.println("--------------------------保存使用记录失败!---------------------------");
                            // }
                        }else if(JSONUtil.parseObj(data1).get("action").equals("safeMsg")){
                            //续费在线状态
                            updateDeviceOnlineStatus( productId,serialNumber);
                            //保存数据
                            pumpUsageRecords.setMessageContent(JSONUtil.toJsonStr(jsonObject));
                            // int i = ngWaterPumpUsageRecordsMapper.insertNgWaterPumpUsageRecords(pumpUsageRecords);
                            // if(i<1){
                            //     System.err.println("--------------------------保存使用记录失败!---------------------------");
                            // }

                        }//开阀门，关阀门
                        else if(JSONUtil.parseObj(data1).get("action").equals("startPump")||JSONUtil.parseObj(data1).get("action").equals("stopPump")){
                            int i = ngWaterPumpUsageRecordsMapper.insertNgWaterPumpUsageRecords(pumpUsageRecords);
                            if(i<1){
                                System.err.println("--------------------------保存使用记录失败!---------------------------");
                            }
                        }
                    }
                }
                //构建回复消息-----------------------------------------------------------------------------
                // Map<String,Object> reportMsg=new HashMap<>();
                // reportMsg.put("code",0);
                // reportMsg.put("msg","ok");
                // issueInstructionsProducer.receiveDataReportResponse(productId.toString(),serialNumber,JSONUtil.toJsonStr(reportMsg));
            }
            //打印设备
            else if ( topic.endsWith("/info/reply")) {
                platformDataReportAckHandler(new String(data));
                updateDeviceOnlineStatus( productId,serialNumber);
                // updateDeviceOnlineStatusDb(serialNumber);
            }
            else if (topic.endsWith("/cmd/down")) {
                platformCmdHandler(new String(data));
                //回应

            } else if (topic.endsWith("/cmd/reply")) {
                deviceCmdAckHandler(new String(data));
                updateDeviceOnlineStatus( productId,serialNumber);
                // updateDeviceOnlineStatusDb(serialNumber);
            }
            otherMsgHandler.messageHandler(bo);
        }catch (Exception e){
            // log.error("=>设备其他消息处理出错",e);
        }
    }


    /**
     * 缓存更新设备在线状态
     */
    private void updateDeviceOnlineStatus(Long productId,String serialNumber){
        try {
            //判断
            if(Boolean.TRUE.equals(stringRedisTemplate.hasKey("neixiang_device_online_status:" + productId + ":" + serialNumber))){
                //重新设置过期时间
                stringRedisTemplate.expire("neixiang_device_online_status:"+productId+":"+serialNumber,360, TimeUnit.SECONDS);
                return;
            }
            stringRedisTemplate.opsForValue().set("neixiang_device_online_status:"+productId+":"+serialNumber,"1",360, TimeUnit.SECONDS);
        }catch (Exception e){
            log.error("=>更新缓存设备在线状态出错",e);
        }
    }
    /**
     * 数据库更新设备在线状态
     */
    private void updateDeviceOnlineStatusDb(String serialNumber){
        try {
            boolean update = new LambdaUpdateChainWrapper<>(deviceReportInfoMapper)
                    .set(DeviceReportInfo::getOnLine, 1)
                    .eq(DeviceReportInfo::getSerialNumber, serialNumber)
                    .update();
            if(!update){
                throw new RuntimeException("=>数据库更新设备在线状态失败");
            }
        }catch (Exception e){
            log.error("=>更新数据库设备在线状态出错",e);
        }
    }



    /**
     * 处理设备数据上报
     * @param data 消息
     */
    private void deviceDataReportHandler(String data){
        // System.err.println("mqtt接收到设备上报数据："+ data);
        //回应
//
//            //解析
////            String jsonString = "{\"type\": \"waterEleData\", \"pakSn\": 123, \"data\": {\"workState\": 1, \"action\": \"startPump\", \"mcuSn\": \"MCU123456\", \"sumEle\": 5000, \"sumFlow\": 3000, \"insFlow\": 2.5, \"userSumFlow\": 1500, \"areaCode\": \"010\", \"cardId\": \"CARD12345678\", \"userBalance\": 100.0, \"userSumEle\": 3000, \"curEle\": 50, \"curFlow\": 200, \"insPower\": 2300}}";
//            JSONObject entries = JSONUtil.parseObj(data);
////            System.err.println("解析后："+entries);
//            //获取帧标识
//            String type = entries.getStr("type");
//            //获取帧号
//            Long pakSn = entries.getLong("pakSn");
//            //获取数据
//            JSONObject dataObj = entries.getJSONObject("data");
//            //获取水泵状态0=关泵,1=开泵
//            Integer workState = dataObj.getInt("workState");
//            //获取动作
//            String action = dataObj.getStr("action");
//            //获取单片机编码
//            String mcuSn = dataObj.getStr("mcuSn");
//            //获取累计用电量
//            Integer sumEle = dataObj.getInt("sumEle");
//            //获取累计用水量
//            Integer sumFlow = dataObj.getInt("sumFlow");
//            //获取瞬时流量
//            Double insFlow = dataObj.getDouble("insFlow");
//            //当前用户累计用水量
//            Integer userSumFlow = dataObj.getInt("userSumFlow");
//            //获取区域号
//            String areaCode = dataObj.getStr("areaCode");
//            //获取卡号
//            String cardId = dataObj.getStr("cardId");
//            //获取用户余额
//            Double userBalance = dataObj.getDouble("userBalance");
//            //获取用户累计用电量
//            Integer userSumEle = dataObj.getInt("userSumEle");
//            //获取本次用电量
//            Integer curEle = dataObj.getInt("curEle");
//            //获取本次用水量
//            Integer curFlow = dataObj.getInt("curFlow");
//            //获取瞬时功率
//            Integer insPower = dataObj.getInt("insPower");

    }
    /**
     * 处理平台接收到数据上报的回应
     */
    private void platformDataReportAckHandler(String data){
        // System.err.println("mqtt回应收到设备上报数据："+ data);
        //处理

    }
    /**
     * 处理平台给设备下发的指令
     */
    private void platformCmdHandler(String data){
        System.err.println("--------------------------------------------------------------mqtt-broker收到给设备下发命令："+ data);
//        JSONObject obj = JSONUtil.parseObj(data);

    }
    /**
     * 处理设备收到指令回应
     */
    private void deviceCmdAckHandler(String data){
        System.err.println("----------------------------------------------------------------------平台收到设备执行完指令的结果："+ data);
    }

    public static void main(String[] args) {
        System.err.println((LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
    }
}
