package org.jeecg.modules.api.listener;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.google.gson.JsonObject;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.DateUtils;
import org.jeecg.config.mqtt.MqttConfigProperties;
import org.jeecg.config.mqtt.MqttMessageEvent;
import org.jeecg.config.mqtt.MqttMessageSender;
import org.jeecg.modules.api.model.ToolData;
import org.jeecg.modules.datarecord.entity.DataRecord;
import org.jeecg.modules.datarecord.mapper.DataRecordMapper;
import org.jeecg.modules.regular.entity.Regular;
import org.jeecg.modules.regular.entity.RegularDetail;
import org.jeecg.modules.regular.entity.RegularInput;
import org.jeecg.modules.regular.mapper.RegularDetailMapper;
import org.jeecg.modules.regular.mapper.RegularInputMapper;
import org.jeecg.modules.toolBorrowingRecord.entity.ToolBorrowingRecord;
import org.jeecg.modules.toolBorrowingRecord.mapper.ToolBorrowingRecordMapper;
import org.jeecg.modules.toolSheet.entity.ToolSheet;
import org.jeecg.modules.toolSheet.mapper.ToolSheetMapper;
import org.jeecg.modules.workOrder.entity.WorkOrder;
import org.jeecg.modules.workOrder.entity.WorkRecord;
import org.jeecg.modules.workOrder.mapper.WorkOrderMapper;
import org.jeecg.modules.workOrder.mapper.WorkRecordMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

@Slf4j
@AllArgsConstructor
@Component
public class MqttMessageListener {

    private ToolBorrowingRecordMapper toolBorrowingRecordMapper;
    private WorkOrderMapper workOrderMapper;
    private WorkRecordMapper workRecordMapper;
    private DataRecordMapper dataRecordMapper;
    private MqttConfigProperties mqttConfigProperties;
    private RegularDetailMapper regularDetailMapper;
    private RegularInputMapper inputMapper;
    private MqttMessageSender mqttMessageSender;
    private ToolSheetMapper toolSheetMapper;

    private static final Map<String, Double> UNIT_TO_OHM = new HashMap<>();
    static {
        UNIT_TO_OHM.put("Ω", 1.0);
        UNIT_TO_OHM.put("KΩ", 1_000.0);   // 千欧
        UNIT_TO_OHM.put("MΩ", 1_000_000.0); // 兆欧
    }

    @EventListener
    public void handleMqttMessage(MqttMessageEvent event) {
        String topic = event.getTopic();
        String payload = event.getPayload();
        // todo 此处test_topic为测试时数采小车程序上报工具采集到的数据时使用
        if(mqttConfigProperties.getProducerTopicMobile().equals(topic)){
            // 调用业务方法
            if(toolDataAcquireLogic(payload)){
                log.info("工具数据保存成功：{}",payload);
            }
        }else {
            System.out.println("**************************:"+payload);
        }

    }

    /**
     * 处理数采小车上传的工具数据报文
     * @param dataPacket
     */
    private boolean toolDataAcquireLogic(String dataPacket) {
        try {
            // 业务逻辑
            ToolData toolData = JSON.parseObject(dataPacket, ToolData.class);
//            handleSaveData(toolData);
            toolData.setDeviceMac(toolData.getDeviceMac().toUpperCase());
            switch (toolData.getDeviceType()) {
                case "1":
                case "2":
                case "3":
                case "4":
                    return handleCliperData(toolData);
                default:
                    log.error("未知的设备数据类型："+dataPacket);
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("msgId", toolData.getMsgId());
                    jsonObject.put("code", 0);
                    mqttMessageSender.send("dcl27_data_result", JSONUtils.toJSONString(jsonObject));
                    return false;
            }
        }catch (Exception e){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("msgId", "-1");
            jsonObject.put("code", -1);
            mqttMessageSender.send("dcl27_data_result", JSONUtils.toJSONString(jsonObject));
            log.error("工具数据保存失败：{}",e.getMessage());
//            e.printStackTrace();
            return false;
        }
    }

    private void handleSaveData(ToolData toolData){
        DataRecord record = new DataRecord();
        record.setDeviceMac(toolData.getDeviceMac());
        record.setValue(Double.valueOf(toolData.getData()));
        record.setDeviceName(toolData.getDeviceName());
        record.setUnit(toolData.getUnit());
        dataRecordMapper.insert(record);
    }
    /**
     * 处理数显卡尺上报的数据
     * @param toolData
     * @return
     * @throws Exception
     */
    private boolean handleCliperData(ToolData toolData) throws Exception {
        if(StringUtils.isBlank(toolData.getData())){ // 空数据直接跳过
            return false;
        }
        ToolBorrowingRecord borrowingRecord = toolBorrowingRecordMapper.selectWorkOrderByDeviceMac(toolData.getDeviceMac());
        if(borrowingRecord == null){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("msgId", toolData.getMsgId());
            jsonObject.put("code", 1);
            mqttMessageSender.send("dcl27_data_result", JSONUtils.toJSONString(jsonObject));
            throw new Exception("未找到,MAC地址为"+toolData.getDeviceMac()+"的工具借用信息！");
        }
        ToolSheet toolSheet = toolSheetMapper.selectOne(new LambdaQueryWrapper<ToolSheet>().eq(ToolSheet::getMac, toolData.getDeviceMac()));
        if(toolSheet == null){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("msgId", toolData.getMsgId());
            jsonObject.put("code", 1);
            mqttMessageSender.send("dcl27_data_result", JSONUtils.toJSONString(jsonObject));
            throw new Exception("未找到工器具！");
        }
        borrowingRecord.setToolTypeId(toolSheet.getToolId());
        //查找workRecord
        WorkRecord workRecord = workRecordMapper.selectOne(new LambdaQueryWrapper<WorkRecord>()
                .eq(WorkRecord::getWorkOrder, borrowingRecord.getWorkOrder())
                .eq(WorkRecord::getToolId, borrowingRecord.getToolId())
                .eq(WorkRecord::getNowWay,1));
        if(workRecord == null){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("msgId", toolData.getMsgId());
            jsonObject.put("code", 1);
            mqttMessageSender.send("dcl27_data_result", JSONUtils.toJSONString(jsonObject));
            throw new Exception("未找到工单！");
        }else{
            workRecord.setNumericValue(new BigDecimal(toolData.getData()).setScale(2, RoundingMode.HALF_UP).toString());
            workRecord.setUnit(toolData.getUnit());
            workRecord.setInspecTime(new Date());
            workRecordMapper.updateById(workRecord);
            //todo 判断是否合格
            RegularInput input = inputMapper.selectOne(new LambdaQueryWrapper<RegularInput>().eq(RegularInput::getId, workRecord.getRegularInputId()));
            if(checkValid(toolData,input)){
                //todo 发送合格
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("msgId", toolData.getMsgId());
                jsonObject.put("code", 0);
                mqttMessageSender.send("dcl27_data_result", JSONUtils.toJSONString(jsonObject));
            }else {
                //todo 发送不合格
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("msgId", toolData.getMsgId());
                jsonObject.put("code", 1);
                mqttMessageSender.send("dcl27_data_result", JSONUtils.toJSONString(jsonObject));
            }
        }
        //暂时注释，测试不通过再打开
//        //todo 根据工单编号查找测量项点
//        WorkOrder workOrder = workOrderMapper.selectById(borrowingRecord.getWorkOrder());
//        if(workOrder == null || workOrder.getStatus() == 4){
//            throw new Exception("该工单已完成作业！");
//        }
//        //todo 查找作业规程
//        List<RegularDetail> regularDetailList = regularDetailMapper.selectList(new LambdaQueryWrapper<RegularDetail>()
//                .eq(RegularDetail::getRegularId, workOrder.getRegularId()).eq(RegularDetail::getMeasure, 1));
//        //todo 使用工具编号匹配测量项点
//        regularDetailList.forEach(detail -> {
//            List<RegularInput> inputs = inputMapper.selectList(new LambdaQueryWrapper<RegularInput>().eq(RegularInput::getDetailId, detail.getId()).eq(RegularInput::getToolId, borrowingRecord.getToolTypeId()));
//            inputs.forEach(input -> {
//                //todo 判断是否合格
//                if(Double.parseDouble(toolData.getData()) < input.getMinValue() || Double.parseDouble(toolData.getData()) > input.getMaxValue()){
//                    //todo 发送不合格
//                    JSONObject jsonObject = new JSONObject();
//                    jsonObject.put("msgId", toolData.getMsgId());
//                    jsonObject.put("code", 1);
//                    mqttMessageSender.send("dcl27_data_result", JSONUtils.toJSONString(jsonObject));
//                }else{
//                    //todo 发送合格
//                    JSONObject jsonObject = new JSONObject();
//                    jsonObject.put("msgId", toolData.getMsgId());
//                    jsonObject.put("code", 0);
//                    mqttMessageSender.send("dcl27_data_result", JSONUtils.toJSONString(jsonObject));
//                }
//
//                WorkRecord record = new WorkRecord();
//                record.setWorkOrder(workOrder.getId());
//                record.setDeviceId(workOrder.getDeviceId());
//                record.setUnit(toolData.getUnit());
//                record.setNumericValue(toolData.getData());
//                record.setNowWay(1);
//                record.setRegularInputId(input.getId());
//                record.setPartId(detail.getDepard());
//                record.setToolId(borrowingRecord.getToolId());
//                workRecordMapper.insert(record);
//            });
//        });
        return true;
    }

    /**
     * 处理无线轮径尺上报的数据
     * @param toolData
     * @return
     * @throws Exception
     */
    private boolean handleRulerData(ToolData toolData) throws Exception {
        //这里统一使用查Mac的方法，将轮径尺的编号填到MAC字段(本身也不知道轮径尺的MAC地址，编号唯一)，用编号代替MAC查询
        ToolBorrowingRecord borrowingRecord = toolBorrowingRecordMapper.selectWorkOrderByDeviceMac(toolData.getDeviceName());
        if(borrowingRecord == null){
            throw new Exception("未找到,编号为"+toolData.getDeviceName()+"的轮径尺！");
        }
        WorkRecord record = workRecordMapper.selectOne(new LambdaQueryWrapper<WorkRecord>()
                .eq(WorkRecord::getToolId,borrowingRecord.getToolId())
                .eq(WorkRecord::getWorkOrder,borrowingRecord.getWorkOrder())
                .eq(WorkRecord::getNowWay,1));
        record.setNumericValue(toolData.getData());
        record.setUnit(toolData.getUnit());
        record.setInspecTime(ObjectUtil.isNotNull(toolData.getDateTime()) ? DateUtils.parseDatetime(toolData.getDateTime()) : DateUtils.getDate());
        return workRecordMapper.updateById(record) > 0;
    }

    /**
     * 处理扳手上报的数据
     * @param toolData
     * @return
     * @throws Exception
     */
    private boolean handleWrenchData(ToolData toolData) throws Exception {
        //这里统一使用查Mac的方法，将扳手编号填到MAC字段(本身也不知道扳手的MAC地址，编号唯一)，用编号代替MAC查询
        ToolBorrowingRecord borrowingRecord = toolBorrowingRecordMapper.selectWorkOrderByDeviceMac(toolData.getDeviceName());
        if(borrowingRecord == null){
            throw new Exception("未找到,编号为"+toolData.getDeviceName()+"的扳手！");
        }
        WorkRecord record = workRecordMapper.selectOne(new LambdaQueryWrapper<WorkRecord>()
                .eq(WorkRecord::getToolId,borrowingRecord.getToolId())
                .eq(WorkRecord::getWorkOrder,borrowingRecord.getWorkOrder())
                .eq(WorkRecord::getNowWay,1));
        record.setNumericValue(toolData.getData());
        record.setUnit(toolData.getUnit());
        record.setInspecTime(ObjectUtil.isNotNull(toolData.getDateTime()) ? DateUtils.parseDatetime(toolData.getDateTime()) : DateUtils.getDate());
        return workRecordMapper.updateById(record) > 0;
    }

    /**
     * 处理万用表上报的数据
     * @param toolData
     * @return
     * @throws Exception
     */
    private boolean handleMultimeterData(ToolData toolData) throws Exception {
        //这里统一使用查Mac的方法，将万用表编号填到MAC字段(本身也不知道扳手的MAC地址，编号唯一)，用编号代替MAC查询
        ToolBorrowingRecord borrowingRecord = toolBorrowingRecordMapper.selectWorkOrderByDeviceMac(toolData.getDeviceName());
        if(borrowingRecord == null){
            throw new Exception("未找到,编号为"+toolData.getDeviceName()+"的万用表！");
        }
        WorkRecord record = workRecordMapper.selectOne(new LambdaQueryWrapper<WorkRecord>()
                .eq(WorkRecord::getToolId,borrowingRecord.getToolId())
                .eq(WorkRecord::getWorkOrder,borrowingRecord.getWorkOrder())
                .eq(WorkRecord::getNowWay,1));
        record.setNumericValue(toolData.getData());
        record.setUnit(toolData.getUnit());
        record.setInspecTime(ObjectUtil.isNotNull(toolData.getDateTime()) ? DateUtils.parseDatetime(toolData.getDateTime()) : DateUtils.getDate());
        return workRecordMapper.updateById(record) > 0;
    }

    /// true为合格
    private boolean checkValid(ToolData toolData, RegularInput input) {
        try {
            String dataUnit = toolData.getUnit();
            String inputUnit = input.getUnit();

            // 判断是否为电阻类单位（包含 Ω 字符）
            boolean isResistance = inputUnit != null && inputUnit.contains("Ω");

            double dataValue = Double.parseDouble(toolData.getData());
            double minValue = input.getMinValue();
            double maxValue = input.getMaxValue();

            if (isResistance) {
                // 电阻类：统一转换为欧姆（Ω）后再比较
                double dataInOhm = convertToOhm(dataValue, dataUnit);
                double minInOhm = convertToOhm(minValue, inputUnit);
                double maxInOhm = convertToOhm(maxValue, inputUnit);

                return dataInOhm >= minInOhm && dataInOhm <= maxInOhm;
            } else {
                // 非电阻类：直接比较原始数值（假设单位一致或无量纲）
                return dataValue >= minValue && dataValue <= maxValue;
            }
        } catch (Exception e) {
            // 数值解析失败、单位不支持等
            System.err.println("校验失败: " + e.getMessage());
            return false;
        }
    }

    /**
     * 将数值从指定单位转换为欧姆（Ω）
     */
    private double convertToOhm(double value, String unit) {
        if (unit == null || unit.trim().isEmpty()) {
            return value; // 默认视为 Ω
        }
        unit = unit.trim();
        Double factor = UNIT_TO_OHM.get(unit);
        if (factor == null) {
            throw new IllegalArgumentException("不支持的电阻单位: " + unit);
        }
        return value * factor;
    }
}
