import React from 'react';
import { useEffect, useRef, useState, useCallback, useImperativeHandle, forwardRef } from 'react';

// 直接声明全局 lcjs 变量（已确认依赖已引入，无需再关联 arctionJS）
declare const lcjs: any;

// 定义组件 Props 类型
export interface WaterFallChartProps {
  texts?: {
    title?: string;
    unit?: string;
  };
  btns?: string[];
  className?: string;
  style?: React.CSSProperties;
  defaultPeriod?: number;
  defaultResolution?: number;
  fftPointNumber?: number;
  xAxisRange: { start: number; end: number };
  powerMin?: number;
  powerMax?: number;
  colorConfig: {
    gain: number;
  };
}

// 定义组件暴露的实例方法类型（核心：明确对外暴露的方法）
export interface WaterFallChartInstance {
  addData: (data: any[]) => void;
  togglePause: () => void;
  reset: () => void;
}

// 核心：移除 RenderWorker 类（不再需要定时轮询渲染）

// 核心：使用 forwardRef 包裹组件，支持暴露实例方法
const WaterFallChart = forwardRef<WaterFallChartInstance, WaterFallChartProps>((props, ref) => {
  // 解构 props
  const {
    texts = {},
    btns = [],
    className = '',
    style = {},
    defaultPeriod = 100,
    fftPointNumber = 1024, // 默认 FFT 点数
    xAxisRange = { start: 0, end: 30000000 },
    powerMin=-160,
    powerMax=20,
    colorConfig= { gain: 20 }
  } = props;

  // 容器 Ref（用于挂载 LightningChart）
  const containerRef = useRef<HTMLDivElement>(null);
  // 图表实例 Ref（保存全局上下文，防止重复创建）
  const chartRef = useRef<any>(null);
  // 暂停状态（React 状态管理）
  const [paused, setPaused] = useState(false);
  const powerExtremesRef = useRef({
    min: -95, // 初始默认最小值（匹配原有 setColorStyle 默认值，无数据时兜底）
    max: 0,   // 初始默认最大值（匹配原有 setColorStyle 默认值，无数据时兜底）
    hasValidData: false, // 标记是否已有有效数据（区分默认值和实际数据值）
  });

  // 常量定义
  const RANGE_TIME_MS = 10 * 1000;
  const DefaultAxisYThickness = 45;
  const MAX_CACHE_LENGTH = 500; // 缓存最大长度限制
  const BUFFER_LENGTH = 450;

  // 颜色数组
  const defaultColorsArray = (() => {
    const colors = "#000000,#000008,#000010,#000018,#000020,#000029,#000031,#000039,#000041,#00004a,#000052,#00005a,#000062,#00006a,#000073,#00007b,#000083,#00008b,#000094,#00009c,#0000a4,#0000ac,#0000b4,#0000bd,#0000c5,#0000cd,#0000d5,#0000de,#0000e6,#0000ee,#0000f6,#0000ff,#0000ff,#0006ff,#000dff,#0013ff,#001aff,#0020ff,#0027ff,#002dff,#0034ff,#003aff,#0041ff,#0047ff,#004eff,#0055ff,#005bff,#0062ff,#0068ff,#006fff,#0075ff,#007cff,#0082ff,#0089ff,#008fff,#0096ff,#009cff,#00a3ff,#00aaff,#00b0ff,#00b7ff,#00bdff,#00c4ff,#00caff,#00d1ff,#00d7ff,#00deff,#00e4ff,#00ebff,#00f1ff,#00f8ff,#00ffff,#00ffff,#00fff3,#00ffe8,#00ffdd,#00ffd2,#00ffc7,#00ffbc,#00ffb1,#00ffa6,#00ff9b,#00ff90,#00ff85,#00ff79,#00ff6e,#00ff63,#00ff58,#00ff4d,#00ff42,#00ff37,#00ff2c,#00ff21,#00ff16,#00ff0b,#00ff00,#00ff00,#0dff00,#1aff00,#28ff00,#35ff00,#43ff00,#50ff00,#5dff00,#6bff00,#78ff00,#86ff00,#93ff00,#a1ff00,#aeff00,#bbff00,#c9ff00,#d6ff00,#e4ff00,#f1ff00,#ffff00,#ffff00,#fffb00,#fff700,#fff300,#ffef00,#ffeb00,#ffe800,#ffe400,#ffe000,#ffdc00,#ffd800,#ffd500,#ffd100,#ffcd00,#ffc900,#ffc500,#ffc200,#ffbe00,#ffba00,#ffb600,#ffb200,#ffaf00,#ffab00,#ffa700,#ffa300,#ff9f00,#ff9c00,#ff9800,#ff9400,#ff9000,#ff8c00,#ff8900,#ff8500,#ff8100,#ff7d00,#ff7900,#ff7500,#ff7200,#ff6e00,#ff6a00,#ff6600,#ff6200,#ff5f00,#ff5b00,#ff5700,#ff5300,#ff4f00,#ff4c00,#ff4800,#ff4400,#ff4000,#ff3c00,#ff3900,#ff3500,#ff3100,#ff2d00,#ff2900,#ff2600,#ff2200,#ff1e00,#ff1a00,#ff1600,#ff1300,#ff0f00,#ff0b00,#ff0700,#ff0300,#ff0000,#ff0000,#ff0001,#ff0003,#ff0005,#ff0007,#ff0009,#ff000a,#ff000c,#ff000e,#ff0010,#ff0012,#ff0014,#ff0015,#ff0017,#ff0019,#ff001b,#ff001d,#ff001f,#ff0020,#ff0022,#ff0024,#ff0026,#ff0028,#ff002a,#ff002b,#ff002d,#ff002f,#ff0031,#ff0033,#ff0035,#ff0036,#ff0038,#ff003a,#ff003c,#ff003e,#ff0040,#ff0041,#ff0043,#ff0045,#ff0047,#ff0049,#ff004a,#ff004c,#ff004e,#ff0050,#ff0052,#ff0054,#ff0055,#ff0057,#ff0059,#ff005b,#ff005d,#ff005f,#ff0060,#ff0062,#ff0064,#ff0066,#ff0068,#ff006a,#ff006b,#ff006d,#ff006f,#ff0071,#ff0073,#ff0075,#ff0076,#ff0078,#ff007a,#ff007c,#ff007e,#ff0080,#ff0081"
      .split(",")
      .filter(color => color && /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.test(color))
      .filter((value, index, self) => self.indexOf(value) === index);

    if (colors.length < 256) {
      const fillCount = 256 - colors.length;
      const lastColor = colors[colors.length - 1] || "#ff0000";
      for (let i = 0; i < fillCount; i++) {
        colors.push(lastColor);
      }
    }
    return colors;
  })();
  const DEFAULT_COLORS = useRef<string[]>(defaultColorsArray).current;

  // 图表上下文（移除 updater 定时相关，保留必要缓存）
  const chartContext = useRef({
    period: defaultPeriod,
    last: [] as any[],
    cache: [] as any[][],
    resolution: fftPointNumber || 1920,
    series: null as any, // 热力图系列实例
    updater: { last: 0, timeout: 250 } as { last: number; timeout: number } | null, // 添加 updater 属性
  });

  // 辅助函数：提取单个数据批次中的有效功率极值
  const extractBatchPowerExtremes = useCallback((dataBatch: any[]) => {
    const validPowerPoints = dataBatch.flat().filter((item: any) => {
      return typeof item === 'number' && !isNaN(item) && isFinite(item);
    });
    if (validPowerPoints.length === 0) {
      return null;
    }
    const batchMin = Math.min(...validPowerPoints);
    const batchMax = Math.max(...validPowerPoints);
    return { min: batchMin, max: batchMax };
  }, []);

  // 数据平铺适配函数
  const spreadData = useCallback((source: any[]) => {
    const targetLength = fftPointNumber;
    const { min: powerMin, max: powerMax } = powerExtremesRef.current;
    if (source.length === 0) {
      return [Array(targetLength).fill(powerMin)];
    }
    const validSource = source[0].map(item => Math.max(powerMin, Math.min(powerMax, item ?? powerMin)));
    const targetRow: number[] = [];
    const freqInterval = 30000000;

    for (let i = 0; i < targetLength; i++) {
      const freq = 0 + (i / targetLength) * freqInterval;
      const freqRatio = (freq - 0) / freqInterval;
      const sourceIndex = Math.floor(freqRatio * validSource.length);
      const safeSourceIndex = Math.min(Math.max(sourceIndex, 0), validSource.length - 1);
      targetRow.push(validSource[safeSourceIndex]);
    }
    return [targetRow];
  }, [fftPointNumber]);

  // 颜色样式配置函数
  const setColorStyle1 = useCallback(() => {
    const ctx = chartContext.current;
    const globalExtremes = powerExtremesRef.current;
    if (!ctx.series || !lcjs) {
      console.error("热力图系列未初始化，无法配置颜色样式");
      return;
    }
    const { ColorCSS, LUT, PalettedFill } = lcjs;
    const powerMin = globalExtremes.hasValidData ? globalExtremes.min : -95;
    const powerMax = globalExtremes.hasValidData ? globalExtremes.max : 0;
    const valueRange = powerMax - powerMin;

    if (valueRange <= 0) {
      console.warn("功率极值范围无效（max <= min），使用默认颜色范围");
      return;
    }

    const valueColors: { value: number; color: string }[] = [];
    for (let i = 0; i < valueRange; i++) {
      const colorIndex = Math.floor((i / valueRange) * 256);
      const safeColorIndex = Math.min(colorIndex, DEFAULT_COLORS.length - 1);
      const currentValue = i + powerMin;
      const currentColor = DEFAULT_COLORS[safeColorIndex];
      valueColors.push({
        value: currentValue,
        color: currentColor
      });
    }

    const steps = valueColors.map(({ value, color }) => ({
      value: value,
      label: value,
      color: ColorCSS(color),
    }));

    const lut = new LUT({
      steps: steps,
      units: "dB",
      interpolate: false,
    });

    const paletteFill = new PalettedFill({ lut });
    ctx.series.setFillStyle(paletteFill);
  }, []);

  const setColorStyle2 = useCallback(() => {
    const ctx = chartContext.current;
    const globalExtremes = powerExtremesRef.current;
    if (!ctx.series || !lcjs) {
      console.error("热力图系列未初始化，无法配置颜色样式");
      return;
    }
    const { ColorCSS, LUT, PalettedFill } = lcjs;

    // 步骤1：使用实际数据极值（贴合真实信号范围，避免色阶稀释）
    // const powerMin = globalExtremes.hasValidData ? globalExtremes.min : -95;
    // const powerMax = globalExtremes.hasValidData ? globalExtremes.max : 0;
    const powerMin = -160;
    const powerMax = 20;
    const valueRange = powerMax - powerMin;

    if (valueRange <= 0) {
      console.warn("功率极值范围无效（max <= min），使用默认颜色范围");
      return;
    }

    // 步骤2：新增信号阈值配置（核心：区分有效/无效信号）
    // 阈值规则：取实际功率最小值+10dB（可根据你的信号强度调整该偏移量）
    // 低于此阈值判定为「无信号」，统一设为纯黑/深黑
    const signalThreshold = Math.min(powerMin, powerMax); // 防止阈值超过最大值，避免逻辑错误
    const validSignalRange = powerMax - signalThreshold; // 有效信号的实际范围

    // 步骤3：重构颜色映射数组（先填充无信号区域，再填充有效信号高对比度颜色）
    const valueColors: { value: number; color: string }[] = [];

    // 3.1 无信号区域：功率从min到threshold，统一映射为纯黑（低调不抢眼）
    valueColors.push(
      { value: powerMin, color: "#000000" }, // 起始点
      { value: signalThreshold, color: "#000000" } // 阈值点（以下全黑）
    );

    // 3.2 有效信号区域：分配高对比度颜色，避免相近色
    if (validSignalRange > 0) {
      // 可选：替换为精简的高对比度颜色数组（比原有256色更易区分信号强弱）
      const highContrastColors = [
        "#0000ff", // 暗蓝（弱信号）
        "#001A33", // 蓝
        "#0088ff", // 浅蓝
        "#33FFFF", // 绿
        "#88ff00", // 浅绿
        "#ffff00", // 亮黄
        "#ff8800", // 橙
        "#ff0000"  // 红（极强信号）
      ];

      for (let i = 0; i <= validSignalRange; i++) {
        const currentValue = signalThreshold + i;
        // 映射逻辑：将有效信号范围均匀分配到高对比度颜色数组（避免颜色过于密集）
        const colorIndex = Math.floor((i / validSignalRange) * (highContrastColors.length - 1));
        const currentColor = highContrastColors[colorIndex];

        valueColors.push({
          value: currentValue,
          color: currentColor
        });
      }
    } else {
      // 无有效信号范围时，补充一个默认颜色（防止数组为空）
      valueColors.push({ value: powerMax, color: "#0000ff" });
    }

    // 步骤4：生成LUT所需的steps（保持原有逻辑，映射颜色和值）
    const steps = valueColors.map(({ value, color }) => ({
      value: value,
      label: value.toFixed(1), // 优化标签显示，保留1位小数更整洁
      color: ColorCSS(color),
    }));

    // 步骤5：创建颜色查找表（关闭插值，确保信号边界清晰，不模糊）
    const lut = new LUT({
      steps: steps,
      units: "dB",
      interpolate: false, // 关键：关闭插值，避免有效/无效信号之间出现过渡杂色
    });

    const paletteFill = new PalettedFill({ lut });
    ctx.series.setFillStyle(paletteFill);
  }, []); // 补充依赖项，避免闭包导致的颜色数组更新异常

  const setColorStyle = useCallback(() => {
    const ctx = chartContext.current;
    const globalExtremes = powerExtremesRef.current;
    if (!ctx.series || !lcjs) {
      console.error("热力图系列未初始化，无法配置颜色样式");
      return;
    }
    const { ColorCSS, LUT, PalettedFill } = lcjs;

    // 步骤1：保留固定功率范围，优化颜色在该区间的分布（黑色背景下更醒目）
    const valueRange = powerMax - powerMin;

    if (valueRange <= 0) {
      console.warn("功率极值范围无效（max <= min），使用默认颜色范围");
      return;
    }

    // 步骤2：优化信号阈值逻辑（真正区分无信号/有效信号，提升对比核心）
    // 阈值规则：取 powerMin + 20dB（可调整，建议15-25dB），低于此值判定为「无信号（纯黑）」
    // 解决原有阈值等于powerMin，无信号和弱信号混淆的问题
    const signalOffset = colorConfig.gain; // 关键优化：增大阈值偏移，突出有效信号
    const signalThreshold = Math.min(powerMin + signalOffset, powerMax - 5); // 防止阈值溢出有效区间
    const validSignalRange = powerMax - signalThreshold; // 有效信号的实际可展示范围

    // 步骤4：重构颜色映射数组（强化有效信号区间的颜色密度）
    const valueColors: { value: number; color: string }[] = [];

    // 4.1 无信号区域：powerMin → signalThreshold，纯黑（硬边界，无过渡）
    // 解决原有弱信号被黑色淹没的问题，明确区分「无信号」和「有信号」
    valueColors.push(
      { value: powerMin, color: "#000000" },
      { value: signalThreshold, color: "#000000" }
    );

    // 4.2 有效信号区域：分配高对比度颜色，且「分段加权」（中间信号区间颜色更密集）
    if (validSignalRange > 0) {
      // 细分有效信号区间，提升中间信号的对比差异
      const colorStep = validSignalRange / (DEFAULT_COLORS.length * 2); // 颜色步长减半，提升密度
      for (let i = 0; i <= validSignalRange; i += colorStep) {
        const currentValue = signalThreshold + i;
        if (currentValue > powerMax) break;

        // 映射逻辑：优先分配高对比度颜色，避免均匀过渡导致的对比不足
        const colorIndex = Math.floor(
          (i / validSignalRange) * (DEFAULT_COLORS.length - 1)
        );
        const currentColor = DEFAULT_COLORS[Math.min(colorIndex, DEFAULT_COLORS.length - 1)];

        valueColors.push({
          value: currentValue,
          color: currentColor,
        });
      }
    } else {
      // 无有效信号范围时，补充鲜艳颜色，避免视觉平淡
      valueColors.push({ value: powerMax, color: "#0099FF" });
    }

    // 步骤5：优化LUT步骤配置（提升标签可读性，强化颜色边界）
    const steps = valueColors.map(({ value, color }) => ({
      value: value,
      label: value.toFixed(0), // 优化：整数显示，更整洁，减少视觉干扰
      color: ColorCSS(color),
    }));

    // 步骤6：微调颜色查找表（可选开启「轻度插值」，提升颜色过渡的层次感，不模糊边界）
    // 关键：仅在有效信号区间内插值，无信号区域保持纯黑硬边界
    const lut = new LUT({
      steps: steps,
      units: "dB",
      interpolate: true, // 优化：开启轻度插值，让有效信号颜色过渡更自然，对比更鲜明
      // 新增：设置颜色范围兜底，避免信号溢出时显示异常
      min: powerMin,
      max: powerMax,
    });

    const paletteFill = new PalettedFill({ lut });
    ctx.series.setFillStyle(paletteFill);
  }, [colorConfig.gain]);
  // 重置图表系列函数
  const resetChartSeries = useCallback(() => {
    const ctx = chartContext.current;
    const chart = chartRef.current;
    if (!chart || !lcjs) {
      console.warn("图表或坐标轴未初始化，无法重置系列");
      return;
    }
    if (ctx.series) {
      try {
        chart.getSeries().forEach(series => series.dispose());
      } catch (error) {
        console.error("销毁旧系列失败", error);
      }
    }
    const { emptyLine } = lcjs;
    if (!emptyLine) {
      console.error("lcjs 缺少 emptyLine API，无法配置系列样式");
      return;
    };

    const targetResolution = fftPointNumber;
    const freqInterval = 30000000;
    const xStep = freqInterval > 0 ? (freqInterval / targetResolution) : 1;

    try {
      ctx.series = chart
        .addHeatmapScrollingGridSeries({
          scrollDimension: "rows",
          resolution: targetResolution,
          start: { x: 0, y: 0 },
          step: { x: xStep, y: ctx.period },
        })
        .setWireframeStyle(emptyLine)
        .setMouseInteractions(false)
        .setDataCleaning({ minDataPointCount: 0 });
    } catch (error) {
      console.error("创建热力图系列失败", error);
      return;
    }
    setColorStyle();
  }, [setColorStyle, fftPointNumber]);

  const addData = useCallback((data: any[]) => {
    // 1. 暂停状态下不执行任何操作
    if (paused) return;
    // 2. 校验输入数据有效性
    if (!Array.isArray(data) || data.length === 0) {
      console.warn("传入的数据无效，跳过更新");
      return;
    }
    const ctx = chartContext.current;
    const now = window.performance.now();

    // 3. 提取功率极值并更新全局极值
    const batchExtremes = extractBatchPowerExtremes(data);
    if (batchExtremes) {
      const globalExtremes = powerExtremesRef.current;
      if (!globalExtremes.hasValidData) {
        globalExtremes.min = batchExtremes.min;
        globalExtremes.max = batchExtremes.max;
        globalExtremes.hasValidData = true;
        // 首次获取有效数据，更新颜色样式
        setColorStyle();
      } else {
        globalExtremes.min = Math.min(globalExtremes.min, batchExtremes.min);
        globalExtremes.max = Math.max(globalExtremes.max, batchExtremes.max);
      }
    }

    // 4. 数据缓存处理（限制缓存长度，防止内存溢出）
    ctx.cache.push(data);
    if (ctx.cache.length > MAX_CACHE_LENGTH) {
      ctx.cache = ctx.cache.slice(-BUFFER_LENGTH);
    }

    // 5. 【核心】直接处理数据并渲染（单次add对应单次渲染）
    let values = [data]; // 取出当前传入的单批数据
    ctx.last = data; // 记录最后一批数据，用于兜底

    // 6. 数据平铺适配（匹配FFT点数分辨率）
    if (values.length < 1) {
      values = spreadData(values);
    }

    // 7. 渲染到热力图系列（完成单次更新）
    if (ctx.series) {
      // 检查时间间隔，避免过于频繁的更新
      const lastUpdateTime = ctx.updater?.last || 0;
      const updateTimeout = ctx.updater?.timeout || 250;

      if (now - lastUpdateTime >= updateTimeout) {
        ctx.series.addIntensityValues(values);
        // 更新最后渲染时间
        if (!ctx.updater) {
          ctx.updater = { last: now, timeout: 250 };
        } else {
          ctx.updater.last = now;
        }
      }
    }

  }, [paused, extractBatchPowerExtremes, setColorStyle, spreadData]);

  // 暂停/继续切换方法
  const togglePause = useCallback(() => {
    setPaused(prev => !prev);
  }, []);

  // 监听X轴范围变化，更新瀑布图X轴（联动功能保留）
  useEffect(() => {
    if (!chartRef.current || !xAxisRange) return;

    const chart = chartRef.current;
    const axisX = chart.getDefaultAxisX();
    const currentXInterval = axisX.getInterval();
    if (
      currentXInterval.start === xAxisRange.start &&
      currentXInterval.end === xAxisRange.end
    ) {
      return;
    }

    axisX.setInterval(
      xAxisRange.start,
      xAxisRange.end,
      false,
      true
    );
  }, [xAxisRange]);

  // 暴露实例方法给父组件
  useImperativeHandle(ref, () => ({
    addData,
    togglePause,
    reset: resetChartSeries,
  }), [addData, togglePause, resetChartSeries]);

  // 初始化图表（移除 RenderWorker 相关逻辑，仅初始化图表和系列）
  useEffect(() => {
    if (!lcjs) {
      console.error("LightningChart 未加载，请确保已引入相关依赖");
      return;
    }
    const requiredAPIs = [
      "AxisScrollStrategies",
      "AxisTickStrategies",
      "TimeFormattingFunctions",
      "emptyLine",
      "emptyFill",
      "lightningChart",
      "ColorCSS",
      "LUT",
      "PalettedFill"
    ];
    const missingAPIs = requiredAPIs.filter(api => !lcjs[api]);
    if (missingAPIs.length > 0) {
      console.error("lcjs 缺少必要 API，无法初始化瀑布图", { missingAPIs });
      return;
    }

    const {
      AxisScrollStrategies,
      AxisTickStrategies,
      TimeFormattingFunctions,
      emptyLine,
      emptyFill,
      lightningChart,
      SolidFill,
      ColorRGBA,
      AutoCursorModes,
    } = lcjs;

    if (!containerRef.current) {
      console.error("图表容器未找到，无法初始化 LightningChart");
      return;
    }

    try {
      const chart = lightningChart({
        overrideInteractionMouseButtons: {
          axisXYZoomMouseButton: 2,
          chartXYPanMouseButton: 2,
          chartXYRectangleZoomFitMouseButton: 0,
          axisXYPanMouseButton: 0,
        },
      }).ChartXY({ container: containerRef.current });

      chart
        .setSeriesBackgroundFillStyle(emptyFill)
        .setPadding(5)
        .setPadding({ top: 0 })
        .disableAnimations()
        .setPadding({ left: 0, top: 0, right: 0, bottom: 0 })
        .setMouseInteractionPan(false)
        .setMouseInteractionWheelZoom(false)
        .setMouseInteractionRectangleZoom(false)
        .setMouseInteractionRectangleFit(false)
        .setZoomingRectangleFillStyle(new SolidFill({ color: ColorRGBA(0, 255, 10, 100) }))
        .setTitle("")
        .setAutoCursorMode(AutoCursorModes.disabled);

      chartRef.current = chart;

      const axisX = chart.getDefaultAxisX();
      const axisY = chart.getDefaultAxisY();
      axisX
        .setInterval(0, 30000000, false, true)
        .setMouseInteractions(false)
        .setAnimationScroll(false);

      axisY.setMouseInteractions(false)
        .setAnimationScroll(false);

      

      // 轴刻度样式配置
      function SetTickStyle(tick: any) {
        return tick.setLabelFont((font: any) => font.setWeight('normal').setSize(12).setStyle('normal').setFamily('Arial').setVariant(true))
      }

      axisX.setTickStrategy(AxisTickStrategies.Numeric, (strategy: any) => {
        return strategy
          .setMajorTickStyle(SetTickStyle)
          .setMinorTickStyle(SetTickStyle)
          .setFormattingFunction((value: number) => {
            let v = value;
            const { start, end } = axisX.getInterval();
            const span = Math.abs(end - start);
            let unit = "Hz";
            let factor = 1;

            if (span >= 1e9) { unit = "GHz"; factor = 1e9; }
            else if (span >= 1e6) { unit = "MHz"; factor = 1e6; }
            else if (span >= 1e3) { unit = "KHz"; factor = 1e3; }

            let num = (v / factor).toFixed(2);
            if (num.endsWith(".00")) num = num.slice(0, -3);
            return `${num}${unit}`;
          });
      });

      axisY
        .setScrollStrategy(AxisScrollStrategies.progressive)
        .setTickStrategy(AxisTickStrategies.Numeric, (strategy: any) =>
          strategy
            .setMajorFormattingFunction((val: number) =>
              TimeFormattingFunctions.hhmmss(val)
            )
            .setMinorFormattingFunction((val: number) =>
              TimeFormattingFunctions.hhmmss(val)
            )
            .setMajorTickStyle((style: any) => strategy.getMinorTickStyle())
        )
        .setInterval(0, -RANGE_TIME_MS)
        .setThickness(DefaultAxisYThickness)
        .setTickStrategy(AxisTickStrategies.Numeric, (strategy: any) => {
          return strategy
            .setMajorTickStyle(SetTickStyle)
            .setMinorTickStyle(SetTickStyle)
        });

      // 初始化图表系列（无定时Worker，仅初始化系列）
      const ctx = chartContext.current;
      requestAnimationFrame(() => {
        resetChartSeries();
      });

      // 销毁回调
      return () => {
        chart?.dispose();
        chartRef.current = null;
        chartContext.current.series = null;
      };
    } catch (error) {
      console.error("瀑布图初始化失败：", error);
    }
  }, [resetChartSeries, fftPointNumber]);

  // 渲染 UI 组件
  const renderUIElements = () => {
    return (
      <div className="waterfall-chart-ui" style={{ position: "absolute", top: 0, left: 0, right: 0, zIndex: 10 }}>
        {texts.title && (
          <div style={{ position: "absolute", top: 10, left: 10, color: "#fff" }}>
            {texts.title}
          </div>
        )}

        {texts.unit && (
          <div style={{ position: "absolute", top: 10, right: 10, color: "#fff" }}>
            {texts.unit}
          </div>
        )}

        {btns.includes("pause") && (
          <button
            onClick={togglePause}
            style={{
              position: "absolute",
              top: 10,
              right: 20,
              padding: "4px 12px",
              backgroundColor: paused ? "#409eff" : "#113665",
              color: "#fff",
              border: "none",
              borderRadius: "4px",
              cursor: "pointer",
            }}
          >
            {paused ? "继续" : "暂停"}
          </button>
        )}
      </div>
    );
  };

  return (
    <div
      ref={containerRef}
      className={`waterfall-chart-container ${className}`}
      style={{
        position: "relative",
        width: "100%",
        height: "400px",
        backgroundColor: "#000",
        ...style,
      }}
    >
      {renderUIElements()}
    </div>
  );
});

export default WaterFallChart;