<template>
  <view class="ec-wrap">
    <!-- 通过 props 把 option 喂给 renderjs -->
    <view
      class="ec-canvas"
      :prop="option"
      :change:prop="ec.setOption"
      :data-theme="theme"
    />
  </view>
</template>

<script>
export default {
  name: "EChartsView",
  props: {
    option: { type: Object, default: () => ({}) },
    theme: { type: String, default: "light" },
  },
};
</script>

<script module="ec" lang="renderjs">
import * as echarts from "echarts";

// 使用 Map 存储多个图表实例（支持多个 EChartsView 组件）
const charts = new Map();
const resizeObservers = new Map();

// 地图数据加载状态
let chinaMapLoaded = false;
let chinaMapLoading = false;

// 加载并注册中国地图
async function loadChinaMap() {
  if (chinaMapLoaded) {
    return Promise.resolve();
  }

  if (chinaMapLoading) {
    // 如果正在加载，等待加载完成
    return new Promise((resolve) => {
      const checkInterval = setInterval(() => {
        if (chinaMapLoaded) {
          clearInterval(checkInterval);
          resolve();
        }
      }, 100);
      // 最多等待 10 秒
      setTimeout(() => {
        clearInterval(checkInterval);
        resolve();
      }, 10000);
    });
  }

  chinaMapLoading = true;

  try {
    // 从在线 CDN 加载中国地图 GeoJSON 数据
    // 使用 ECharts 官方示例数据源
    const response = await fetch('https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json');
    if (!response.ok) {
      // 如果第一个源失败，尝试备用源
      const backupResponse = await fetch('https://echarts.apache.org/examples/data/map/china.json');
      if (!backupResponse.ok) {
        throw new Error('Failed to load China map data');
      }
      const geoJson = await backupResponse.json();
      echarts.registerMap('china', geoJson);
    } else {
      const geoJson = await response.json();
      echarts.registerMap('china', geoJson);
    }

    chinaMapLoaded = true;
    console.log('[EChartsView] 中国地图数据已加载并注册');
  } catch (error) {
    console.error('[EChartsView] 加载中国地图数据失败:', error);
    // 即使加载失败，也标记为已尝试，避免重复请求
    chinaMapLoaded = false;
  } finally {
    chinaMapLoading = false;
  }
}

function getChartKey(el) {
  // 使用元素的唯一标识作为 key
  if (!el._echartsKey) {
    el._echartsKey = 'echarts_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
  }
  return el._echartsKey;
}

function ensureChart(el, retryCount = 0) {
  if (!el) return null;

  const key = getChartKey(el);
  let chart = charts.get(key);

  // 如果图表已存在且有效，直接返回
  if (chart && !chart.isDisposed()) {
    return chart;
  }

  // 如果图表已销毁，从 Map 中移除
  if (chart && chart.isDisposed()) {
    charts.delete(key);
    const ro = resizeObservers.get(key);
    if (ro) {
      ro.disconnect();
      resizeObservers.delete(key);
    }
    chart = null;
  }

  // 确保元素有尺寸
  const rect = el.getBoundingClientRect();
  const computedStyle = window.getComputedStyle(el);
  const width = parseFloat(computedStyle.width) || rect.width;
  const height = parseFloat(computedStyle.height) || rect.height;

  // 如果尺寸为 0，尝试延迟初始化（最多重试 10 次）
  if ((width === 0 || height === 0) && retryCount < 10) {
    if (retryCount === 0) {
      console.warn('[EChartsView] 容器尺寸为 0，延迟初始化', { width, height, rect });
    }

    // 使用指数退避策略，避免无限循环
    const delay = Math.min(100 * Math.pow(1.5, retryCount), 1000);
    setTimeout(() => {
      ensureChart(el, retryCount + 1);
    }, delay);
    return null;
  }

  // 如果重试次数过多，使用默认尺寸
  if (width === 0 || height === 0) {
    console.warn('[EChartsView] 容器尺寸仍为 0，使用默认尺寸', { width, height });
    // 使用父元素尺寸或默认值
    const parentRect = el.parentElement ? el.parentElement.getBoundingClientRect() : { width: 800, height: 400 };
    const finalWidth = width || parentRect.width || 800;
    const finalHeight = height || parentRect.height || 400;

    if (finalWidth > 0 && finalHeight > 0) {
      // 设置元素尺寸
      el.style.width = finalWidth + 'px';
      el.style.height = finalHeight + 'px';
    } else {
      console.error('[EChartsView] 无法确定容器尺寸，跳过初始化');
      return null;
    }
  }

      try {
        // 注意：地图数据加载在 setOption 中处理，这里不处理
        // 因为 ensureChart 是同步函数，不能使用 await

        chart = echarts.init(el, null, {
          renderer: "canvas",
          width: rect.width,
          height: rect.height
        });

        charts.set(key, chart);

    // 自适应：监听容器尺寸变化
    if (typeof ResizeObserver !== "undefined") {
      const ro = new ResizeObserver((entries) => {
        for (const entry of entries) {
          const { width, height } = entry.contentRect;
          const c = charts.get(key);
          if (c && !c.isDisposed() && width > 0 && height > 0) {
            try {
              c.resize({ width, height });
            } catch (e) {
              console.warn('[EChartsView] resize 失败', e);
            }
          }
        }
      });
      ro.observe(el);
      resizeObservers.set(key, ro);
    } else {
      // 兜底
      const resizeHandler = () => {
        const c = charts.get(key);
        if (c && !c.isDisposed()) {
          const rect = el.getBoundingClientRect();
          if (rect.width > 0 && rect.height > 0) {
            try {
              c.resize();
            } catch (e) {
              console.warn('[EChartsView] resize 失败', e);
            }
          }
        }
      };
      window.addEventListener("resize", resizeHandler);
      // 存储 handler 以便后续清理
      el._resizeHandler = resizeHandler;
    }

    return chart;
  } catch (e) {
    console.error('[EChartsView] 初始化失败', e);
    return null;
  }
}

function disposeChart(el) {
  if (!el) return;
  const key = getChartKey(el);
  const chart = charts.get(key);

  if (chart && !chart.isDisposed()) {
    try {
      chart.dispose();
    } catch (e) {
      console.warn('[EChartsView] dispose 失败', e);
    }
  }

  charts.delete(key);

  const ro = resizeObservers.get(key);
  if (ro) {
    ro.disconnect();
    resizeObservers.delete(key);
  }

  if (el._resizeHandler) {
    window.removeEventListener("resize", el._resizeHandler);
    delete el._resizeHandler;
  }
}

export default {
  mounted() {
    const el = this.$el.querySelector(".ec-canvas") || this.$el;
    if (!el) {
      console.error('[EChartsView] 找不到容器元素');
      return;
    }
    // 延迟初始化，确保 DOM 已渲染
    setTimeout(() => {
      ensureChart(el);
    }, 50);
  },
  beforeDestroy() {
    const el = this.$el.querySelector(".ec-canvas") || this.$el;
    if (el) {
      disposeChart(el);
    }
  },
  methods: {
    async setOption(option, oldOption) {
      const el = this.$el.querySelector(".ec-canvas") || this.$el;
      if (!el) {
        console.error('[EChartsView] setOption: 找不到容器元素');
        return;
      }

      // 检查 option 是否有效
      if (!option || typeof option !== 'object') {
        console.warn('[EChartsView] setOption: option 无效', option);
        return;
      }

      // 检查是否使用了地图，如果是，先加载地图数据
      const needsMap = option.geo || (option.series && Array.isArray(option.series) && option.series.some(s => s.type === 'map' && s.map === 'china'));
      if (needsMap) {
        await loadChinaMap();
      }

      // 保存 option 供 ensureChart 使用
      el._pendingOption = option;

      // 确保图表已初始化
      let c = ensureChart(el);
      if (!c) {
        // 如果容器尺寸为 0，使用 ResizeObserver 等待容器尺寸可用
        if (typeof ResizeObserver !== "undefined") {
          let roTimeout = null;
          const ro = new ResizeObserver(async (entries) => {
            for (const entry of entries) {
              const { width, height } = entry.contentRect;
              if (width > 0 && height > 0) {
                ro.disconnect();
                if (roTimeout) clearTimeout(roTimeout);
                c = ensureChart(el);
                if (c && !c.isDisposed()) {
                  try {
                    // 如果使用地图，确保地图已加载
                    if (needsMap) {
                      await loadChinaMap();
                    }
                    const plainOption = JSON.parse(JSON.stringify(option));
                    c.setOption(plainOption, true);
                    requestAnimationFrame(() => {
                      const c2 = charts.get(getChartKey(el));
                      if (c2 && !c2.isDisposed()) {
                        try {
                          c2.resize({ width, height });
                        } catch (e) {
                          // 忽略已销毁的错误
                        }
                      }
                    });
                  } catch (e) {
                    console.error('[EChartsView] setOption 失败', e);
                  }
                }
                break;
              }
            }
          });
          ro.observe(el);
          // 设置超时，避免无限等待（5秒后强制使用默认尺寸）
          roTimeout = setTimeout(() => {
            ro.disconnect();
            console.warn('[EChartsView] ResizeObserver 超时，尝试使用默认尺寸初始化');
            // 尝试使用父元素尺寸或默认值
            const parentRect = el.parentElement ? el.parentElement.getBoundingClientRect() : null;
            const defaultWidth = parentRect ? parentRect.width : 800;
            const defaultHeight = parentRect ? parentRect.height : 400;
            if (defaultWidth > 0 && defaultHeight > 0) {
              el.style.width = defaultWidth + 'px';
              el.style.height = defaultHeight + 'px';
              c = ensureChart(el);
              if (c && !c.isDisposed()) {
                try {
                  const plainOption = JSON.parse(JSON.stringify(option));
                  c.setOption(plainOption, true);
                } catch (e) {
                  console.error('[EChartsView] setOption 失败', e);
                }
              }
            }
          }, 5000);
        } else {
          // 兜底：延迟重试（最多3次）
          let retryCount = 0;
          const maxRetries = 3;
          const retry = () => {
            if (retryCount >= maxRetries) {
              console.warn('[EChartsView] 重试次数过多，跳过初始化');
              return;
            }
            retryCount++;
            setTimeout(async () => {
              if (needsMap) {
                await loadChinaMap();
              }
              c = ensureChart(el);
              if (c && !c.isDisposed()) {
                try {
                  const plainOption = JSON.parse(JSON.stringify(option));
                  c.setOption(plainOption, true);
                } catch (e) {
                  console.error('[EChartsView] setOption 失败', e);
                }
              } else if (retryCount < maxRetries) {
                retry();
              }
            }, 200 * retryCount);
          };
          retry();
        }
        return;
      }

      // 检查图表是否已销毁
      if (c.isDisposed()) {
        console.warn('[EChartsView] setOption: 图表已销毁，重新初始化');
        charts.delete(getChartKey(el));
        if (needsMap) {
          await loadChinaMap();
        }
        c = ensureChart(el);
        if (!c) return;
      }

      try {
        // 如果使用地图，确保地图已加载
        if (needsMap) {
          await loadChinaMap();
        }
        // 深拷贝 option 确保是纯 JS 对象
        const plainOption = JSON.parse(JSON.stringify(option));
        c.setOption(plainOption, true);

        // 使用 requestAnimationFrame 避免 resize 警告
        requestAnimationFrame(() => {
          const key = getChartKey(el);
          const c2 = charts.get(key);
          if (c2 && !c2.isDisposed()) {
            const rect = el.getBoundingClientRect();
            if (rect.width > 0 && rect.height > 0) {
              try {
                c2.resize({ width: rect.width, height: rect.height });
              } catch (e) {
                // 忽略已销毁的错误（可能组件已卸载）
              }
            }
          }
        });
      } catch (e) {
        console.error('[EChartsView] setOption 失败', e, option);
      }
    },
  },
};
</script>

<style>
.ec-wrap {
  position: relative !important;
  width: 100%;
  height: 100%;
  overflow: hidden; /* 防止 canvas 越界 */
}

.ec-canvas {
  position: absolute !important;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  width: 100% !important;
  height: 100% !important;
  display: block;
}
</style>
