<template>
  <div :id="props.ids" class="chart-container"></div>
</template>

<script setup>
import * as echarts from "echarts";
import "echarts-gl";
import { defineProps, onMounted, watch, nextTick } from "vue";

const props = defineProps({
  pieData: {
    type: Array,
    default: () => [],
  },
  ids: {
    type: String,
    default: "pie3d",
  },
});

let myChart = null;

// ===============================
// 生成单个扇形的参数方程
// ===============================
function getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h) {
  const midRatio = (startRatio + endRatio) / 2;
  const startRadian = startRatio * Math.PI * 2;
  const endRadian = endRatio * Math.PI * 2;
  const midRadian = midRatio * Math.PI * 2;

  if (startRatio === 0 && endRatio === 1) isSelected = false;
  k = typeof k !== "undefined" ? k : 1 / 3;
  const offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
  const offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
  const hoverRate = isHovered ? 1.05 : 1;

  return {
    u: { min: -Math.PI, max: Math.PI * 3, step: Math.PI / 32 },
    v: { min: 0, max: Math.PI * 2, step: Math.PI / 20 },
    x(u, v) {
      if (u < startRadian)
        return offsetX + Math.cos(startRadian) * (1.3 + Math.cos(v) * k) * hoverRate;
      if (u > endRadian)
        return offsetX + Math.cos(endRadian) * (1.3 + Math.cos(v) * k) * hoverRate;
      return offsetX + Math.cos(u) * (1.3 + Math.cos(v) * k) * hoverRate;
    },
    y(u, v) {
      if (u < startRadian)
        return offsetY + Math.sin(startRadian) * (1.3 + Math.cos(v) * k) * hoverRate;
      if (u > endRadian)
        return offsetY + Math.sin(endRadian) * (1.3 + Math.cos(v) * k) * hoverRate;
      return offsetY + Math.sin(u) * (1.3 + Math.cos(v) * k) * hoverRate;
    },
    z(u, v) {
      if (u < -Math.PI * 0.5) return Math.sin(u);
      if (u > Math.PI * 2.5) return Math.sin(u) * h * 0.12;
      return Math.sin(v) > 0 ? 1 * h * 0.12 : -1;
    },
  };
}

// ===============================
// 生成 3D 饼图配置项
// ===============================
function getPie3D(pieData, internalDiameterRatio) {
  const series = [];
  let sumValue = pieData.reduce((s, i) => s + i.value, 0);

  // 全为 0 的情况：平均分配
  if (sumValue === 0) {
    sumValue = pieData.length;
    pieData = pieData.map((d) => ({ ...d, value: 1 }));
  }

  let startValue = 0;
  const k =
    typeof internalDiameterRatio !== "undefined"
      ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio)
      : 1 / 3;

  const colors = ["#E80000", "#FF8040", "#E2D101", "#0080FF"];

  for (let i = 0; i < pieData.length; i++) {
    const endValue = startValue + pieData[i].value;
    const startRatio = startValue / sumValue;
    const endRatio = endValue / sumValue;

    series.push({
      name: pieData[i].name,
      type: "surface",
      parametric: true,
      shading: "realistic",
      realisticMaterial: { roughness: 0.15, metalness: 0.5 },
      wireframe: { show: false },
      itemStyle: { color: colors[i % colors.length] },
      parametricEquation: getParametricEquation(startRatio, endRatio, false, false, k, 12),
      pieData: pieData[i],
    });

    startValue = endValue;
  }

  const option = {
    backgroundColor: "transparent",
    tooltip: {
      formatter: (params) => {
        const item = pieData[params.seriesIndex];
        const percent = ((item.value / sumValue) * 100).toFixed(1);
        return `${params.seriesName}<br/>占比：${percent}%`;
      },
    },
    grid3D: {
      show: true,
      boxHeight: 25, // 让立体感更强
      // top: "-5%",
      // left: "-5%",
      viewControl: {
        alpha: 30,
        beta: 0,
        distance: 250, // 缩小距离，让饼图更大
        rotateSensitivity: 2,
        zoomSensitivity: 0,
        panSensitivity: 0,
        autoRotate: true,
        autoRotateSpeed: 10,
      },
      light: {
        main: { intensity: 1.4, shadow: true },
        ambient: { intensity: 0.6 },
      },
    },
    xAxis3D: { min: -1, max: 1 },
    yAxis3D: { min: -1, max: 1 },
    zAxis3D: { min: -1, max: 1 },
    series,
  };
  return option;
}

// ===============================
// 初始化与更新逻辑
// ===============================
const initChart = () => {
  const dom = document.getElementById(props.ids);
  if (!dom) return;
  if (myChart) myChart.dispose();
  myChart = echarts.init(dom);
  const option = getPie3D(props.pieData, 0); // 实心饼图
  myChart.setOption(option);
};

onMounted(() => nextTick(initChart));

watch(
  () => props.pieData,
  () => nextTick(initChart),
  { deep: true, immediate: true }
);
</script>

<style scoped>
.chart-container {
  width: 100%;
  height: 100%;
}
</style>
