<template>
  <div class="echart_content" style="overflow: hidden;">
    <div class="is_show_all" v-if="showCheckBox">
      <el-checkbox
        v-model="allSeriesSelected"
        :indeterminate="isIndeterminate"
        @change="toggleChangeAll(allSeriesSelected)"
      >
        显示全部
      </el-checkbox>
    </div>
    <!-- 雷达图容器 -->
    <div
      ref="radarChartRef"
      class="chart_box"
      :style="{ height: reportHeight ? reportHeight : `${height}px` }"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, watch, onMounted, onBeforeUnmount, nextTick } from "vue";
import type { ECharts, EChartsOption, RadarSeriesOption, LegendComponentOption } from "echarts";
import * as echarts from "echarts";
import { getGGroupColor, getScorePerformanceAnalysis } from "@/utils/common";

// ====================== 类型定义 ======================
/** G组颜色对象类型 */
type GColorItem = {
  name: string;
  color: string;
};

/** 表格数据源行：[维度名称, 数值1, 数值2...] */
type DataRow = (string | number)[];
type ChartData = DataRow[];

/** Radar 指示器配置 */
type RadarIndicator = {
  name: string;
  max: number | null;
  min: number | null;
  axisLabel: { show: boolean; formatter?: string; textStyle?: Record<string, any> };
  color: string;
  nameTextStyle: { fontSize?: number; fontWeight: string };
};

// ====================== Props 定义 ======================
interface Props {
  showCheckBox?: boolean;
  height?: number;
  reportHeight?: number | string;
  showLegend?: boolean;
  legengAlign?: string;
  showTooltip?: boolean;
  showDataLabel?: boolean;
  unit?: string;
  legendList?: string[];
  legendLeft?: string;
  colorType?: "gColors" | "colors";
  color?: string[];
  data: ChartData;
  isClick?: boolean;
  showRadiusAxis?: boolean;
  fontSize?: number | string;
  fontColor?: string;
  legendWidth?: number | string;
}
const props = withDefaults(defineProps<Props>(), {
  showCheckBox: true,
  height: 400,
  reportHeight: "",
  showLegend: true,
  legengAlign: "110px",
  showTooltip: true,
  showDataLabel: false,
  unit: "%",
  legendList: () => [],
  legendLeft: "110px",
  colorType: "colors",
  color: () => [],
  isClick: false,
  showRadiusAxis: true,
  fontSize: "",
  fontColor: "",
  legendWidth: "auto",
});

// ====================== Emits 定义 ======================
interface Emits {
  (e: "HandleChartClick", index: number, name: string): void;
}
const emit = defineEmits<Emits>();

// ====================== 响应式状态 ======================
const radarChartRef = ref<HTMLDivElement | null>(null);
let myChart: ECharts | null = null;

const allSeriesSelected = ref<boolean>(false);
const isIndeterminate = ref<boolean>(false);
const gColors = ref<GColorItem[]>(getGGroupColor());
const colors = ref<string[]>(getScorePerformanceAnalysis());
const legendSelected = ref<Record<string, boolean>>({});
const legenSelectList = ref<string[]>([]);

// ====================== 工具方法 ======================
/** 销毁 echarts 实例 */
function disposeChart() {
  if (myChart) {
    myChart.dispose();
    myChart = null;
  }
}

/** 窗口自适应 */
function resizeFn() {
  myChart?.resize();
}

/** 切换全部图例显示/隐藏 */
function toggleChangeAll(show: boolean) {
  if (!props.showCheckBox || !myChart) return;
  const opt = myChart.getOption();
  const legendData: string[] = opt.legend[0].data;
  legendData.forEach((name) => {
    myChart!.dispatchAction({
      type: show ? "legendSelect" : "legendUnSelect",
      name,
    });
  });
  allSeriesSelected.value = show;
  isIndeterminate.value = false;
}

/** 图例切换回调 */
function handleLegendSelectChanged(params: { selected: Record<string, boolean> }) {
  if (!myChart) return;
  const opt = myChart.getOption();
  const legendData: string[] = opt.legend[0].data;
  const selected = params.selected;
  legendSelected.value = selected;

  const allSelected = legendData.every((name) => selected[name]);
  const noneSelected = legendData.every((name) => !selected[name]);
  const someSelected = !allSelected && !noneSelected;

  if (noneSelected) allSeriesSelected.value = false;
  if (allSelected) allSeriesSelected.value = true;
  isIndeterminate.value = someSelected;
}

/** 绑定雷达图指示器点击事件 */
function bindChartNameEvents(indicators: RadarIndicator[]) {
  if (!myChart) return;
  myChart.on("click", (params: any) => {
    if (params.componentType === "radar" && params.targetType === "axisName") {
      const name = params.name as string;
      const dataList = props.data.slice(1).map((row) => String(row[0]));
      const index = dataList.indexOf(name);

      const newIndicators = indicators.map((item, key) => ({
        ...item,
        color: key === index ? "#2e64fa" : "#666666",
        nameTextStyle: {
          ...item.nameTextStyle,
          fontWeight: key === index ? "bold" : "normal",
        },
      }));

      myChart.setOption({
        radar: { indicator: newIndicators },
      });
      emit("HandleChartClick", index, name);
    }
  });
}

/** 初始化渲染雷达图 */
function initChart() {
  if (!radarChartRef.value) return;
  disposeChart();

  myChart = echarts.init(radarChartRef.value, null, { devicePixelRatio: 2 });

  // 初始化选中图例列表，统一转为 string
  if (props.legendList.length > 0) {
    legenSelectList.value = [...props.legendList];
  } else {
    legenSelectList.value = props.data[0]?.slice(1).map((v) => String(v)) ?? [];
  }

  // 构造雷达指示器
  const indicators: RadarIndicator[] = props.data.slice(1).map((row, index) => {
    const name = String(row[0]);
    return {
      name,
      max: props.unit === "%" ? 100 : null,
      min: props.unit === "%" ? 0 : null,
      axisLabel:
        props.showRadiusAxis && index === 0
          ? {
              show: true,
              formatter: `{value}${props.unit}`,
              textStyle: {
                fontSize: props.fontSize || 12,
                color: "#666",
              },
            }
          : { show: false },
      color: props.isClick && index === 0 ? "#2e64fa" : props.fontColor || "#666666",
      nameTextStyle: {
        fontSize: props.fontSize || 14,
        fontWeight: props.isClick && index === 0 ? "bold" : "normal",
      },
    };
  });

  // 图例维度名称
  const legendData = props.data[0]?.slice(1).map((v) => String(v)) ?? [];

  // 生成颜色列表
  let colorList: string[] = [];
  if (props.colorType === "gColors") {
    colorList = legendData.map((item) => {
      const findColor = gColors.value.find((g) => g.name === item);
      return findColor?.color ?? "#848BDC";
    });
  } else {
    colorList = props.color.length > 0 ? props.color : colors.value;
  }

  // 初始化图例选中状态
  const tempLegendSelected: Record<string, boolean> = {};
  legendData.forEach((dim) => {
    tempLegendSelected[dim] = false;
  });
  legenSelectList.value.forEach((item) => {
    tempLegendSelected[item] = true;
  });
  legendSelected.value = tempLegendSelected;

  // 更新全选状态
  allSeriesSelected.value = legenSelectList.value.length === legendData.length;
  isIndeterminate.value =
    legenSelectList.value.length > 0 && legenSelectList.value.length < legendData.length;

  // 构造 series 数据
  const seriesData = legendData.map((grade, gradeIndex) => {
    const values = props.data.slice(1).map((row) => Number(row[gradeIndex + 1]));
    return {
      name: grade,
      value: values,
      label: {
        show: props.showDataLabel,
        position: "outside",
        formatter: `{value}${props.unit}`,
      },
    };
  });

  // 非百分比时自动计算 min/max
  if (props.unit !== "%") {
    let maxValue = -Infinity;
    let minValue = Infinity;
    seriesData.forEach((item) => {
      item.value.forEach((num) => {
        maxValue = Math.max(maxValue, num);
        minValue = Math.min(minValue, num);
      });
    });
    indicators.forEach((item) => {
      item.max = Math.ceil(maxValue);
      item.min = Math.floor(minValue);
    });
  }

  // ECharts Option
  const option: EChartsOption = {
    emphasis: { blurScope: "global" },
    legend: {
      show: props.showLegend,
      data: legendData,
      width: props.legendWidth,
      top:0,
      left: props.legendLeft,
      itemGap: 20,
      itemHeight: 10,
      itemWidth: 20,
      textStyle: { fontSize: 12, color: "#333" },
      icon: "path://M352.64 526.336a158.272 158.272 0 0 0 2.56 17.664H96v-64h259.2a161.952 161.952 0 0 0-2.336 15.232A160 160 0 0 1 672 512a160.992 160.992 0 0 0-3.2-32H928v64h-259.2q1.12-5.504 1.824-11.104a160 160 0 0 1-318.016-6.4zM416 512a96 96 0 1 0 96-96 96 96 0 0 0-96 96z m254.72 20.224v-0.576z m-318.08-5.888v-1.664q-0.064 0.832 0 1.664z m-0.16-2.08v-1.248a5.44 5.44 0 0 0 0 1.248z m0-2.08v-0.928z m0-2.048zM352 518.08z m0-2.048zM352 512v-4.096V512z m0-5.344v-0.736 0.736z m0-2.56z m0.256-4.128z m0-1.664z m0-1.6v-0.992z",
      selectedMode: true,
      selected: legendSelected.value,
      type: "scroll",
      pageButtonItemGap: 5,
      pageButtonPosition: "end",
      orient: "horizontal",
      alignTo: "none",
      pageIconColor: "#999",
      pageIconInactiveColor: "#ccc",
    } as LegendComponentOption,
    tooltip: {
      show: props.showTooltip,
      triggerOn: "mousemove | click",
      renderMode: "html",
      confine: true,
      extraCssText: "border-radius: 4px;white-space:normal;word-wrap:break-word;max-width: 400px;",
      enterable: true,
      formatter: (params: any[]) => {
        const opt = myChart!.getOption();
        const radarIndicators = opt.radar[0].indicator as RadarIndicator[];
        let tooltipContent = `<div class='tooltip_content'>`;
        const title = params[0].name;
        tooltipContent += `<div class='tooltip_title'>${title}</div>`;
        radarIndicators.forEach((item, index) => {
          if (item.name) {
            const value = params[0].value[index];
            tooltipContent += `<div class='tooltip_student'>${item.name}：${value}${props.unit}</div>`;
          }
        });
        return tooltipContent;
      },
    },
    color: colorList,
    radar: {
      indicator: indicators,
      shape: indicators.length < 3 ? "circle" : undefined,
      splitNumber: 5,
      startAngle: 90,
      splitLine: { show: true },
      axisLabel: { show: false },
      splitArea: {
        show: true,
        areaStyle: {
          opacity: 0.1,
          color: ["#f0f8ff", "#e0f7fa", "#fff3e0", "#efebe9", "#f5f5f5"],
        },
      },
      radiusAxis: {
        type: "value",
        min: 0,
        max: 100,
        interval: 20,
        splitLine: { show: true, lineStyle: { color: "#eee" } },
        splitArea: { show: false },
      },
      axisLine: {
        show: props.data.length < 3 ? false : true,
        lineStyle: { color: "#999" },
      },
      center: props.reportHeight ? ["50%", "50%"] : props.showLegend ? ["50%", "55%"] : ["50%", "55%"],
    },
    triggerEvent: true,
    series: [
      {
        type: "radar",
        symbol: "circle",
        symbolSize: 7,
        data: seriesData,
        itemStyle: { opacity: 1 },
        emphasis: {
          symbol: "none",
          focus: "self",
          itemStyle: { opacity: 1, borderWidth: 2 },
          areaStyle: { opacity: 0.1 },
        },
        blur: {
          symbol: "none",
          itemStyle: { opacity: 0.2 },
          lineStyle: { opacity: 0.2 },
        },
      } as RadarSeriesOption,
    ],
  };

  myChart.setOption(option);

  // 绑定事件
  myChart.off("legendselectchanged");
  myChart.on("legendselectchanged", handleLegendSelectChanged);

  if (props.isClick) {
    bindChartNameEvents(indicators);
  }

  window.addEventListener("resize", resizeFn);
}

// ====================== 监听 & 生命周期 ======================
watch(
  () => allSeriesSelected.value,
  (newVal) => {
    toggleChangeAll(newVal);
  }
);

watch(
  () => props.data,
  () => {
    initChart();
  },
  { deep: true }
);

onMounted(() => {
  initChart();
});

onBeforeUnmount(() => {
  window.removeEventListener("resize", resizeFn);
  disposeChart();
});
</script>

<style lang="scss" scoped>
//图标外层公共样式
.echart_content {
  position: relative;
  width: 100%;
  margin: auto;
  min-height: 360px;
  height: auto;
  .is_show_all {
    position: absolute;
    top: -4px;
    left: 5px;
  }

  .chart_box {
    width: 100%;
    height: 400px;
  }
}

//弹窗悬浮层样式更改
.echart_content::-webkit-scrollbar {
  width: 100%;
  height: 8px;
  /* 设置滚动条宽度为8像素 */
  background-color: transparent;
}

/* 滑块样式 */
.echart_content::-webkit-scrollbar-thumb {
  background-color: #b8b8b8;
  /* 设置滑块颜色为深灰色 */
  border-radius: 4px;
  /* 设置滑块边角半径为4像素 */
  min-height: 40px;//设置手柄最小高度
}

/* 滚动条轨道内部空白区域样式 */
.echart_content::-webkit-scrollbar-track {
  background-color: #f0f0f0;
  /* 设置轨道背景色为浅灰色 */
}

/* 滚动条两端按钮样式 */
.echart_content::-webkit-scrollbar-button {
  display: none;
  /* 不显示按钮 */
}

/* 交叉点处的区域样式 */
.echart_content::-webkit-scrollbar-corner {
  background-color: transparent;
  /* 设置交叉点处的背景色为透明 */
}

/* 调整大小手柄样式 */
.echart_content::-webkit-resizer {
  display: none;
  /* 不显示调整大小手柄 */
}
</style>