import { ref, nextTick, onMounted, onBeforeUnmount, onUnmounted, computed, watch } from 'vue';
import '../plugins/echarts.mjs';
import { init } from '../../../node_modules/.pnpm/echarts@6.0.0/node_modules/echarts/lib/core/echarts.mjs';

const useChartOps = () => ({
  /** */
  chartHeight: "16rem",
  /** 字体大小 */
  fontSize: 13,
  /** 字体颜色 */
  fontColor: "#999",
  /** 主题颜色 */
  themeColor: "#00E4E5",
  /** 颜色组 */
  colors: [
    "#00E4E5",
    "#4ABEFF",
    "#EDF2FF",
    "#14DEBA",
    "#FFAF20",
    "#FA8A6C",
    "#FFAF20"
  ]
});
const RESIZE_DELAYS = [50, 100, 200, 350];
const MENU_RESIZE_DELAYS = [50, 100, 200];
const RESIZE_DEBOUNCE_DELAY = 100;
function useChart(options = {}) {
  const { initOptions, initDelay = 0, threshold = 0.1, autoTheme = true } = options;
  const chartRef = ref();
  let chart = null;
  let intersectionObserver = null;
  let pendingOptions = null;
  let resizeTimeoutId = null;
  let resizeFrameId = null;
  let isDestroyed = false;
  let emptyStateDiv = null;
  const clearTimers = () => {
    if (resizeTimeoutId) {
      clearTimeout(resizeTimeoutId);
      resizeTimeoutId = null;
    }
    if (resizeFrameId) {
      cancelAnimationFrame(resizeFrameId);
      resizeFrameId = null;
    }
  };
  const requestAnimationResize = () => {
    if (resizeFrameId) {
      cancelAnimationFrame(resizeFrameId);
    }
    resizeFrameId = requestAnimationFrame(() => {
      handleResize();
      resizeFrameId = null;
    });
  };
  const debouncedResize = () => {
    if (resizeTimeoutId) {
      clearTimeout(resizeTimeoutId);
    }
    resizeTimeoutId = window.setTimeout(() => {
      requestAnimationResize();
      resizeTimeoutId = null;
    }, RESIZE_DEBOUNCE_DELAY);
  };
  const multiDelayResize = (delays) => {
    nextTick(requestAnimationResize);
    delays.forEach((delay) => {
      setTimeout(requestAnimationResize, delay);
    });
  };
  let menuOpenStopHandle = null;
  let menuTypeStopHandle = null;
  const setupMenuWatchers = () => {
    nextTick(requestAnimationResize);
    setTimeout(() => multiDelayResize(MENU_RESIZE_DELAYS), 0);
  };
  const cleanupMenuWatchers = () => {
    menuOpenStopHandle?.();
    menuTypeStopHandle?.();
    menuOpenStopHandle = null;
    menuTypeStopHandle = null;
  };
  let themeStopHandle = null;
  const setupThemeWatcher = () => {
    if (autoTheme) {
    }
  };
  const cleanupThemeWatcher = () => {
    themeStopHandle?.();
    themeStopHandle = null;
  };
  const createLineStyle = (color, width = 1, type) => ({
    color,
    width,
    ...type && { type }
  });
  const styleCache = {
    axisLine: null,
    splitLine: null,
    axisLabel: null,
    lastDarkValue: false
  };
  const clearStyleCache = () => {
    styleCache.axisLine = null;
    styleCache.splitLine = null;
    styleCache.axisLabel = null;
    styleCache.lastDarkValue = false;
  };
  const getAxisLineStyle = (show = true) => {
    if (styleCache.lastDarkValue !== false) {
      clearStyleCache();
    }
    if (!styleCache.axisLine) {
      styleCache.axisLine = {
        show,
        lineStyle: createLineStyle("#EDEDED")
      };
    }
    return styleCache.axisLine;
  };
  const getSplitLineStyle = (show = true) => {
    if (styleCache.lastDarkValue !== false) {
      clearStyleCache();
    }
    if (!styleCache.splitLine) {
      styleCache.splitLine = {
        show,
        lineStyle: createLineStyle("#EDEDED", 1, "dashed")
      };
    }
    return styleCache.splitLine;
  };
  const getAxisLabelStyle = (show = true) => {
    if (styleCache.lastDarkValue !== false) {
      clearStyleCache();
    }
    if (!styleCache.axisLabel) {
      const { fontColor, fontSize } = useChartOps();
      styleCache.axisLabel = {
        show,
        color: fontColor,
        fontSize
      };
    }
    return styleCache.axisLabel;
  };
  const getAxisTickStyle = () => ({
    show: false
  });
  const getAnimationConfig = (animationDelay = 50, animationDuration = 1500) => ({
    animationDelay: (idx) => idx * animationDelay + 200,
    animationDuration: (idx) => animationDuration - idx * 50,
    animationEasing: "quarticOut"
  });
  const getTooltipStyle = (trigger = "axis", customOptions = {}) => ({
    trigger,
    backgroundColor: "rgba(255, 255, 255, 0.9)",
    borderColor: "#ddd",
    borderWidth: 1,
    textStyle: {
      color: "#333"
    },
    ...customOptions
  });
  const getLegendStyle = (position = "bottom", customOptions = {}) => {
    const baseConfig = {
      textStyle: {
        color: "#333"
      },
      itemWidth: 12,
      itemHeight: 12,
      itemGap: 20,
      ...customOptions
    };
    switch (position) {
      case "bottom":
        return {
          ...baseConfig,
          bottom: 0,
          left: "center",
          orient: "horizontal",
          icon: "roundRect"
        };
      case "top":
        return {
          ...baseConfig,
          top: 0,
          left: "center",
          orient: "horizontal",
          icon: "roundRect"
        };
      case "left":
        return {
          ...baseConfig,
          left: 0,
          top: "center",
          orient: "vertical",
          icon: "roundRect"
        };
      case "right":
        return {
          ...baseConfig,
          right: 0,
          top: "center",
          orient: "vertical",
          icon: "roundRect"
        };
      default:
        return baseConfig;
    }
  };
  const getGridWithLegend = (showLegend, legendPosition = "bottom", baseGrid = {}) => {
    const defaultGrid = {
      top: 15,
      right: 15,
      bottom: 8,
      left: 0,
      containLabel: true,
      ...baseGrid
    };
    if (!showLegend) {
      return defaultGrid;
    }
    switch (legendPosition) {
      case "bottom":
        return {
          ...defaultGrid,
          bottom: 40
        };
      case "top":
        return {
          ...defaultGrid,
          top: 40
        };
      case "left":
        return {
          ...defaultGrid,
          left: 120
        };
      case "right":
        return {
          ...defaultGrid,
          right: 120
        };
      default:
        return defaultGrid;
    }
  };
  const createIntersectionObserver = () => {
    if (intersectionObserver || !chartRef.value) return;
    intersectionObserver = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting && pendingOptions && !isDestroyed) {
            requestAnimationFrame(() => {
              if (!isDestroyed && pendingOptions) {
                try {
                  if (!chart) {
                    chart = init(entry.target);
                  }
                  const event = new CustomEvent("chartVisible", {
                    detail: { options: pendingOptions }
                  });
                  entry.target.dispatchEvent(event);
                  pendingOptions = null;
                  cleanupIntersectionObserver();
                } catch (error) {
                  console.error("\u56FE\u8868\u521D\u59CB\u5316\u5931\u8D25:", error);
                }
              }
            });
          }
        });
      },
      { threshold }
    );
    intersectionObserver.observe(chartRef.value);
  };
  const cleanupIntersectionObserver = () => {
    if (intersectionObserver) {
      intersectionObserver.disconnect();
      intersectionObserver = null;
    }
  };
  const isContainerVisible = (element) => {
    const rect = element.getBoundingClientRect();
    return rect.width > 0 && rect.height > 0 && rect.top < window.innerHeight && rect.bottom > 0;
  };
  const performChartInit = (options2) => {
    if (!chart && chartRef.value && !isDestroyed) {
      chart = init(chartRef.value);
      setupMenuWatchers();
      setupThemeWatcher();
    }
    if (chart && !isDestroyed) {
      chart.setOption(options2);
      pendingOptions = null;
    }
  };
  const emptyStateManager = {
    create: () => {
      if (!chartRef.value || emptyStateDiv) return;
      emptyStateDiv = document.createElement("div");
      emptyStateDiv.style.cssText = `
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        font-size: 12px;
        color: ${"#B3B2B2"};
        background: transparent;
        z-index: 10;
      `;
      emptyStateDiv.innerHTML = `<span>\u6682\u65E0\u6570\u636E</span>`;
      if (chartRef.value.style.position !== "relative" && chartRef.value.style.position !== "absolute") {
        chartRef.value.style.position = "relative";
      }
      chartRef.value.appendChild(emptyStateDiv);
    },
    remove: () => {
      if (emptyStateDiv && chartRef.value) {
        chartRef.value.removeChild(emptyStateDiv);
        emptyStateDiv = null;
      }
    },
    updateStyle: () => {
      if (emptyStateDiv) {
        emptyStateDiv.style.color = "#999";
      }
    }
  };
  const initChart = (options2 = {}, isEmpty = false) => {
    if (!chartRef.value || isDestroyed) return;
    const mergedOptions = { ...initOptions, ...options2 };
    try {
      if (isEmpty) {
        if (chart) {
          chart.clear();
        }
        emptyStateManager.create();
        return;
      } else {
        emptyStateManager.remove();
      }
      if (isContainerVisible(chartRef.value)) {
        if (initDelay > 0) {
          setTimeout(() => performChartInit(mergedOptions), initDelay);
        } else {
          performChartInit(mergedOptions);
        }
      } else {
        pendingOptions = mergedOptions;
        createIntersectionObserver();
      }
    } catch (error) {
      console.error("\u56FE\u8868\u521D\u59CB\u5316\u5931\u8D25:", error);
    }
  };
  const updateChart = (options2) => {
    if (isDestroyed) return;
    try {
      if (!chart) {
        initChart(options2);
        return;
      }
      chart.setOption(options2);
    } catch (error) {
      console.error("\u56FE\u8868\u66F4\u65B0\u5931\u8D25:", error);
    }
  };
  const handleResize = () => {
    if (chart && !isDestroyed) {
      try {
        chart.resize();
      } catch (error) {
        console.error("\u56FE\u8868resize\u5931\u8D25:", error);
      }
    }
  };
  const destroyChart = () => {
    isDestroyed = true;
    if (chart) {
      try {
        chart.dispose();
      } catch (error) {
        console.error("\u56FE\u8868\u9500\u6BC1\u5931\u8D25:", error);
      } finally {
        chart = null;
      }
    }
    cleanupMenuWatchers();
    cleanupThemeWatcher();
    emptyStateManager.remove();
    cleanupIntersectionObserver();
    clearTimers();
    clearStyleCache();
    pendingOptions = null;
  };
  const getChartInstance = () => chart;
  const isChartInitialized = () => chart !== null;
  onMounted(() => {
    window.addEventListener("resize", debouncedResize);
  });
  onBeforeUnmount(() => {
    window.removeEventListener("resize", debouncedResize);
  });
  onUnmounted(() => {
    destroyChart();
  });
  return {
    chartRef,
    initChart,
    updateChart,
    handleResize,
    destroyChart,
    getChartInstance,
    isChartInitialized,
    emptyStateManager,
    getAxisLineStyle,
    getSplitLineStyle,
    getAxisLabelStyle,
    getAxisTickStyle,
    getAnimationConfig,
    getTooltipStyle,
    getLegendStyle,
    useChartOps,
    getGridWithLegend
  };
}
function useChartComponent(options) {
  const {
    props,
    generateOptions,
    checkEmpty,
    watchSources = [],
    onVisible,
    chartOptions = {}
  } = options;
  const chart = useChart(chartOptions);
  const { chartRef, initChart, emptyStateManager } = chart;
  const isEmpty = computed(() => {
    if (props.isEmpty) return true;
    if (checkEmpty) return checkEmpty();
    return false;
  });
  const updateChart = () => {
    nextTick(() => {
      if (isEmpty.value) {
        if (chart.getChartInstance()) {
          chart.getChartInstance()?.clear();
        }
        emptyStateManager.create();
      } else {
        emptyStateManager.remove();
        initChart(generateOptions());
      }
    });
  };
  const handleChartVisible = () => {
    if (onVisible) {
      onVisible();
    } else {
      updateChart();
    }
  };
  const stopHandles = [];
  const setupWatchers = () => {
    if (watchSources.length > 0) {
      const stopHandle = watch(watchSources, updateChart, { deep: true });
      stopHandles.push(stopHandle);
    }
  };
  const cleanupWatchers = () => {
    stopHandles.forEach((stop) => stop());
    stopHandles.length = 0;
  };
  const setupLifecycle = () => {
    onMounted(() => {
      updateChart();
      if (chartRef.value) {
        chartRef.value.addEventListener("chartVisible", handleChartVisible);
      }
    });
    onBeforeUnmount(() => {
      if (chartRef.value) {
        chartRef.value.removeEventListener("chartVisible", handleChartVisible);
      }
      cleanupWatchers();
      emptyStateManager.remove();
    });
  };
  setupWatchers();
  setupLifecycle();
  return {
    ...chart,
    isEmpty,
    updateChart,
    handleChartVisible
  };
}

export { useChart, useChartComponent, useChartOps };
