<template>
  <div
    ref="bar_echart_horizontal"
    class="echart_content"
    :style="{ height: chartHeight + 'px' }"
  ></div>
</template>

<script setup lang="ts">
import {
  ref,
  watch,
  onMounted,
  onBeforeUnmount,
  nextTick,
  withDefaults,
} from "vue";
import _ from "lodash";
import * as echarts from "echarts";
import { getCompareAnalysis } from "@/utils/common";

// ================= 类型定义 =================
interface MarkLineItem {
  value: number;
  isShow?: boolean;
}

interface TooltipListItem {
  name?: string;
  value: any;
}

interface TooltipDataItem {
  rank?: string;
  list: TooltipListItem[];
}

interface Props {
  datax?: any[];
  datay?: number[];
  color?: string;
  isClick?: boolean;
  markNumber?: number | number[];
  markLineData?: MarkLineItem[];
  unit?: string;
  typeName?: string;
  tooltipData?: TooltipDataItem[];
}

// ================= Props & Emits =================
const props = withDefaults(defineProps<Props>(), {
  datax: () => [1, 2, 3, 4, 5, 6, 7],
  datay: () => [50, 60, 70, 80, 70, 70, 100],
  color: "#FAC858",
  isClick: false,
  markNumber: 65,
  markLineData: () => [],
  unit: "%",
  typeName: "",
  tooltipData: () => [],
});

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

// ================= 响应式数据 =================
const bar_echart_horizontal = ref<HTMLDivElement | null>(null);
const echart = ref<echarts.ECharts | null>(null);
const chartHeight = ref(0);

// ================= 方法 =================
// 设置图表高度
const SetChartHeight = () => {
  chartHeight.value = props.datax.length * 24 + 60;
  if (chartHeight.value < 380) chartHeight.value = 380;
  if (chartHeight.value > 600) chartHeight.value = 600;
  console.log("横向柱状图高度", chartHeight.value);
};

// 获取最大值计算规则
const GetMaxValue = (value: number) => {
  const thresholdMap = [
    { maxThreshold: 0.3, bound: 0.3 },
    { maxThreshold: 0.6, bound: 0.6 },
    { maxThreshold: 1, bound: 1 },
    { maxThreshold: 1.5, bound: 1.5 },
    { maxThreshold: 2, bound: 2 },
    { maxThreshold: 4, bound: 4 },
    { maxThreshold: 8, bound: 8 },
    { maxThreshold: 10, bound: 10 },
    { maxThreshold: 40, bound: 40 },
    { maxThreshold: 50, bound: 50 },
    { maxThreshold: 60, bound: 60 },
    { maxThreshold: 70, bound: 70 },
    { maxThreshold: 80, bound: 80 },
    { maxThreshold: 90, bound: 90 },
    { maxThreshold: 100, bound: 100 },
    { maxThreshold: 120, bound: 120 },
    { maxThreshold: 150, bound: 150 },
    { maxThreshold: 180, bound: 180 },
    { maxThreshold: 200, bound: 200 },
    { maxThreshold: 250, bound: 250 },
    { maxThreshold: 300, bound: 300 },
    { maxThreshold: 350, bound: 350 },
    { maxThreshold: 400, bound: 400 },
    { maxThreshold: 450, bound: 450 },
    { maxThreshold: 500, bound: 500 },
    { maxThreshold: 600, bound: 600 },
    { maxThreshold: 700, bound: 700 },
  ];
  const matchedRule = thresholdMap.find(
    ({ maxThreshold }) => value === maxThreshold || value < maxThreshold,
  );
  return matchedRule ? matchedRule.bound : Math.ceil(value / 10) * 10;
};

// 加载 echarts
const LoadEchart = () => {
  if (echart.value) {
    echart.value.dispose();
  }
  if (!bar_echart_horizontal.value) return;

  console.log("加载横向柱状图组件", props.datay);
  console.log("横向柱状图辅助线数据", props.markNumber);

  echart.value = echarts.init(bar_echart_horizontal.value, {
    devicePixelRatio: 2,
  });

  let totalWidth = bar_echart_horizontal.value.clientHeight;
  let singleSeriesWidth = Math.ceil((totalWidth - 97) / props.datax.length);

  const barMinWidth = 20;
  const dataZoomNum = Math.floor((totalWidth - 97) / (barMinWidth * 1));
  const dataZoomEnd = Math.floor((100 / props.datax.length) * dataZoomNum);

  let maxMarkNumber = 0;
  let markLineData: any[] = [];

  if (Object.prototype.toString.call(props.markNumber) === "[object Array]") {
    const markNumArr = props.markNumber as number[];
    maxMarkNumber = markNumArr.length ? Math.max(...markNumArr) : 0;
    markNumArr.forEach((item) => {
      markLineData.push({
        name: "辅助线",
        xAxis: item,
        label: {
          show: true,
          formatter: "{c}" + props.unit,
          position: "start",
          color: "#F56C6C",
          fontSize: 14,
        },
      });
    });
  } else if (props.markLineData?.length) {
    const markNumberArr: number[] = [];
    props.markLineData.forEach((item, index) => {
      markNumberArr.push(item.value);
      if (item.isShow) {
        markLineData.push({
          name: "辅助线",
          xAxis: item.value,
          label: {
            show: true,
            formatter: "{c}" + props.unit,
            position: "start",
            color: getCompareAnalysis[index],
            fontSize: 14,
          },
          lineStyle: { color: getCompareAnalysis[index] },
        });
      }
    });
    // 修复原代码逻辑：此处 markNumber 为 number，不应使用 .length
    maxMarkNumber = props.markNumber as number;
  } else {
    maxMarkNumber = props.markNumber as number;
    markLineData = [
      {
        name: "辅助线",
        xAxis: props.markNumber,
        label: {
          show: true,
          formatter: "{c}" + props.unit,
          position: "start",
          color: "#F56C6C",
          fontSize: 14,
        },
      },
    ];
  }

  let dataZoom = {
    start: 0,
    end: dataZoomEnd,
    type: "slider",
    show: true,
    borderColor: "transparent",
    borderCap: "round",
    yAxisIndex: [0],
    width: 8,
    right: 20,
    top: 20,
    bottom: 20,
    fillerColor: "transparent",
    zoomLock: true,
    handleSize: "0",
    handleStyle: { color: "#b8b8b8", borderWidth: 2 },
    backgroundColor: "transparent",
    showDataShadow: false,
    showDetail: false,
    filterMode: "filter",
  };

  const datay = props.datay.filter((num) => !isNaN(num));
  const maxValue = Math.max(...datay);
  const nearestValue = GetMaxValue(maxValue);
  let unit = props.unit;
  const typeName = props.typeName || "";

  let option: echarts.EChartsOption = {
    tooltip: {
      axisPointer: { type: "shadow" },
      trigger: "axis",
      triggerOn: "mousemove | click",
      renderMode: "html", // 修复拼写错误 renderModel -> renderMode
      confine: true,
      extraCssText:
        "border-radius: 4px;padding:5px 0px 5px 5px;white-space:normal;word-wrap:break-word;max-width: 400px;", // 修复拼写错误 word-warp -> word-wrap
      enterable: true,
      formatter: (params: any) => {
        let tooltip = `<div class='tooltip_content'>`;
        let title = params[0].name;
        let value = params?.value || params[0]?.value;
        if (props.tooltipData.length > 0) {
          if (typeName) {
            tooltip += `<div class='tooltip_title'>${title}</div>`;
            tooltip += `<div class='tooltip_student'>${typeName}：${value}${unit}</div>`;
          } else {
            let rank = props.tooltipData[params[0].dataIndex]?.rank || "";
            tooltip += `<div class='tooltip_title'>${title} ${rank}</div>`;
          }
          let list = props.tooltipData[params[0].dataIndex].list;
          for (let i = 0; i < list.length; i++) {
            let item = list[i];
            tooltip += item.name
              ? `<div class='tooltip_student'>${item.name}：${item.value}</div>`
              : `<div class='tooltip_student'>${item.value}</div>`;
          }
        } else {
          tooltip += `<div class='tooltip_title'>${title}</div>`;
          tooltip += `<div class='tooltip_student'>${typeName}：${value}${unit}</div>`;
        }
        tooltip += `</div>`;
        return tooltip;
      },
    },
    grid: { left: 40, right: 50, top: 20, bottom: 0, containLabel: true },
    dataZoom: singleSeriesWidth < barMinWidth ? dataZoom : null,
    yAxis: {
      type: "category",
      data: props.datax,
      axisPointer: { type: "shadow" },
      axisLabel: {
        formatter: "{value}",
        interval: 0,
        color: "#666666",
        fontSize: 14,
      },
      splitArea: { show: true, areaStyle: { color: ["#fafafa", "#ffffff"] } },
      inverse: true,
    },
    xAxis: {
      type: "value",
      axisLabel: {
        formatter: "{value}" + (unit == "%" ? unit : ""),
        color: "#666666",
        fontSize: 14,
        rotate: 0,
      },
      axisLine: { show: true, lineStyle: { color: "#E4E7ED", width: 1 } },
      splitLine: {
        show: false,
        lineStyle: { color: ["#E4E7ED"], width: 1, type: "solid" },
      },
      axisTick: { show: true, alignWithLabel: false },
      max: maxMarkNumber > nearestValue ? maxMarkNumber : nearestValue,
    },
    series: [
      {
        name: "",
        type: "bar",
        barMaxWidth: 50,
        barMinWidth: 14,
        itemStyle: { color: props.color },
        tooltip: { valueFormatter: (value: any) => value + unit },
        label: {
          show: true,
          position: "right",
          formatter: "{c}" + unit,
          color: "#666",
          fontSize: 14,
        },
        data: props.datay,
        markLine: props.markNumber
          ? {
              symbol: ["triangle", "none"],
              symbolSize: [8, 8],
              lineStyle: { type: "dashed", color: "#F56C6C", width: 1 },
              label: { formatter: "{c}" + props.unit, position: "start" },
              data: markLineData,
            }
          : null,
      },
    ],
  };

  echart.value.setOption(option);

  if (props.isClick) {
    let container = echart.value.getDom();
    let containerHeight = container.offsetHeight;
    // 获取 grid 区域偏移量 (使用 any 绕过部分内部 API 类型限制)
    const gridRect = (echart.value as any)
      .getModel()
      .getComponent("grid")
      .coordinateSystem.getRect();
    const yAxisDataLength = props.datax.length;
    const singleLabelHeight = gridRect.height / yAxisDataLength;

    echart.value.on("click", (params: any) => {
      if (params.componentSubType === "bar") {
        let pixelPosition = echart.value!.convertToPixel(
          { yAxisIndex: 0 },
          params.name,
        );
        echart.value!.setOption({
          graphic: {
            id: "highlight-box",
            type: "rect",
            shape: {
              y: pixelPosition - singleLabelHeight / 2,
              x: gridRect.x,
              width: gridRect.width,
              height: singleLabelHeight,
            },
            style: { fill: params.color + "30" },
          },
        });
        emit("HandleChartClick", params.dataIndex, params.name);
      }
    });

    let defaultPixelPosition = echart.value.convertToPixel(
      { yAxisIndex: 0 },
      props.datax[0],
    );
    echart.value.setOption({
      graphic: {
        id: "highlight-box",
        type: "rect",
        shape: {
          y: defaultPixelPosition - singleLabelHeight / 2,
          x: gridRect.x,
          height: singleLabelHeight,
          width: gridRect.width,
        },
        style: { fill: "rgba(84,112,198,0.1)" },
      },
    });
  }
};

// 监听窗口大小变化
const handleResize = _.throttle(() => {
  console.log("窗口变化了");
  nextTick(() => {
    LoadEchart();
  });
}, 500);

// ================= 侦听器 =================
watch(
  () => props.datay,
  () => {
    SetChartHeight();
    nextTick(() => {
      LoadEchart();
    });
  },
  { deep: true },
);

watch(
  () => props.markLineData,
  () => {
    LoadEchart();
  },
  { deep: true },
);

// ================= 生命周期 =================
onMounted(() => {
  window.addEventListener("resize", handleResize);
  SetChartHeight();
  nextTick(() => {
    LoadEchart();
  });
});

onBeforeUnmount(() => {
  window.removeEventListener("resize", handleResize);
  if (echart.value) {
    echart.value.dispose();
  }
});
</script>

<style lang="scss" scoped></style>
