package com.fizz.business.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fizz.business.constants.enums.DeviceEnum;
import com.fizz.business.constants.enums.WsTypeEnum;
import com.fizz.business.domain.DeviceSnapshot;
import com.fizz.business.domain.msg.*;
import com.fizz.business.dto.DeviceChartDataDTO;
import com.fizz.business.dto.DeviceFieldTrendDTO;
import com.fizz.business.dto.DeviceHistoryTrendDTO;
import com.fizz.business.mapper.DeviceSnapshotMapper;
import com.fizz.business.utils.WebSocketUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 设备数据快照服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DeviceSnapshotService {

    // 使用ConcurrentHashMap存储最新的测量数据
    private final Map<Class<?>, OpcMessage> latestMeasurements = new ConcurrentHashMap<>();
    private final DeviceSnapshotMapper deviceSnapshotMapper;
    private final ObjectMapper objectMapper;

    /**
     * 最近一次成功创建设备快照的时间（用于兜底触发，避免完全依赖调度器）
     */
    private volatile LocalDateTime lastSnapshotTime;

    /**
     * 更新最新的测量数据
     * @param message 测量数据消息
     */
    public void updateLatestMeasurement(OpcMessage message) {
        if (message != null) {
            latestMeasurements.put(message.getClass(), message);
            log.trace("更新测量数据缓存: {}", message.getClass().getSimpleName());
        }
    }

    /**
     * 由实时测量处理链路兜底触发快照创建：
     * - 与定时任务互不冲突
     * - 仅当距离上次快照 >= 5 分钟时才真正落库
     */
    public void captureSnapshotIfNeeded() {
        try {
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime last = lastSnapshotTime;
            if (last == null || java.time.Duration.between(last, now).toMinutes() >= 5) {
                createDeviceSnapshots();
                lastSnapshotTime = now;
            }
        } catch (Exception e) {
            log.error("兜底创建设备数据快照失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 创建当前所有设备的数据快照
     */
    @Transactional(rollbackFor = Exception.class)
    public void createDeviceSnapshots() {
        try {
            // 获取当前时间戳
            LocalDateTime now = LocalDateTime.now();
            log.info("开始创建设备快照，当前时间: {}, latestMeasurements缓存大小: {}", now, latestMeasurements.size());

            // 获取最新的测量数据
            AppMeasureEntryMessage entry = (AppMeasureEntryMessage) latestMeasurements.get(AppMeasureEntryMessage.class);
            AppMeasureFurnaceMessage furnace = (AppMeasureFurnaceMessage) latestMeasurements.get(AppMeasureFurnaceMessage.class);
            AppMeasureCoatMessage coat = (AppMeasureCoatMessage) latestMeasurements.get(AppMeasureCoatMessage.class);
            AppMeasureExitMessage exit = (AppMeasureExitMessage) latestMeasurements.get(AppMeasureExitMessage.class);

            log.info("测量数据状态 - entry: {}, furnace: {}, coat: {}, exit: {}",
                    entry != null ? "有数据" : "null",
                    furnace != null ? "有数据" : "null",
                    coat != null ? "有数据" : "null",
                    exit != null ? "有数据" : "null");

            if (entry == null && furnace == null && coat == null && exit == null) {
                log.warn("没有可用的测量数据，跳过快照创建。latestMeasurements缓存内容: {}", latestMeasurements.keySet());
                return;
            }

            // 为每个设备创建快照
            List<DeviceSnapshot> snapshots = new ArrayList<>();
            int deviceCount = 0;
            for (DeviceEnum device : DeviceEnum.values()) {
                deviceCount++;
                try {
                    DeviceSnapshot snapshot = createDeviceSnapshot(device, now, entry, furnace, coat, exit);
                    if (snapshot != null) {
                        snapshots.add(snapshot);
                        log.debug("设备[{}]快照创建成功", device.name());
                    } else {
                        log.debug("设备[{}]快照返回null（可能没有对应数据）", device.name());
                    }
                } catch (Exception e) {
                    log.error("创建设备[{}]快照失败: {}", device.name(), e.getMessage(), e);
                }
            }

            log.info("共处理{}个设备，成功创建{}个快照", deviceCount, snapshots.size());

            // 批量保存快照
            if (!snapshots.isEmpty()) {
                int savedCount = 0;
                for (DeviceSnapshot snapshot : snapshots) {
                    try {
                        int result = deviceSnapshotMapper.insert(snapshot);
                        if (result > 0) {
                            savedCount++;
                            log.debug("设备快照保存成功: deviceCode={}, createTime={}",
                                    snapshot.getDeviceCode(), snapshot.getCreateTime());
                        } else {
                            log.warn("设备快照保存失败（insert返回0）: deviceCode={}", snapshot.getDeviceCode());
                        }
                    } catch (Exception e) {
                        log.error("保存设备快照到数据库失败: deviceCode={}, error={}",
                                snapshot.getDeviceCode(), e.getMessage(), e);
                    }
                }
                log.info("成功保存{}个设备数据快照到数据库", savedCount);

                // 推送所有设备的历史趋势数据
                pushAllDevicesHistoryTrend();

                // 推送设备统计数据
                pushAllChartData();

                // 推送每个设备每个字段的趋势数据（供前端画"点位趋势小图"）
                pushAllDeviceFieldTrends();
            } else {
                log.warn("没有可保存的快照数据，所有设备快照创建都返回null");
            }
        } catch (Exception e) {
            log.error("创建设备数据快照失败: {}", e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 推送所有设备的历史趋势数据（今天一天的数据，10分钟间隔）
     */
    public void pushAllDevicesHistoryTrend() {
        try {
            for (DeviceEnum device : DeviceEnum.values()) {
                DeviceHistoryTrendDTO trendData = getDeviceHistoryTrend(device.name());
                if (trendData != null && trendData.getSeries() != null && !trendData.getSeries().isEmpty()) {
                    WebSocketUtil.sendHistoryTrendMessage(trendData);
                }
            }
        } catch (Exception e) {
            log.error("推送设备历史趋势数据失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 推送设备统计数据
     */
    public void pushAllChartData() {
        try {
            DeviceChartDataDTO chartData = buildAllChartData();
            if (chartData != null) {
                WebSocketUtil.sendChartDataMessage(chartData);
            }
        } catch (Exception e) {
            log.error("推送统计数据失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 推送每个设备每个字段的趋势数据（今天范围，10分钟间隔采样）
     */
    public void pushAllDeviceFieldTrends() {
        try {
            for (DeviceEnum device : DeviceEnum.values()) {
                List<String> fields = device.getParamFields();
                if (fields == null || fields.isEmpty()) continue;
                for (String field : fields) {
                    DeviceFieldTrendDTO dto = getDeviceFieldTrend(device.name(), field);
                    if (dto != null) {
                        WebSocketUtil.sendDeviceFieldTrendMessage(dto);
                    }
                }
            }
        } catch (Exception e) {
            log.error("推送设备字段趋势失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 获取 单设备-单字段 今日趋势与统计（10分钟采样）
     */
    public DeviceFieldTrendDTO getDeviceFieldTrend(String deviceCode, String fieldName) {
        try {
            DeviceEnum device = DeviceEnum.fromName(deviceCode);
            if (device == null) return null;

            // 今天范围
            LocalDate today = LocalDate.now();
            LocalDateTime startTime = today.atStartOfDay();
            LocalDateTime endTime = today.atTime(LocalTime.MAX);

            // 查询今天的快照
            LambdaQueryWrapper<DeviceSnapshot> qw = new LambdaQueryWrapper<DeviceSnapshot>()
                    .eq(DeviceSnapshot::getDeviceCode, deviceCode)
                    .between(DeviceSnapshot::getCreateTime, startTime, endTime)
                    .orderByAsc(DeviceSnapshot::getCreateTime);

            List<DeviceSnapshot> rows = deviceSnapshotMapper.selectList(qw);
            if (rows == null || rows.isEmpty()) return null;

            // 10分钟采样
            List<DeviceSnapshot> sampled = sampleDataByInterval(rows, 10);

            DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
            List<String> categories = new ArrayList<>(sampled.size());
            List<Double> data = new ArrayList<>(sampled.size());

            for (DeviceSnapshot s : sampled) {
                categories.add(s.getCreateTime().format(timeFormatter));
                double v = 0.0;
                try {
                    Map<String, Object> json = objectMapper.readValue(s.getSnapshotData(), Map.class);
                    Object raw = json.get(fieldName);
                    if (raw instanceof Number) v = ((Number) raw).doubleValue();
                } catch (Exception ignore) {
                }
                data.add(v);
            }

            // 统计（忽略全0）
            List<Double> valid = new ArrayList<>();
            for (Double v : data) {
                if (v != null && v != 0.0) valid.add(v);
            }

            Double avg = null, max = null, min = null;
            if (!valid.isEmpty()) {
                double sum = 0;
                max = valid.get(0);
                min = valid.get(0);
                for (Double v : valid) {
                    sum += v;
                    if (v > max) max = v;
                    if (v < min) min = v;
                }
                avg = sum / valid.size();
            }

            Double last = data.isEmpty() ? null : data.get(data.size() - 1);

            return DeviceFieldTrendDTO.builder()
                    .deviceCode(deviceCode)
                    .deviceName(device.getDesc())
                    .fieldName(fieldName)
                    // label/unit 目前后端没有统一来源，这里先留空，前端可用 fieldMeta 补齐
                    .fieldLabel(null)
                    .unit(null)
                    .categories(categories)
                    .data(data)
                    .avg(avg)
                    .max(max)
                    .min(min)
                    .last(last)
                    .build();

        } catch (Exception e) {
            log.error("获取设备字段趋势失败, deviceCode={}, fieldName={}, err={}", deviceCode, fieldName, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 构建设备图表数据
     */
    private DeviceChartDataDTO buildAllChartData() {
        try {
            // 1. 设备类型分布饼图
            DeviceChartDataDTO.PieChartData pieChartData = buildDeviceTypePieChart();

            // 2. 数据来源分布条形图
            DeviceChartDataDTO.BarChartData barChartData = buildSourceTypeBarChart();

            // 3. 同类型设备对比折线图（只对比单位相同的设备）
            DeviceChartDataDTO.LineChartData lineChartData = buildSameTypeDeviceCompareChart();

            // 4. 设备统计数据
            List<DeviceChartDataDTO.DeviceStatistics> statistics = buildDeviceStatistics();

            return DeviceChartDataDTO.builder()
                    .deviceTypePieChart(pieChartData)
                    .sourceTypeBarChart(barChartData)
                    .sameTypeDeviceCompareChart(lineChartData)
                    .deviceStatistics(statistics)
                    .build();
        } catch (Exception e) {
            log.error("构建图表数据失败: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 构建设备类型分布饼图数据
     */
    private DeviceChartDataDTO.PieChartData buildDeviceTypePieChart() {
        Map<String, Integer> distribution = new HashMap<>();
        distribution.put("入口段", 0);
        distribution.put("处理段", 0);
        distribution.put("出口段", 0);
        distribution.put("其他", 0);

        for (DeviceEnum device : DeviceEnum.values()) {
            String sectionType = device.getSectionType().name();
            if ("ENTRY".equals(sectionType)) {
                distribution.put("入口段", distribution.get("入口段") + 1);
            } else if ("PROCESS".equals(sectionType)) {
                distribution.put("处理段", distribution.get("处理段") + 1);
            } else if ("EXIT".equals(sectionType)) {
                distribution.put("出口段", distribution.get("出口段") + 1);
            } else {
                distribution.put("其他", distribution.get("其他") + 1);
            }
        }

        String[] colors = {"#0066cc", "#409eff", "#66b1ff", "#a0cfff"};
        List<DeviceChartDataDTO.PieSeries> series = new ArrayList<>();
        int colorIndex = 0;

        for (Map.Entry<String, Integer> entry : distribution.entrySet()) {
            if (entry.getValue() > 0) {
                series.add(DeviceChartDataDTO.PieSeries.builder()
                        .name(entry.getKey())
                        .data(entry.getValue().doubleValue())
                        .color(colors[colorIndex % colors.length])
                        .build());
                colorIndex++;
            }
        }

        return DeviceChartDataDTO.PieChartData.builder()
                .series(series)
                .build();
    }

    /**
     * 构建数据来源分布条形图数据
     */
    private DeviceChartDataDTO.BarChartData buildSourceTypeBarChart() {
        Map<String, Integer> distribution = new HashMap<>();
        distribution.put("ENTRY", 0);
        distribution.put("FURNACE", 0);
        distribution.put("COAT", 0);
        distribution.put("EXIT", 0);

        for (DeviceEnum device : DeviceEnum.values()) {
            String sourceType = device.getSourceType().name();
            if (distribution.containsKey(sourceType)) {
                distribution.put(sourceType, distribution.get(sourceType) + 1);
            }
        }

        List<String> categories = new ArrayList<>();
        List<Double> data = new ArrayList<>();

        for (Map.Entry<String, Integer> entry : distribution.entrySet()) {
            if (entry.getValue() > 0) {
                categories.add(entry.getKey());
                data.add(entry.getValue().doubleValue());
            }
        }

        return DeviceChartDataDTO.BarChartData.builder()
                .categories(categories)
                .series(Collections.singletonList(
                        DeviceChartDataDTO.BarSeries.builder()
                                .name("设备数量")
                                .data(data)
                                .build()
                ))
                .build();
    }

    /**
     * 构建同类型设备对比折线图数据（只对比单位相同的设备）
     */
    private DeviceChartDataDTO.LineChartData buildSameTypeDeviceCompareChart() {
        // 获取今天的数据
        LocalDate today = LocalDate.now();
        LocalDateTime startTime = today.atStartOfDay();
        LocalDateTime endTime = today.atTime(LocalTime.MAX);

        // 按数据来源分组，同一来源的设备单位相同，可以对比
        Map<String, List<DeviceEnum>> devicesBySource = new HashMap<>();
        for (DeviceEnum device : DeviceEnum.values()) {
            if (device.getParamFields() == null || device.getParamFields().isEmpty()) {
                continue;
            }
            String sourceType = device.getSourceType().name();
            devicesBySource.computeIfAbsent(sourceType, k -> new ArrayList<>()).add(device);
        }

        // 选择设备数量最多的数据源，取前5个设备进行对比
        String selectedSource = devicesBySource.entrySet().stream()
                .max(Map.Entry.comparingByValue((a, b) -> Integer.compare(a.size(), b.size())))
                .map(Map.Entry::getKey)
                .orElse(null);

        if (selectedSource == null || devicesBySource.get(selectedSource).isEmpty()) {
            return null;
        }

        List<DeviceEnum> selectedDevices = devicesBySource.get(selectedSource).stream()
                .limit(5)
                .collect(Collectors.toList());

        List<String> categories = new ArrayList<>();
        List<DeviceChartDataDTO.LineSeries> series = new ArrayList<>();

        // 生成时间轴（最近10个时间点，每10分钟一个）
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
        LocalDateTime now = LocalDateTime.now();
        for (int i = 9; i >= 0; i--) {
            LocalDateTime time = now.minusMinutes(i * 10L);
            categories.add(time.format(timeFormatter));
        }

        // 为每个设备生成数据系列
        for (DeviceEnum device : selectedDevices) {
            if (device.getParamFields() == null || device.getParamFields().isEmpty()) {
                continue;
            }

            // 获取该设备今天的历史数据
            LambdaQueryWrapper<DeviceSnapshot> qw = new LambdaQueryWrapper<DeviceSnapshot>()
                    .eq(DeviceSnapshot::getDeviceCode, device.name())
                    .between(DeviceSnapshot::getCreateTime, startTime, endTime)
                    .orderByAsc(DeviceSnapshot::getCreateTime);

            List<DeviceSnapshot> rows = deviceSnapshotMapper.selectList(qw);
            List<DeviceSnapshot> sampledRows = sampleDataByInterval(rows, 10);

            // 使用第一个字段的数据
            String firstField = device.getParamFields().get(0);
            List<Double> data = new ArrayList<>();

            // 填充数据（如果历史数据不足，用0填充）
            for (int i = 0; i < 10; i++) {
                if (i < sampledRows.size()) {
                    try {
                        Map<String, Object> jsonData = objectMapper.readValue(
                                sampledRows.get(i).getSnapshotData(), Map.class);
                        Object value = jsonData.get(firstField);
                        double numValue = 0.0;
                        if (value instanceof Number) {
                            numValue = ((Number) value).doubleValue();
                        }
                        data.add(numValue);
                    } catch (Exception e) {
                        data.add(0.0);
                    }
                } else {
                    data.add(0.0);
                }
            }

            series.add(DeviceChartDataDTO.LineSeries.builder()
                    .name(device.getDesc())
                    .data(data)
                    .build());
        }

        if (series.isEmpty()) {
            return null;
        }

        return DeviceChartDataDTO.LineChartData.builder()
                .categories(categories)
                .series(series)
                .build();
    }

    /**
     * 构建设备统计数据
     */
    private List<DeviceChartDataDTO.DeviceStatistics> buildDeviceStatistics() {
        List<DeviceChartDataDTO.DeviceStatistics> statistics = new ArrayList<>();
        LocalDate today = LocalDate.now();
        LocalDateTime startTime = today.atStartOfDay();
        LocalDateTime endTime = today.atTime(LocalTime.MAX);

        // 获取最新的测量数据
        AppMeasureEntryMessage entry = (AppMeasureEntryMessage) latestMeasurements.get(AppMeasureEntryMessage.class);
        AppMeasureFurnaceMessage furnace = (AppMeasureFurnaceMessage) latestMeasurements.get(AppMeasureFurnaceMessage.class);
        AppMeasureCoatMessage coat = (AppMeasureCoatMessage) latestMeasurements.get(AppMeasureCoatMessage.class);
        AppMeasureExitMessage exit = (AppMeasureExitMessage) latestMeasurements.get(AppMeasureExitMessage.class);

        for (DeviceEnum device : DeviceEnum.values()) {
            if (device.getParamFields() == null || device.getParamFields().isEmpty()) {
                continue;
            }

            String firstField = device.getParamFields().get(0);

            // 获取当前值
            double currentValue = 0.0;
            switch (device.getSourceType()) {
                case ENTRY:
                    if (entry != null) {
                        currentValue = getFieldValue(entry, firstField);
                    }
                    break;
                case FURNACE:
                    if (furnace != null) {
                        currentValue = getFieldValue(furnace, firstField);
                    }
                    break;
                case COAT:
                    if (coat != null) {
                        currentValue = getFieldValue(coat, firstField);
                    }
                    break;
                case EXIT:
                    if (exit != null) {
                        currentValue = getFieldValue(exit, firstField);
                    }
                    break;
            }

            // 从历史数据中计算统计值
            LambdaQueryWrapper<DeviceSnapshot> qw = new LambdaQueryWrapper<DeviceSnapshot>()
                    .eq(DeviceSnapshot::getDeviceCode, device.name())
                    .between(DeviceSnapshot::getCreateTime, startTime, endTime)
                    .orderByAsc(DeviceSnapshot::getCreateTime);

            List<DeviceSnapshot> rows = deviceSnapshotMapper.selectList(qw);
            List<Double> values = new ArrayList<>();

            for (DeviceSnapshot snapshot : rows) {
                try {
                    Map<String, Object> jsonData = objectMapper.readValue(
                            snapshot.getSnapshotData(), Map.class);
                    Object value = jsonData.get(firstField);
                    if (value instanceof Number) {
                        double numValue = ((Number) value).doubleValue();
                        if (numValue > 0) {
                            values.add(numValue);
                        }
                    }
                } catch (Exception e) {
                    // ignore
                }
            }

            String avg = "—";
            String max = "—";
            String min = "—";

            if (!values.isEmpty()) {
                double avgValue = values.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
                double maxValue = values.stream().mapToDouble(Double::doubleValue).max().orElse(0.0);
                double minValue = values.stream().mapToDouble(Double::doubleValue).min().orElse(0.0);

                avg = String.format("%.2f", avgValue);
                max = String.format("%.2f", maxValue);
                min = String.format("%.2f", minValue);
            }

            statistics.add(DeviceChartDataDTO.DeviceStatistics.builder()
                    .deviceCode(device.name())
                    .deviceName(device.getDesc())
                    .avg(avg)
                    .max(max)
                    .min(min)
                    .current(currentValue > 0 ? String.format("%.2f", currentValue) : "—")
                    .build());
        }

        return statistics;
    }

    /**
     * 获取字段值
     */
    private double getFieldValue(Object message, String fieldName) {
        try {
            java.lang.reflect.Field field = message.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            Object value = field.get(message);
            if (value instanceof Number) {
                return ((Number) value).doubleValue();
            }
        } catch (Exception e) {
            // ignore
        }
        return 0.0;
    }

    /**
     * 获取设备今天一天的历史趋势数据（10分钟间隔采样）
     * @param deviceCode 设备代码
     * @return 历史趋势数据
     */
    public DeviceHistoryTrendDTO getDeviceHistoryTrend(String deviceCode) {
        try {
            // 获取今天开始和结束时间
            LocalDate today = LocalDate.now();
            LocalDateTime startTime = today.atStartOfDay();
            LocalDateTime endTime = today.atTime(LocalTime.MAX);

            // 查询今天的所有快照数据
            LambdaQueryWrapper<DeviceSnapshot> qw = new LambdaQueryWrapper<DeviceSnapshot>()
                    .eq(DeviceSnapshot::getDeviceCode, deviceCode)
                    .between(DeviceSnapshot::getCreateTime, startTime, endTime)
                    .orderByAsc(DeviceSnapshot::getCreateTime);

            List<DeviceSnapshot> rows = deviceSnapshotMapper.selectList(qw);
            if (rows == null || rows.isEmpty()) {
                return null;
            }

            // 按10分钟间隔采样数据
            List<DeviceSnapshot> sampledRows = sampleDataByInterval(rows, 10);

            // 获取设备信息
            DeviceEnum device = DeviceEnum.valueOf(deviceCode);
            if (device == null) {
                return null;
            }

            // 构建历史趋势数据
            List<String> categories = new ArrayList<>();
            Map<String, List<Double>> seriesMap = new HashMap<>();
            List<String> fields = device.getParamFields();

            if (fields == null || fields.isEmpty()) {
                return null;
            }

            // 初始化系列数据
            for (String field : fields) {
                seriesMap.put(field, new ArrayList<>());
            }

            // 处理采样后的数据
            DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
            for (DeviceSnapshot snapshot : sampledRows) {
                categories.add(snapshot.getCreateTime().format(timeFormatter));

                Map<String, Object> jsonData = new HashMap<>();
                try {
                    jsonData = objectMapper.readValue(snapshot.getSnapshotData(), Map.class);
                } catch (Exception e) {
                    log.warn("解析快照数据失败: {}", snapshot.getSnapshotData());
                }

                for (String field : fields) {
                    Object value = jsonData.get(field);
                    double numValue = 0.0;
                    if (value instanceof Number) {
                        numValue = ((Number) value).doubleValue();
                    }
                    seriesMap.get(field).add(numValue);
                }
            }

            // 构建系列数据（最多6个字段）
            List<DeviceHistoryTrendDTO.SeriesData> series = fields.stream()
                    .limit(6)
                    .map(field -> DeviceHistoryTrendDTO.SeriesData.builder()
                            .fieldName(field)
                            .name(field) // 前端可以根据字段元数据替换为标签
                            .data(seriesMap.get(field))
                            .build())
                    .collect(Collectors.toList());

            return DeviceHistoryTrendDTO.builder()
                    .deviceCode(deviceCode)
                    .deviceName(device.getDesc())
                    .categories(categories)
                    .series(series)
                    .build();

        } catch (Exception e) {
            log.error("获取设备[{}]历史趋势数据失败: {}", deviceCode, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 按时间间隔采样数据（每N分钟取一条）
     * @param rows 原始数据列表
     * @param intervalMinutes 间隔分钟数
     * @return 采样后的数据列表
     */
    private List<DeviceSnapshot> sampleDataByInterval(List<DeviceSnapshot> rows, int intervalMinutes) {
        if (rows == null || rows.isEmpty()) {
            return new ArrayList<>();
        }

        List<DeviceSnapshot> sampled = new ArrayList<>();
        LocalDateTime lastTime = null;

        for (DeviceSnapshot row : rows) {
            LocalDateTime rowTime = row.getCreateTime();

            if (lastTime == null) {
                // 第一条数据
                sampled.add(row);
                lastTime = rowTime;
            } else {
                // 计算时间差（分钟）
                long diffMinutes = java.time.Duration.between(lastTime, rowTime).toMinutes();

                // 如果时间差大于等于间隔，则采样这条数据
                if (diffMinutes >= intervalMinutes) {
                    sampled.add(row);
                    lastTime = rowTime;
                }
            }
        }

        return sampled;
    }

    /**
     * 创建设备快照
     */
    private DeviceSnapshot createDeviceSnapshot(DeviceEnum device, LocalDateTime timestamp,
                                              AppMeasureEntryMessage entry,
                                              AppMeasureFurnaceMessage furnace,
                                              AppMeasureCoatMessage coat,
                                              AppMeasureExitMessage exit) {
        try {
            // 创建快照对象
            DeviceSnapshot snapshot = new DeviceSnapshot();
            snapshot.setCreateTime(timestamp);
            snapshot.setDeviceId(device.getIdx());
            snapshot.setDeviceCode(device.name());
            snapshot.setDeviceName(device.getDesc());
            snapshot.setSectionType(device.getSectionType().name());
            snapshot.setSourceType(device.getSourceType().name());

            List<String> paramFields = device.getParamFields();
            log.debug("设备[{}]参数字段列表: {}", device.name(), paramFields);

            // 根据设备类型获取对应的测量数据
            ObjectNode dataNode = objectMapper.createObjectNode();
            switch (device.getSourceType()) {
                case ENTRY:
                    if (entry != null) {
                        extractData(entry, paramFields, dataNode);
                        log.debug("设备[{}]从ENTRY提取数据，dataNode大小: {}", device.name(), dataNode.size());
                    } else {
                        log.debug("设备[{}]需要ENTRY数据，但entry为null", device.name());
                    }
                    break;
                case FURNACE:
                    if (furnace != null) {
                        extractData(furnace, paramFields, dataNode);
                        log.debug("设备[{}]从FURNACE提取数据，dataNode大小: {}", device.name(), dataNode.size());
                    } else {
                        log.debug("设备[{}]需要FURNACE数据，但furnace为null", device.name());
                    }
                    break;
                case COAT:
                    if (coat != null) {
                        extractData(coat, paramFields, dataNode);
                        log.debug("设备[{}]从COAT提取数据，dataNode大小: {}", device.name(), dataNode.size());
                    } else {
                        log.debug("设备[{}]需要COAT数据，但coat为null", device.name());
                    }
                    break;
                case EXIT:
                    if (exit != null) {
                        extractData(exit, paramFields, dataNode);
                        log.debug("设备[{}]从EXIT提取数据，dataNode大小: {}", device.name(), dataNode.size());
                    } else {
                        log.debug("设备[{}]需要EXIT数据，但exit为null", device.name());
                    }
                    break;
            }

            // 如果没有数据，则跳过
            if (dataNode.isEmpty()) {
                log.debug("设备[{}]快照数据为空，跳过快照创建", device.name());
                return null;
            }

            // 设置快照数据
            snapshot.setSnapshotData(dataNode.toString());
            log.debug("设备[{}]快照创建成功，数据长度: {}", device.name(), dataNode.toString().length());
            return snapshot;
        } catch (Exception e) {
            log.error("创建设备[{}]快照时发生错误: {}", device.name(), e.getMessage(), e);
            return null;
        }
    }

    /**
     * 从消息对象中提取指定字段的数据
     */
    private void extractData(Object message, List<String> fields, ObjectNode dataNode) {
        if (message == null || fields == null || fields.isEmpty()) {
            log.debug("extractData参数无效: message={}, fields={}",
                    message != null ? message.getClass().getSimpleName() : "null",
                    fields != null ? fields.size() : "null");
            return;
        }

        int extractedCount = 0;
        try {
            for (String field : fields) {
                try {
                    // 使用反射获取字段值
                    java.lang.reflect.Field declaredField = message.getClass().getDeclaredField(field);
                    declaredField.setAccessible(true);
                    Object value = declaredField.get(message);

                    // 处理不同类型的值
                    if (value != null) {
                        if (value instanceof Integer) {
                            dataNode.put(field, (Integer) value);
                            extractedCount++;
                        } else if (value instanceof Long) {
                            dataNode.put(field, (Long) value);
                            extractedCount++;
                        } else if (value instanceof Float) {
                            dataNode.put(field, (Float) value);
                            extractedCount++;
                        } else if (value instanceof Double) {
                            dataNode.put(field, (Double) value);
                            extractedCount++;
                        } else if (value instanceof Boolean) {
                            dataNode.put(field, (Boolean) value);
                            extractedCount++;
                        } else if (value instanceof String) {
                            dataNode.put(field, (String) value);
                            extractedCount++;
                        } else if (value instanceof Enum) {
                            dataNode.put(field, value.toString());
                            extractedCount++;
                        } else if (value instanceof java.math.BigDecimal) {
                            // 处理BigDecimal类型（很多测量字段是BigDecimal）
                            dataNode.put(field, ((java.math.BigDecimal) value).doubleValue());
                            extractedCount++;
                        } else {
                            log.debug("字段[{}]类型[{}]未处理，值: {}", field, value.getClass().getSimpleName(), value);
                        }
                    } else {
                        log.trace("字段[{}]值为null", field);
                    }
                } catch (NoSuchFieldException e) {
                    log.trace("字段[{}]在消息[{}]中不存在", field, message.getClass().getSimpleName());
                } catch (Exception e) {
                    log.warn("获取字段[{}]值失败: {}", field, e.getMessage());
                }
            }
            log.debug("从[{}]提取了{}个字段，共{}个字段",
                    message.getClass().getSimpleName(), extractedCount, fields.size());
        } catch (Exception e) {
            log.error("提取数据时发生错误: {}", e.getMessage(), e);
        }
    }
}
