<template>
  <div class="realtimeCurve-content">
    <div v-loading="loading" class="echarts-content">
      <div ref="chartRef" class="echarts-container" :style="{ height: height }"></div>
      <div v-if="allData.length === 0" class="el-table-empty">
        <el-image :src="emptybg"></el-image>
        <span>当前无数据</span>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted, nextTick } from 'vue';
import * as echarts from 'echarts';
import emptybgUrl from '@/assets/images/empty-bg.png';
import type { ECharts, EChartsOption } from 'echarts';
import BizVarDictAPI, { BizVarDictTable, BizVarDictPageQuery } from '@/api/module_business/vardict';
import MqttUtil, { MqttMessageCallback } from '@/utils/mqttUtil';
const emptybg = ref(emptybgUrl)

// 起重机信息
const craneInfo = JSON.parse(localStorage.getItem('craneInfo') || '{}');
const loading = ref(true);
const height = ref('0px');

// 查询参数
const queryFormVarDictData = reactive<BizVarDictPageQuery>({
  page_no: 0,
  page_size: 0,
  crane_no: craneInfo.crane_no,
  var_code: undefined,
  var_name: undefined,
  mec_type: undefined,
  switch_type: undefined,
  gateway_id: undefined,
  var_group: undefined,
  var_category: undefined,
  is_top_show: undefined,
  is_save: undefined,
  is_overview_top_show: undefined,
  is_home_page_show: undefined,
  status: undefined,
  created_time: undefined,
  updated_time: undefined,
  created_id: undefined,
  updated_id: undefined,
});

// MQTT配置
const mqttConfig = {
  wsUrl: import.meta.env.VITE_APP_WS_ENDPOINT || 'ws://127.0.0.1:9001',
  topics: ['cdc/' + craneInfo.crane_no + '/analog/batch/#'],
};
const mqttUtil = new MqttUtil(mqttConfig);

// 变量数据存储
const allData = ref<BizVarDictTable[]>([]);

// ========== ECharts核心配置 ==========
const chartRef = ref<HTMLDivElement | null>(null);
let chartInstance: ECharts | null = null;
const MAX_DATA_POINTS = 100; // 单条曲线最大数据点
const gridHeight = 150; // 每组Grid高度（px）
const gridGap = 50; // 组间间距，保持宽松不拥挤
const gridTopBase = 80; // 增大顶部基础间距，避免图例遮挡第一组


// 单条曲线数据结构：[时间戳, 值]
interface SeriesDataItem {
  name: string; // 变量名（var_name）
  code: string; // 变量编码
  data: [number, number][]; // 时间戳+值
}
const seriesData = ref<SeriesDataItem[]>([]);

// ========== 数据加载 ==========
const getData = async () => {
  const response = await BizVarDictAPI.listBizVarDictAnalog(queryFormVarDictData);
  allData.value = response.data.data || [];
  if (allData.value.length === 0) {
    loading.value = false;
  }
  // 初始化多grid+多曲线
  initMultiGridSeries();
};

// ========== 多Grid+多曲线初始化 ==========
const initMultiGridSeries = () => {
  if (allData.value.length === 0) {
    console.warn('无变量数据，无法生成曲线');
    return;
  }

  // 为每个变量初始化曲线数据（初始值+当前时间戳）
  seriesData.value = allData.value.map(item => ({
    name: item.var_name || '未知变量',
    code: item.var_code || '',
    data: [], // 初始数据点
  }));
  // 确保动态高度赋值完成，DOM渲染就绪后再初始化ECharts
  nextTick(() => {
    initEchartsWithMultiGrid();
  });
};

// ========== 多Grid布局的ECharts初始化 ==========
const initEchartsWithMultiGrid = () => {
  if (!chartRef.value || !seriesData.value.length) return;

  // 创建ECharts实例
  chartInstance = echarts.init(chartRef.value);

  // 计算每个Grid的尺寸：核心优化确保任意数量数据完整显示
  const gridCount = seriesData.value.length; // 取allData实际数量（十几条也支持）

  // 动态计算高度：根据allData数量计算总高度，赋值给height ref
  const totalChartHeight = gridTopBase + gridCount * (gridHeight + gridGap);
  height.value = `${totalChartHeight}px`; // 绑定到容器style的height属性

  // 1. 构建多Grid配置
  const grids = seriesData.value.map((_, index) => ({
    id: `grid_${index}`,
    left: '2%', // 【修改2】Grid左间距设为0，消除视觉上的左侧空白
    right: '4%', // 【修改2】Grid右间距设为0，消除视觉上的右侧空白
    top: gridTopBase + index * (gridHeight + gridGap),
    height: gridHeight,
    width: '94%', // 【修改2】Grid宽度设为100%，填满容器
    containLabel: true,
    padding: [10, 20, 20, 20], // 微调内边距，避免标签溢出
    show: true
  }));

  // 2. 构建多X轴配置（统一时间范围 + 保留白色大字体 + 仅保留横线（竖线关闭））
  const xAxes: any[] = seriesData.value.map((_, index) => ({
    gridIndex: index,
    type: 'time',
    show: true,
    axisLabel: {
      formatter: (value: number) => new Date(value).toLocaleTimeString(),
      fontSize: 14,
      color: '#506388',
      margin: 10
    },
    // 关闭X轴分割线，避免视觉干扰
    splitLine: { show: false },
    // 强制X轴刻度对齐
    alignTicks: true
  }));

  // 3. 构建多Y轴配置（保留白色大字体 + 恢复灰色细横线（仅横线））
  const yAxes: any[] = seriesData.value.map((item, index) => ({
    gridIndex: index,
    type: 'value',
    show: true,
    name: item.name,
    nameTextStyle: {
      fontSize: 14, // 字号稍大
      color: '#fff' // y轴名称白色字体
    },
    nameGap: 20,
    axisLabel: {
      formatter: (value: any) => `{fixedWidth|${value}}`, // 用rich样式包裹
      rich: {
        fixedWidth: {
          width: 80,
          textAlign: 'right', // 文本右对齐
          backgroundColor: 'transparent', // 透明背景
          fontSize: 14,
        }
      },
      color: '#506388',
      margin: 20,
      overflow: 'hidden',
      textOverflow: 'ellipsis'
    },
    // 水平网格线
    splitLine: {
      show: true, // 开启水平网格线（横线）
      lineStyle: {
        color: '#3E5487', // 灰色（与深色背景协调）
        width: 1 // 柔和不突兀，避免太扎眼
      }
    },
    position: 'left' // 恢复y轴左侧布局
  }));

  // 4. 构建多Series配置（确保曲线颜色和图例颜色对照，支持任意数据量）
  const series: any[] = seriesData.value.map((item, index) => {
    const curveColor = getColor(index); // 调用优化后的颜色函数，支持任意index
    return {
      name: item.name,
      type: 'line',
      smooth: true,
      symbol: 'none',
      gridIndex: index,
      xAxisIndex: index,
      yAxisIndex: index,
      data: item.data,
      color: curveColor, // 明确设置series颜色（图例将自动取该颜色）
      lineStyle: { color: curveColor, width: 2 }, // 曲线颜色与series颜色一致
      itemStyle: { color: curveColor }, // 图例标记颜色与曲线一致
      areaStyle: {
        // 优化面积图颜色，增加渐变和透明度，适配动态颜色
        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
          { offset: 0, color: curveColor + 'cc' }, // 顶部半透明
          { offset: 1, color: curveColor + '11' }  // 底部几乎透明
        ])
      }
    };
  });

  // ECharts最终配置
  const option: EChartsOption = {
    // 【核心配置1】全局开启刻度对齐
    alignTicks: true,
    // 图例配置（确保与曲线颜色对照，支持任意数据量）
    legend: {
      show: true,
      top: 20,
      left: 'center',
      data: seriesData.value.map(item => item.name),
      textStyle: {
        fontSize: 14,
        color: '#fff' // 图例文字白色字体
      },
      itemWidth: 12,
      itemHeight: 12,
      padding: [0, 20],
      formatter: (name) => {
        return name.length > 10 ? name.substring(0, 10) + '...' : name;
      }
    },
    // Tooltip配置
    tooltip: {
      trigger: 'axis',
      triggerOn: 'mousemove',
      formatter: function (params: any) {
        if (!params || params.length === 0) return '';

        const targetTime = params[0].data[0];
        const timeStr = new Date(targetTime).toLocaleTimeString();
        let tooltipHtml = `<div style="font-weight: bold; margin-bottom: 8px;font-size: 12px">时间：${timeStr}</div>`;

        seriesData.value.forEach((seriesItem, idx) => {
          const closestData = seriesItem.data.find(d => d[0] === targetTime);
          const value = closestData ? closestData[1] : '-';
          tooltipHtml += `
            <div style="display: flex; align-items: center; margin: 4px 0;">
              <span style="display: inline-block; width: 8px; height: 8px; background: ${getColor(idx)}; margin-right: 8px; border-radius: 50%;"></span>
              <span style="font-size: 12px" >${seriesItem.name}：</span>
              <span style="margin-left: 8px;font-size: 12px">${value}</span>
            </div>
          `;
        });
        return tooltipHtml;
      },
      backgroundColor: 'rgba(255,255,255,0.95)',
      borderColor: '#e6e6e6',
      borderWidth: 1,
      padding: 12,
      textStyle: { fontSize: 12 },
    },
    height: totalChartHeight,
    grid: grids,
    xAxis: xAxes,
    yAxis: yAxes,
    series: series,
  };

  chartInstance.setOption(option);

  // 【监听图例勾选变化事件】
  chartInstance.off('legendselectchanged');
  chartInstance.on('legendselectchanged', (params: any) => {
    if (!params || !params.selected) {
      console.warn('无有效勾选状态数据');
      return;
    }

    const selectedLegend = params.selected;

    // 【核心步骤1：筛选出「显示状态」的图例名称和对应的索引】
    const showSeriesNames = Object.entries(selectedLegend)
      .filter(([_, isSelected]) => isSelected)
      .map(([name]) => name);
    // 得到显示的索引数组（按原有顺序排列）
    const showIndices = seriesData.value
      .map((item, index) => ({ name: item.name, index }))
      .filter((item) => showSeriesNames.includes(item.name))
      .map((item) => item.index);

    // 【核心步骤2：遍历所有grid，更新show属性 + 重新计算显示grid的top值】
    const updatedGrids = grids.map((grid, index) => {
      const seriesName = seriesData.value[index].name;
      const isShow = selectedLegend[seriesName] || false;

      if (!isShow) {
        // 隐藏的grid：仅设置show: false，保持其他属性不变
        return { ...grid, show: false };
      } else {
        // 显示的grid：找到它在「显示数组」中的排序，重新计算top值
        const showSortIndex = showIndices.findIndex(showIndex => showIndex === index);
        const newTop = gridTopBase + showSortIndex * (gridHeight + gridGap);
        return { ...grid, show: true, top: newTop }; // 应用新的top值，实现紧凑排列
      }
    });

    // 【原有逻辑：更新xAxis/yAxis的show属性 + 同步X轴范围】
    const updatedXAxes = xAxes.map((xAxis, index) => {
      const seriesName = seriesData.value[index].name;
      return {
        ...xAxis,
        show: selectedLegend[seriesName] || false,
        axisLine: { onZero: false },
        scale: false
      };
    });

    const updatedYAxes = yAxes.map((yAxis, index) => {
      const seriesName = seriesData.value[index].name;
      return { ...yAxis, show: selectedLegend[seriesName] || false };
    });

    // 【原有逻辑：重新计算图表总高度】
    const showGridCount = showIndices.length;
    const newTotalChartHeight = gridTopBase + showGridCount * (gridHeight + gridGap);
    height.value = `${newTotalChartHeight}px`;

    // 【核心步骤3：更新ECharts配置，应用新的grid位置和尺寸】
    chartInstance?.setOption({
      grid: updatedGrids,
      xAxis: updatedXAxes,
      yAxis: updatedYAxes,
      height: newTotalChartHeight
    });

    // 【原有逻辑：重新调整图表尺寸】
    chartInstance?.resize({
      width: 'auto', // 精准获取容器实际宽度
      height: newTotalChartHeight
    });
  });

  // 初始化后主动调用resize，强制适配容器尺寸，解决不显示问题
  chartInstance.resize({
    width: 'auto',
    height: totalChartHeight,
  });

  // 窗口自适应 + 滚动容器适配
  const resizeHandler = () => {
    if (chartInstance) {
      chartInstance.resize({
        width: 'auto',
        height: 'auto',
      });
    }
  };
  window.addEventListener('resize', resizeHandler);
};

// ========== MQTT回调（实时更新多Grid曲线） ==========
const handleMqttMessage: MqttMessageCallback = (topic, payload) => {
  if (!payload?.data) return;

  // 遍历MQTT数据，更新对应变量的曲线
  payload.data.forEach((payloadItem: any) => {
    if (!payloadItem.var_code) return;

    // 找到对应变量的曲线数据
    const targetSeries = seriesData.value.find(item => item.code === payloadItem.var_code);
    if (targetSeries) {
      // 添加新数据点（当前时间戳 + 最新值）
      targetSeries.data.push([payload.timestamp, payloadItem.value]);
      // 超出最大数据点时，删除最早的点
      if (targetSeries.data.length > MAX_DATA_POINTS) {
        targetSeries.data.shift();
      }
    }
  });
  // 实时更新图表
  updateEcharts();
  loading.value = false;
};

// ========== 图表更新方法（同步X轴范围） ==========
const updateEcharts = () => {
  if (!chartInstance || !seriesData.value.length) return;

  // 1. 更新所有X轴的时间范围（同步无留白配置）
  const updatedXAxes = seriesData.value.map((_, index) => ({
    gridIndex: index,
    axisLine: { onZero: false },
    scale: false
  }));

  // 2. 更新series数据（避免重复渲染grid/x/y轴）
  const updatedSeries = seriesData.value.map((item, index) => {
    const curveColor = getColor(index);
    return {
      gridIndex: index,
      xAxisIndex: index,
      yAxisIndex: index,
      data: item.data,
      color: curveColor, // 保持更新时颜色一致
      lineStyle: { color: curveColor, width: 2 },
      areaStyle: {
        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
          { offset: 0, color: curveColor + 'cc' },
          { offset: 1, color: curveColor + '11' }
        ])
      }
    };
  });

  // 3. 应用更新（先更X轴范围，再更数据，确保对齐）
  chartInstance.setOption({
    xAxis: updatedXAxes,
    series: updatedSeries
  });
};

// ========== 优化：支持任意数量数据的颜色生成函数（不再写死） ==========
/**
 * 生成区分度高的颜色，支持任意数量的索引（十几条、几十条都支持）
 */
const getColor = (index: number) => {
  const extendedColors = [
    '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FECA57',
    '#FF9FF3', '#54A0FF', '#8E44AD', '#E74C3C', '#3498DB',
    '#2ECC71', '#F1C40F', '#9B59B6', '#1ABC9C', '#E67E22',
    '#34495E', '#FF7675', '#74B9FF', '#00B894', '#FDCB6E'
  ];
  return extendedColors[index % extendedColors.length];
};

onMounted(async () => {
  await getData();
  mqttUtil.initConnect(handleMqttMessage);
});

onUnmounted(() => {
  // 销毁ECharts实例
  if (chartInstance) {
    chartInstance.dispose();
    chartInstance = null;
  }
  // 释放MQTT资源
  mqttUtil.releaseResources();
  // 移除resize监听
  window.removeEventListener('resize', () => chartInstance?.resize());
});
</script>

<style lang="less" scoped>
.realtimeCurve-content {
  :deep(.el-loading-parent--relative) {
    --el-mask-color: rgba(255, 255, 255, 0.1);
  }
}

.echarts-content {
  width: 100%;
  height: 100%;
  overflow-x: hidden;
  background: linear-gradient(to bottom, rgba(20, 66, 140, 0.8) 0%, rgba(18, 31, 52, 1) 15%);
}

// ECharts容器：适配动态高度
.echarts-container {
  width: 100%;
  // 高度由动态计算的height ref决定，无需额外设置
}

.el-table-empty {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: #8ECAFF;

  img {
    width: 200px;
    height: auto;
    margin-bottom: 20px;
  }
}

::-webkit-scrollbar {
  width: 5px;
  height: 5px;
}

::-webkit-scrollbar-track {
  border-radius: 10px;
}

::-webkit-scrollbar-thumb {
  border-radius: 7px;
  background-color: #798DAE;
}
</style>