package cn.gintone.config;

import cn.gintone.controller.vo.DeviceReqConfListReqVO;
import cn.gintone.controller.vo.DeviceReqConfSaveReqVO;
import cn.gintone.dal.DeviceReqConfMapper;
import cn.gintone.entity.DeviceReqConfDO;
import cn.gintone.iotdbUtils.MyDateUtils;
import cn.gintone.service.DeviceReqConfService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.kafka.support.KafkaHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

@Component
public class PumpStationKafkaConsumer {

    @Autowired
    private DeviceReqConfMapper deviceReqConfMapper;

    private static final Logger logger = LoggerFactory.getLogger(PumpStationKafkaConsumer.class);

    private HashMap<String, Date> snCodeDateMap = new HashMap<>();

    private final Semaphore semaphore = new Semaphore(5);

    /**
     * 主消费者 - 处理大部分topic
     */
    @KafkaListener(
            topics = {
                    "MKLDYL_JCSJ", "BZYYZ_JCSJ", "BZPSQ_JCSJ", "BZXZY_JCSJ",
                    "BZZLB_JCSJ", "BZYZJ_JCSJ", "BZJSZM_JCSJ", "BZYLZM_JCSJ", "BZCSZM_JCSJ",
                    "BZSCZM_JCSJ", "BZTXZM_JCSJ", "BZTFFJ_JCSJ", "BZSFFJ_JCSJ", "BZPFFJ_JCSJ",
                    "BZFJ_JCSJ", "BZFSJ_JCSJ", "BZYWCJ_JCSJ_2", "BZQBJ_JCSJ", "BZYDYHQT_JCSJ",
                    "BZZF_JCSJ", "BZQSB_JCSJ", "BZGSJ_JCSJ", "BZPDJ_JCSJ", "BZLDYWJ_JCSJ",
                    "BZYWCJ_JCSJ", "BZYWJ_JCSJ", "BZBSF_JCSJ", "BZFF_JCSJ", "BZDF_JCSJ",
                    "TYJG_JCSJ", "BZSB_JCSJ", "TYYLD_JCSJ", "TYYSGW_JCSJ", "YSGWLLJ_JCSJ",
                    "YSGWSWJ_JCSJ"
            },
            containerFactory = "kafkaListenerContainerFactory2",
            groupId = "pump_station_main_group"  // 改为不同的组
    )
    public void consumePumpStationData(String message,
                                       @Header(KafkaHeaders.RECEIVED_TOPIC) String topic,
                                       Acknowledgment ack) {
        try {
//            logger.info("主消费者收到泵站数据, topic: {}, 消息长度: {}", topic, message);

            // 立即提交偏移量，避免阻塞
            ack.acknowledge();

            // 异步处理业务逻辑
            processMessageContent(topic, message);

        } catch (Exception e) {
            logger.error("处理泵站数据时发生错误, topic: {}, 错误: {}", topic, e.getMessage(), e);
        }
    }

    @KafkaListener(
            topics = {"BZHSZM_JCSJ"},
            containerFactory = "kafkaListenerContainerFactory2",
            groupId = "pump_station_bzhszm_group"  // 专用组
    )
    public void consumePumpStationData_BZHSZM_JCSJ(String message,
                                                   @Header(KafkaHeaders.RECEIVED_TOPIC) String topic,
                                                   Acknowledgment ack) {
//        logger.info("BZHSZM_JCSJ专用消费者收到数据, topic: {}, 消息长度: {}", topic, message);
        try {
            ack.acknowledge();
            processMessageContent(topic, message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @KafkaListener(
            topics = {"BZPSZM_JCSJ"},
            containerFactory = "kafkaListenerContainerFactory2",
            groupId = "pump_station_bzpszm_group"  // 专用组
    )
    public void consumePumpStationData_BZPSZM_JCSJ(String message,
                                                   @Header(KafkaHeaders.RECEIVED_TOPIC) String topic,
                                                   Acknowledgment ack) {
//        logger.info("BZPSZM_JCSJ专用消费者收到数据, topic: {}, 消息长度: {}", topic, message);
        try {
            ack.acknowledge();
            processMessageContent(topic, message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理消息内容
     */
    private void processMessageContent(String topic, String message) {
        try {
            // 先进行基本的消息验证
            if (message == null || message.trim().isEmpty()) {
                logger.warn("收到空消息, topic: {}", topic);
                return;
            }

            // 解析JSON消息
            JSONObject msgJsonObject = parseMessageJson(topic, message);
            if (msgJsonObject == null) {
                return;
            }

            // 获取序列号
            String snCode = getSnCode(msgJsonObject, topic);
            if (snCode == null) {
                return;
            }

            // 检查时间有效性
            if (!isMessageTimeValid(msgJsonObject)) {
                logger.debug("消息时间无效, topic: {}, SN: {}", topic, snCode);
                return;
            }

            // 检查消息频率
            if (shouldSkipMessage(snCode)) {
                logger.debug("消息频率过高被跳过, topic: {}, SN: {}", topic, snCode);
                return;
            }

            // 更新设备配置状态
            updateDeviceConfigStatus(snCode, topic);

        } catch (Exception e) {
            logger.error("处理消息内容失败, topic: {}, 错误: {}", topic, e.getMessage(), e);
        }
    }

    /**
     * 解析JSON消息 - 修复版本
     */
    private JSONObject parseMessageJson(String topic, String message) {
        // 先检查消息是否以 { 开头，以 } 结尾
        if (!isValidJsonFormat(message)) {
            logger.error("消息格式无效，不是合法的JSON, topic: {}, message: {}",
                    topic, getMessagePreview(message));
            return null;
        }

        try {
            JSONObject jsonObject = JSON.parseObject(message);
            if (jsonObject == null) {
                logger.error("JSON解析结果为null, topic: {}, message: {}",
                        topic, getMessagePreview(message));
                return null;
            }
            return jsonObject;
        } catch (Exception e) {
            // 安全的日志记录，避免消息内容本身导致的问题
            logger.error("JSON转换错误, topic: {}, message预览: {}, 错误类型: {}, 错误详情: {}",
                    topic,
                    getMessagePreview(message),
                    e.getClass().getSimpleName(),
                    e.getMessage());
            return null;
        }
    }

    /**
     * 安全的获取消息预览
     */
    private String getMessagePreview(String message) {
        if (message == null) {
            return "null";
        }

        try {
            // 限制预览长度，避免日志过大
            String preview = message.trim();
            if (preview.length() > 200) {
                preview = preview.substring(0, 200) + "...";
            }

            // 移除可能影响日志格式的字符
            preview = preview.replace("\n", " ").replace("\r", " ");
            return preview;
        } catch (Exception e) {
            return "无法解析消息内容";
        }
    }

    /**
     * 检查消息是否是合法的JSON格式
     */
    private boolean isValidJsonFormat(String message) {
        if (message == null || message.trim().isEmpty()) {
            return false;
        }

        String trimmed = message.trim();
        return trimmed.startsWith("{") && trimmed.endsWith("}");
    }
    /**
     * 获取序列号
     */
    private String getSnCode(JSONObject msgJsonObject, String topic) {
        try {
            return msgJsonObject.getString("serialNo");
        } catch (Exception e) {
            logger.error("获取序列号失败, topic: {}", topic, e);
            return null;
        }
    }

    /**
     * 检查消息时间是否有效（24小时内）
     */
    private boolean isMessageTimeValid(JSONObject msgJsonObject) {
        try {
            JSONArray services = msgJsonObject.getJSONArray("services");
            if (services == null || services.isEmpty()) {
                return false;
            }

            JSONObject paramsObject = services.getJSONObject(0).getJSONObject("params");
            if (paramsObject == null) {
                return false;
            }

            String ts = paramsObject.getString("ts");
            if (ts == null) {
                return false;
            }

            long messageTime = MyDateUtils.stringToLong(ts);
            long currentTime = System.currentTimeMillis();

            // 检查消息时间是否在24小时内
            return (currentTime - messageTime) < (24 * 60 * 60 * 1000);

        } catch (Exception e) {
            logger.error("检查消息时间有效性失败", e);
            return false;
        }
    }

    /**
     * 检查是否应该跳过该消息（基于频率控制）
     */
    private boolean shouldSkipMessage(String snCode) {
        Date oldDate = snCodeDateMap.get(snCode);
        if (oldDate == null) {
            return false;
        }

        long timeDiff = System.currentTimeMillis() - oldDate.getTime();
        // 20分钟内重复消息被跳过
        return timeDiff < (20 * 60 * 1000);
    }

    /**
     * 更新设备配置状态
     */
    private void updateDeviceConfigStatus(String snCode, String topic) {
        try {
            // 更新SN码的时间戳
            snCodeDateMap.put(snCode, new Date());

            // 查询设备配置
            DeviceReqConfListReqVO query = new DeviceReqConfListReqVO();
            query.setSnCode(snCode);
            List<DeviceReqConfDO> deviceReqConfList = deviceReqConfMapper.selectList(query);

            if (deviceReqConfList == null || deviceReqConfList.isEmpty()) {
                logger.debug("未找到设备配置, SN: {}", snCode);
                return;
            }

            // 批量更新设备配置状态
            int updateCount = updateDeviceConfigBatch(deviceReqConfList);

            logger.info("设备配置状态更新完成, topic: {}, SN: {}, 更新记录数: {}",
                    topic, snCode, updateCount);

        } catch (Exception e) {
            logger.error("更新设备配置状态失败, SN: {}", snCode, e);
            throw new RuntimeException("更新设备配置状态失败", e);
        }
    }

    /**
     * 批量更新设备配置
     */
    private int updateDeviceConfigBatch(List<DeviceReqConfDO> deviceReqConfList) {
        int updateCount = 0;
        Date currentDate = new Date();

        for (DeviceReqConfDO deviceConf : deviceReqConfList) {
            try {
                int result = deviceReqConfMapper.update(new UpdateWrapper<DeviceReqConfDO>().lambda()
                        .eq(DeviceReqConfDO::getId, deviceConf.getId())
                        .set(DeviceReqConfDO::getState, 1)
                        .set(DeviceReqConfDO::getSycnDate, currentDate)
                );

                if (result > 0) {
                    updateCount++;
                }

            } catch (Exception e) {
                logger.error("更新设备配置失败, ID: {}", deviceConf.getId(), e);
            }
        }

        return updateCount;
    }
}