package com.usky.cdi.service.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.usky.cdi.domain.DmpDevice;
import com.usky.cdi.mapper.DmpDeviceMapper;
import com.usky.cdi.service.config.DeviceFieldConfig;
import com.usky.cdi.service.vo.IotDataTransferVO;
import lombok.Data;
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 java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

/**
 *
 * @author fyc
 * @email yuchuan.fu@chinausky.com
 * @date 2025/11/27
 */
@Data
@Slf4j
@Component
public class DeviceDataQuery {
    @Autowired
    private DmpDeviceMapper dmpDeviceMapper;
    @Value("${device.data.base-url}")
    private String baseUrl;
    @Value("${device.data.simulation}")
    private boolean simulation;

    @Autowired
    private DeviceFieldConfig deviceFieldConfig;

    private static final Set<Integer> ALLOWED_DEVICE_TYPES = new HashSet<>(Arrays.asList(
            711, 710, 709, 708, 707
    ));

    // 定义各参数的格式化器（整数位,小数位）
    private static final DecimalFormat FORMAT_2_2 = new DecimalFormat("00.00"); // 2位整数+2位小数
    private static final DecimalFormat FORMAT_0_3 = new DecimalFormat("0.000"); // 0位整数+3位小数
    private static final DecimalFormat FORMAT_1_2 = new DecimalFormat("0.00");  // 1位整数+2位小数
    private static final DecimalFormat FORMAT_3_2 = new DecimalFormat("000.00"); // 3位整数+2位小数
    private static final DecimalFormat FORMAT_4_2 = new DecimalFormat("0000.00"); // 4位整数+2位小数

    // ========== 新增缓存相关成员变量 ==========
    // 缓存A/B/C相电流值
    private static final Map<String, Double> currentValueCache = new ConcurrentHashMap<>();
    // 缓存各相复用次数
    private static final Map<String, Integer> currentReuseCountCache = new ConcurrentHashMap<>();
    // 最大复用次数（可调整）
    private static final int MAX_REUSE_COUNT = 3;
    // 复用概率（0.5=50%概率复用，可调整）
    private static final double REUSE_PROBABILITY = 0.5;

    // 定义模拟数据范围常量
    private static final double TEMP_RANGE_MIN = 10.0;
    private static final double TEMP_RANGE_MAX = 20.0;
    private static final double HUMIDITY_RANGE_MIN = 40.0;
    private static final double HUMIDITY_RANGE_MAX = 41.0;
    private static final double OXYGEN_RANGE_MIN = 20.0;
    private static final double OXYGEN_RANGE_MAX = 21.0;
    private static final double CO2_RANGE_MIN = 480.0;
    private static final double CO2_RANGE_MAX = 490.0;
    private static final double VOLTAGE_RANGE_MIN = 220.0;
    private static final double VOLTAGE_RANGE_MAX = 230.0;
    private static final double CURRENT_RANGE_MIN = 0.0;
    private static final double CURRENT_RANGE_MAX = 1.5;
    private static final double POWER_RANGE_MIN = 1.0;
    private static final double POWER_RANGE_MAX = 20.0;
    private static final double TEMP_LINE_RANGE_MIN = 20.0;
    private static final double TEMP_LINE_RANGE_MAX = 50.0;
    private static final double LEAKAGE_CURRENT_RANGE_MIN = 50.0;
    private static final double LEAKAGE_CURRENT_RANGE_MAX = 60.0;
    private static final double FLOATING_RANGE_MIN = 0.0;
    private static final double FLOATING_RANGE_MAX = 0.5;
    private static final double FLOATING_RANGE_MIN1 = 0.0;
    private static final double FLOATING_RANGE_MAX1 = 1.0;
    private static final double SEWAGE_LEVEL_MIN = 0.0;
    private static final double SEWAGE_LEVEL_MAX = 0.1;

    private static int callCount = 0;

    /**
     * 获取指定设备类型的设备数据
     * @param transferVO 设备数据传输请求参数
     * @return 设备数据列表
     */
    public List<JSONObject> getDeviceData(IotDataTransferVO transferVO) {
        // 参数验证
        if (transferVO == null || transferVO.getDevices() == null || transferVO.getDevices().isEmpty()) {
            log.warn("获取设备数据失败：参数无效");
            return Collections.emptyList();
        }

        try {
            // 构建请求参数
            JSONObject requestBody = new JSONObject();
            List<String> deviceUuids = transferVO.getDevices().stream()
                    .map(DmpDevice::getDeviceUuid)
                    .collect(Collectors.toList());
            requestBody.put("deviceuuid", deviceUuids);

            log.debug("请求设备数据接口，设备数量：{}", deviceUuids.size());
            String response = HttpClientUtils.doPostJson(baseUrl, requestBody.toJSONString());
            log.info("接口返回数据：{}", response);

            List<JSONObject> resultList = parseResponseData(response, transferVO.getDeviceType(), transferVO.getDevices());
            boolean useXiangyuMock = false;
            List<JSONObject> xiangyuDataList = new ArrayList<>();

            // 当租户数据为空时获取桃浦象屿相同设备数据进行模拟（修复版：不修改原始设备列表）
            if (resultList.isEmpty() && ALLOWED_DEVICE_TYPES.contains(transferVO.getDeviceType())) {
                LambdaQueryWrapper<DmpDevice> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(DmpDevice::getTenantId, 1205)
                        .eq(DmpDevice::getDeviceType, transferVO.getDeviceType())
                        .orderByAsc(DmpDevice::getId)
                        .last("LIMIT 1");
                DmpDevice xiangyuDevice = dmpDeviceMapper.selectOne(queryWrapper);

                if (xiangyuDevice != null) {
                    JSONObject xiangyuReq = new JSONObject();
                    xiangyuReq.put("deviceuuid", Collections.singletonList(xiangyuDevice.getDeviceUuid()));
                    String xiangyuResp = HttpClientUtils.doPostJson(baseUrl, xiangyuReq.toJSONString());

                    JSONObject responseObj = JSON.parseObject(xiangyuResp);
                    // 修复：象屿接口可能返回null/空串/非JSON，导致responseObj为null引发NPE
                    if (responseObj != null && responseObj.getJSONArray("data") != null && !responseObj.getJSONArray("data").isEmpty()) {
                        JSONArray dataArray = responseObj.getJSONArray("data");
                        JSONObject deviceData = dataArray.getJSONObject(0);
                        JSONObject metrics = deviceData.getJSONObject("metrics");
                        Object realtime = metrics.get("realtime");
                        System.out.println("接口返回数据时间戳对象：" + realtime);
                        Long timestamp = realtime instanceof Long ? (Long) realtime : null;
                        System.out.println("接口返回数据时间戳：" + timestamp);

                        if (timestamp != null && timestamp >= (System.currentTimeMillis() - 7 * 24 * 60 * 60 * 1000L)) {
                            // 修复：不修改原始设备列表，直接生成模拟模板
                            useXiangyuMock = true;
                            xiangyuDataList = parseResponseData(xiangyuResp, transferVO.getDeviceType(),
                                    Collections.singletonList(xiangyuDevice));
                        }
                    }
                }
            }

            // 若返回数据为空且开启模拟模式，则生成模拟数据
            if (resultList.isEmpty() && simulation) {
                log.info("接口返回数据为空，生成模拟数据，设备类型：{}", transferVO.getDeviceType());
                if (useXiangyuMock && !xiangyuDataList.isEmpty()) {
                    // 使用象屿数据作为模板生成全量模拟
                    resultList = generateSimulationData(transferVO.getDeviceType(), transferVO.getDevices(), xiangyuDataList.get(0));
                } else {
                    resultList = generateSimulationData(transferVO.getDeviceType(), transferVO.getDevices(), null);
                }
            } else if (resultList.size() < transferVO.getDevices().size()) {
                log.warn("接口返回数据数量与请求数量不一致，设备类型：{}", transferVO.getDeviceType());

                // 获取返回数据中的device_id集合
                Set<String> returnedDeviceIds = resultList.stream()
                        .map(data -> data.getString("device_id"))
                        .filter(Objects::nonNull)
                        .collect(Collectors.toSet());

                // 获取请求中devices的device_id集合
                Map<String, DmpDevice> requestDeviceMap = transferVO.getDevices().stream()
                        .filter(device -> device.getDeviceId() != null)
                        .collect(Collectors.toMap(DmpDevice::getDeviceId, device -> device));

                // 找出返回数据中缺少的device_id
                List<String> missingDeviceIds = requestDeviceMap.keySet().stream()
                        .filter(deviceId -> !returnedDeviceIds.contains(deviceId))
                        .collect(Collectors.toList());

                log.info("发现缺少的设备数据，生成模拟数据，设备数量：{}", missingDeviceIds.size());
                // 为缺少的设备生成模拟数据
                List<DmpDevice> missingDevices = missingDeviceIds.stream()
                        .map(requestDeviceMap::get)
                        .collect(Collectors.toList());

                JSONObject templateData = resultList.isEmpty() ?
                        (xiangyuDataList.isEmpty() ? null : xiangyuDataList.get(0))
                        : resultList.get(0);

                List<JSONObject> missingSimulationData = generateSimulationData(transferVO.getDeviceType(), missingDevices, templateData);
                // 修复：不再清空原有数据
                resultList.addAll(missingSimulationData);
            }

            // 最终校验
            if (resultList.size() != transferVO.getDevices().size()) {
                log.warn("数据整合后仍存在缺失，请求设备数量：{}，返回设备数量：{}",
                        transferVO.getDevices().size(), resultList.size());
            } else {
                log.debug("数据整合完成，设备数量与请求一致：{}", resultList.size());
            }

            return resultList;
        } catch (Exception e) {
            log.error("获取设备数据失败：{}", e.getMessage(), e);
            // 异常情况下若开启模拟模式，则生成模拟数据
            if (simulation) {
                log.info("接口调用异常，生成模拟数据，设备类型：{}", transferVO.getDeviceType());
                return generateSimulationData(transferVO.getDeviceType(), transferVO.getDevices(), null);
            }
            return Collections.emptyList();
        }
    }

    /**
     * 解析接口响应数据，提取指定字段
     * @param responseJson 接口响应JSON字符串
     * @param deviceType 设备类型
     * @param devices 设备列表
     * @return 解析后的设备数据列表
     */
    private List<JSONObject> parseResponseData(String responseJson, Integer deviceType, List<DmpDevice> devices) {
        List<JSONObject> resultList = new ArrayList<>();
        if (responseJson == null || responseJson.trim().isEmpty()) {
            log.warn("接口响应数据为空");
            return resultList;
        }

        try {
            // 构建设备UUID到ID的映射，过滤掉deviceUuid为null的设备
            Map<String, String> deviceUuidToIdMap = devices.stream()
                    .filter(device -> device.getDeviceUuid() != null)
                    .collect(Collectors.toMap(DmpDevice::getDeviceUuid, DmpDevice::getDeviceId));

            JSONObject responseObj = JSON.parseObject(responseJson);

            // 检查响应状态
            String status = responseObj.getString("status");
            String code = responseObj.getString("code");

            if (!"SUCCESS".equals(status) || !"0".equals(code)) {
                log.warn("接口返回失败：状态={}, 错误码={}, 错误信息={}", status, code, responseObj.getString("msg"));
                return resultList;
            }

            JSONArray dataArray = responseObj.getJSONArray("data");
            if (dataArray == null || dataArray.isEmpty()) {
                log.debug("接口响应数据为空数组");
                return resultList;
            }

            List<String> targetFields = getTargetFieldsByDeviceType(deviceType);

            for (int i = 0; i < dataArray.size(); i++) {
                JSONObject deviceData = dataArray.getJSONObject(i);
                if (deviceData == null) {
                    continue;
                }

                JSONObject metrics = deviceData.getJSONObject("metrics");
                String deviceUuid = deviceData.getString("deviceuuid");

                if (metrics == null || deviceUuid == null) {
                    continue;
                }

                JSONObject targetData = new JSONObject();
                boolean hasValidData = false;

                // 提取目标字段数据
                for (String field : targetFields) {
                    Object value = metrics.get(field);
                    if (value != null) {
                        targetData.put(field, value);
                        hasValidData = true;
                    }
                }

                // 添加设备标识信息
                String deviceId = deviceUuidToIdMap.get(deviceUuid);

                // 如果找不到，直接丢弃这条数据，不放入结果
                if (deviceId == null) {
                    continue;
                }

                // 能走到这里，说明一定有 deviceId
                targetData.put("deviceuuid", deviceUuid);
                targetData.put("device_id", deviceId);

                if (hasValidData) {
                    resultList.add(targetData);
                }
            }

            log.debug("解析接口响应数据完成，有效设备数据数量：{}", resultList.size());
            return resultList;
        } catch (Exception e) {
            log.error("解析接口响应数据失败：{}", e.getMessage(), e);
            return Collections.emptyList();
        }
    }

    /**
     * 根据设备类型获取目标字段（自动包含time）
     * @param deviceType 设备类型
     * @return 目标字段列表
     */
    private List<String> getTargetFieldsByDeviceType(Integer deviceType) {
        if (deviceType == null) {
            log.warn("获取目标字段失败：设备类型为空");
            return Collections.singletonList("realtime");
        }

        String fieldsStr = deviceFieldConfig.deviceFieldMapping().get(deviceType.toString());
        if (fieldsStr == null || fieldsStr.trim().isEmpty()) {
            log.warn("获取目标字段失败：设备类型{}对应的字段映射不存在", deviceType);
            return Collections.singletonList("realtime");
        }

        List<String> fields = Arrays.stream(fieldsStr.split(","))
                .map(String::trim)
                .filter(field -> !field.isEmpty())
                .collect(Collectors.toList());

        // 确保包含时间字段
        if (!fields.contains("realtime")) {
            fields.add("realtime");
        }

        return fields;
    }

    /**
     * 生成模拟数据（按指定精度格式化）
     * @param deviceType 设备类型
     * @param devices 设备列表
     * @return 模拟数据列表
     */
    private List<JSONObject> generateSimulationData(Integer deviceType, List<DmpDevice> devices, JSONObject standard) {
        List<JSONObject> simulationList = new ArrayList<>();
        long currentTime = System.currentTimeMillis();
        // System.out.println("深拷贝当前时间戳：" + currentTime);

        // 获取天气数据（仅在需要时）
        // 期望：只有“象屿模板为空/缺字段”时，才用天气数据对温湿度做修正；有象屿模板就不要再相加
        boolean needWeatherForTemp = (deviceType != null && deviceType == 707) && (standard == null || standard.get("wd") == null);
        boolean needWeatherForHumi = (deviceType != null && deviceType == 708) && (standard == null || standard.get("sd") == null);
        boolean needWeatherForElectric = (deviceType != null && deviceType == 704) && (standard == null);
        Map<String, Double> weatherData = null;
        if (needWeatherForTemp || needWeatherForHumi || needWeatherForElectric) {
            weatherData = WeatherFetcher.fetchWeather();
        }

        for (DmpDevice device : devices) {
            JSONObject simData;

            if (standard != null) {
                simData = new JSONObject();
                simData.putAll(standard);

                // 【关键】先移除，确保 FastJSON 内部缓存失效
                simData.remove("realtime");
                simData.remove("device_id");
                simData.remove("deviceuuid");

                // 再重新 put，强制类型正确
                simData.put("realtime", currentTime);
                simData.put("device_id", device.getDeviceId());
                // System.out.println("深拷贝时间戳1：" + simData.getLong("realtime"));

                if (device.getDeviceUuid() != null && standard.containsKey("deviceuuid")) {
                    simData.put("deviceuuid", device.getDeviceUuid());
                }

                // 若象屿模板里缺少温湿度字段，则再回退到天气+差值逻辑补齐（避免“所有情况都相加”）
                if (deviceType != null && deviceType == 707 && simData.get("wd") == null) {
                    double temp707;
                    if (weatherData != null && !weatherData.isEmpty()) {
                        double floating = BasementClimateUtil.getTempDiffWithOutdoor();
                        temp707 = weatherData.get("temperature") + floating;
                    } else {
                        temp707 = BasementClimateUtil.getCurrentTempRange();
                    }
                    simData.put("wd", temp707);
                } else if (deviceType != null && deviceType == 708 && simData.get("sd") == null) {
                    double humi708;
                    if (weatherData != null && !weatherData.isEmpty()) {
                        double floating = BasementClimateUtil.getHumiDiffWithOutdoor();
                        humi708 = weatherData.get("humidity") + floating;
                    } else {
                        humi708 = BasementClimateUtil.getCurrentHumiRange();
                    }
                    simData.put("sd", humi708);
                }

                addNoiseToNumericFields(simData, deviceType);
                // System.out.println("深拷贝时间戳2：" + simData.getLong("realtime"));
            } else {
                // ❌ 无标准模板，走原始随机逻辑
                simData = new JSONObject();
                simData.put("realtime", currentTime);
                simData.put("device_id", device.getDeviceId());

                switch (deviceType) {
                    case 707:
                        double temp707 = 0.0;
                        if (weatherData != null && !weatherData.isEmpty()) {
                            double floating = BasementClimateUtil.getTempDiffWithOutdoor();
                            temp707 = weatherData.get("temperature") + floating;
                        } else {
                            temp707 = BasementClimateUtil.getCurrentTempRange();
                        }
                        simData.put("wd", temp707);
                        break;

                    case 708:
                        double humi708 = 0.0;
                        if (weatherData != null && !weatherData.isEmpty()) {
                            double floating = BasementClimateUtil.getHumiDiffWithOutdoor();
                            humi708 = weatherData.get("humidity") + floating;
                        } else {
                            humi708 = BasementClimateUtil.getCurrentHumiRange();
                        }
                        simData.put("sd", humi708);
                        break;

                    case 709:
                        double o2709 = ThreadLocalRandom.current().nextDouble(OXYGEN_RANGE_MIN, OXYGEN_RANGE_MAX);
                        simData.put("o2", formatNumber(o2709, FORMAT_2_2));
                        break;

                    case 710:
                        double co2710 = ThreadLocalRandom.current().nextDouble(CO2_RANGE_MIN, CO2_RANGE_MAX);
                        simData.put("co2", formatNumber(co2710, FORMAT_0_3));
                        break;

                    case 711:
                        simData.put("co", 0);
                        break;

                    case 702:
                        simData.put("leach_status", 0);
                        break;

                    case 703:
                        simData.put("sensorValue", 0);
                        break;

                    case 704:
                    case 705:
                        double aVoltage = ThreadLocalRandom.current().nextDouble(VOLTAGE_RANGE_MIN, VOLTAGE_RANGE_MAX);
                        simData.put("aVoltage", formatNumber(aVoltage, FORMAT_3_2));
                        double bVoltage = ThreadLocalRandom.current().nextDouble(VOLTAGE_RANGE_MIN, VOLTAGE_RANGE_MAX);
                        simData.put("bVoltage", formatNumber(bVoltage, FORMAT_3_2));
                        double cVoltage = ThreadLocalRandom.current().nextDouble(VOLTAGE_RANGE_MIN, VOLTAGE_RANGE_MAX);
                        simData.put("cVoltage", formatNumber(cVoltage, FORMAT_3_2));

                        String deviceId = device.getDeviceId();
                        double aElectricity = getCurrentValue(deviceId, "a");
                        simData.put("aElectricity", formatNumber(aElectricity, FORMAT_3_2));
                        double bElectricity = getCurrentValue(deviceId, "b");
                        simData.put("bElectricity", formatNumber(bElectricity, FORMAT_3_2));
                        double cElectricity = getCurrentValue(deviceId, "c");
                        simData.put("cElectricity", formatNumber(cElectricity, FORMAT_3_2));

                        double totalPower = (aVoltage * aElectricity + bVoltage * bElectricity + cVoltage * cElectricity) / 1000;
                        simData.put("totalPower", formatNumber(totalPower, FORMAT_4_2));

                        double lineTemp = 0.0;
                        if (weatherData != null && !weatherData.isEmpty()) {
                            lineTemp = weatherData.get("temperature") + 1.0;
                        } else {
                            lineTemp = ThreadLocalRandom.current().nextDouble(TEMP_LINE_RANGE_MIN, TEMP_LINE_RANGE_MAX);
                        }
                        simData.put("line1TEMP", formatNumber(lineTemp + ThreadLocalRandom.current().nextDouble(FLOATING_RANGE_MIN1, FLOATING_RANGE_MAX1), FORMAT_2_2));
                        simData.put("Line2TEMP", formatNumber(lineTemp + ThreadLocalRandom.current().nextDouble(FLOATING_RANGE_MIN1, FLOATING_RANGE_MAX1), FORMAT_2_2));
                        simData.put("Line3TEMP", formatNumber(lineTemp + ThreadLocalRandom.current().nextDouble(FLOATING_RANGE_MIN1, FLOATING_RANGE_MAX1), FORMAT_2_2));
                        simData.put("Line4TEMP", formatNumber(lineTemp + ThreadLocalRandom.current().nextDouble(FLOATING_RANGE_MIN1, FLOATING_RANGE_MAX1), FORMAT_2_2));

                        simData.put("leakageCurrent", formatNumber(ThreadLocalRandom.current().nextDouble(LEAKAGE_CURRENT_RANGE_MIN, LEAKAGE_CURRENT_RANGE_MAX), FORMAT_4_2));
                        break;

                    case 712:
                        simData.put("qx", 0);
                        break;

                    case 713:
                        simData.put("cd", 0);
                        break;

                    case 714:
                        simData.put("wy", 0);
                        break;

                    case 716:
                        String deviceId1 = device.getDeviceId();
                        double value = FixedWaterLevelGenerator.getSensorValue(deviceId1);
                        simData.put("sensorValue", formatNumber(value, FORMAT_1_2));
                        break;
                    // case 719:
                    //     break;
                    case 720:
                        simData.put("startDuration", 0);
                        simData.put("batteryVoltage", randomDouble261_266());
                        break;
                    default:
                        log.warn("未知设备类型：{}，无法生成模拟数据", deviceType);
                        continue;
                }
            }

            simulationList.add(simData);
        }

        log.info("生成模拟数据完成，设备类型：{}，数量：{}", deviceType, simulationList.size());
        return simulationList;
    }

    private double randomDouble261_266() {
        Random random = new Random();
        int intVal = 2610 + random.nextInt(51);
        return intVal / 100.0;
    }

    private void addNoiseToNumericFields(JSONObject data, Integer deviceType) {
        Map<String, Double> noiseConfig = getNoiseConfigByDeviceType(deviceType);

        // 这些字段永远不加噪
        Set<String> skipFields = new HashSet<>(Arrays.asList("realtime", "device_id", "deviceuuid"));

        for (String key : data.keySet()) {
            if (skipFields.contains(key)) continue;
            if (isDiscreteField(key)) continue;

            Object value = data.get(key);
            Double original = null;

            // 【关键】支持 Number 和 String 两种类型
            if (value instanceof Number) {
                original = ((Number) value).doubleValue();
            } else if (value instanceof String) {
                try {
                    original = Double.parseDouble((String) value);
                } catch (NumberFormatException e) {
                    System.out.println("跳过字段（非数字）: " + key + " = " + value);
                    continue; // 不是数字字符串，跳过
                }
            }

            if (original == null) continue;

            // 每个设备、每个字段、每次调用都是独立的随机噪声 ✅
            double noiseFactor = noiseConfig.getOrDefault(key, 0.02);
            double noise = original * noiseFactor * (ThreadLocalRandom.current().nextDouble(-1, 1));
            double newValue = original + noise;

            System.out.println("加噪: " + key + " | 原值=" + original + " | 噪声=" + noise + " | 新值=" + newValue);
            log.info("加噪: {} | 原值={} | 噪声={} | 新值={}", key, original, noise, newValue);

            // 保持原类型：原来是 String 就格式化回 String，原来是 Number 就放 Double
            if (value instanceof String) {
                data.put(key, formatNumber(newValue, getFormatByKey(key)));
            } else {
                data.put(key, newValue);
            }
        }
    }

    /**
     * 根据字段名获取对应的格式化器
     */
    private DecimalFormat getFormatByKey(String key) {
        switch (key) {
            case "aVoltage":
            case "bVoltage":
            case "cVoltage":
            case "aElectricity":
            case "bElectricity":
            case "cElectricity":
                return FORMAT_3_2;
            case "totalPower":
                return FORMAT_4_2;
            case "line1TEMP":
            case "Line2TEMP":
            case "Line3TEMP":
            case "Line4TEMP":
            case "wd":
            case "sd":
            case "o2":
                return FORMAT_2_2;
            case "co2":
                return FORMAT_0_3;
            case "leakageCurrent":
                return FORMAT_4_2;
            case "sensorValue":
                return FORMAT_1_2;
            default:
                return null; // 不格式化，保持原样
        }
    }

    private boolean isDiscreteField(String field) {
        return field.equalsIgnoreCase("realtime")
                || field.equalsIgnoreCase("device_id")
                || field.equalsIgnoreCase("deviceuuid")
                || field.equalsIgnoreCase("leach_status")
                || field.equalsIgnoreCase("sensorValue")
                || field.equalsIgnoreCase("qx")
                || field.equalsIgnoreCase("cd")
                || field.equalsIgnoreCase("wy")
                || field.equalsIgnoreCase("co");
    }

    // 获取各字段的浮动模拟配置
    private Map<String, Double> getNoiseConfigByDeviceType(Integer deviceType) {
        Map<String, Double> config = new HashMap<>();
        switch (deviceType) {
            case 707: // 温度
                config.put("wd", 0.03); //
                break;
            case 708: // 湿度
                config.put("sd", 0.05);
                break;
            case 709: // 氧气
                config.put("o2", 0.02);
                break;
            case 710: // CO2
                config.put("co2", 0.02);
                break;
            case 704: // 电气火灾
                config.put("aVoltage", 0.01);
                config.put("bVoltage", 0.01);
                config.put("cVoltage", 0.01);
                config.put("aElectricity", 0.05);
                config.put("bElectricity", 0.05);
                config.put("cElectricity", 0.05);
                config.put("totalPower", 0.05);
                config.put("line1TEMP", 0.03);
                config.put("Line2TEMP", 0.03);
                config.put("Line3TEMP", 0.03);
                config.put("Line4TEMP", 0.03);
                config.put("leakageCurrent", 0.1); // 电流波动大些
                break;
            default:
                // 默认所有数值字段 ±2%
                break;
        }
        return config;
    }

    /**
     * 通用数值格式化方法
     * @param value 原始数值
     * @param format 格式化器
     * @return 格式化后的字符串
     */
    private String formatNumber(double value, DecimalFormat format) {
        if (format == null) {
            return String.valueOf(value);
        }
        return format.format(value);
    }

    // ========== 获取带缓存的电流值 ==========
    private double getCurrentValue(String deviceId, String phase) {
        String cacheKey = (deviceId == null ? "dummy" : deviceId) + "_" + phase;
        int count = currentReuseCountCache.getOrDefault(cacheKey, 0);

        if (!currentValueCache.containsKey(cacheKey) || count >= MAX_REUSE_COUNT) {
            return generateNewCurrent(cacheKey);
        }

        boolean reuse = ThreadLocalRandom.current().nextDouble() < REUSE_PROBABILITY;
        if (reuse) {
            currentReuseCountCache.put(cacheKey, count + 1);
            return currentValueCache.get(cacheKey);
        } else {
            return generateNewCurrent(cacheKey);
        }
    }

    // 同步修改generateNewCurrent方法（参数改为cacheKey）
    private double generateNewCurrent(String cacheKey) {
        double newValue = ThreadLocalRandom.current().nextDouble(CURRENT_RANGE_MIN, CURRENT_RANGE_MAX);
        newValue = Math.round(newValue * 100.0) / 100.0;
        currentValueCache.put(cacheKey, newValue);
        currentReuseCountCache.put(cacheKey, 0);
        return newValue;
    }
}