<template>
  <div style="width: 100%; height: 500px">
    <!-- 时间范围选择器 -->
    <el-date-picker
      size="mini"
      v-model="dateRange"
      type="daterange"
      align="right"
      unlink-panels
      range-separator="至"
      start-placeholder="开始日期"
      end-placeholder="结束日期"
      @change="onDateRangeChange"
      style="margin: 20px 0 0 0"
    ></el-date-picker>

    <div
      v-loading="loading"
      :ref="`plotlyChart-${index}`"
      style="width: 100%; height: 450px"
    >
      <el-empty v-if="isError" description="请求失败"></el-empty>
    </div>
  </div>
</template>

<script>
import Plotly from "plotly.js-dist-min";
import axios from "axios";
import { myMixin } from "@/mixins/chartRequestMixin";

export default {
  name: "BoxPlotWithMedians",
  mixins: [myMixin],
  props: {
    fileAddr: {
      default: "",
      type: String,
    },
    index: {
      type: String,
    },
    setUpImgData: {
      default: () => [],
      type: Array,
    },
  },
  data() {
    return {
      chartData: {}, // 存储从 API 获取的原始数据
      dateRange: [], // 日期范围选择器的值
      loading: false,
      isError: false,
    };
  },
  mounted() {
    this.getData(); // 获取数据
  },
  watch: {
    setUpImgData: {
      handler(newType) {
        this.drawBoxPlot();
      },
      deep: true,
    },
  },
  methods: {
    // 获取数据
    async getData() {
      if (this.fileAddr !== "") {
        try {
          this.loading = true;
          this.cancelToken = axios.CancelToken.source();
          const resultChartsData = await axios.get(this.fileAddr, {
            cancelToken: this.cancelToken.token,
          });
          this.chartData = resultChartsData.data;
          this.drawBoxPlot(); // 绘制图表
          this.isError = false;
          this.loading = false;
        } catch (error) {
          this.isError = true;
          this.loading = false;
        }
      }
    },

    // 处理日期范围变化
    onDateRangeChange() {
      this.drawBoxPlot(); // 日期变化时重新绘制图表
    },

    // 判断时间戳是否在选择的日期范围内
    isInDateRange(timestamp) {
      const [startDate, endDate] = this.dateRange;
      if (!startDate || !endDate) return true;

      const date = new Date(timestamp);
      return date >= new Date(startDate) && date <= new Date(endDate);
    },

    // 过滤数据
    filterData(group) {
      const filteredXData = [];
      const filteredYData = [];
      const filteredMedians = group.medians ? { x: [], y: [] } : null;
      group.medians.x.forEach((timestamp, index) => {
        if (this.isInDateRange(timestamp)) {
          filteredMedians.x.push(timestamp);
          filteredMedians.y.push(group.medians.y[index]);
        }
      });
      group.xData.forEach((timestamp, index) => {
        if (this.isInDateRange(timestamp)) {
          filteredXData.push(timestamp);
          filteredYData.push(group.yData[index]);
        }
      });

      return {
        ...group,
        xData: filteredXData,
        yData: filteredYData,
        medians: filteredMedians,
      };
    },

    // 绘制箱线图
    drawBoxPlot() {
      const chartContainer = this.$refs[`plotlyChart-${this.index}`];
      const { data, xaixs, yaixs, analysisTypeCode } = this.chartData;

      // 过滤数据，根据选定的日期范围
      const filteredData = data.map(this.filterData);

      // 创建图表数据
      const traces = [];
      const medianMarkers = [];

      filteredData.forEach((group) => {
        traces.push({
          x: group.xData,
          y: group.yData,
          type: "box",
          name: group.title,
          marker: {
            color: group.color,
          },
          boxpoints: false, // 是否显示异常值
          boxmean: true, // 是否显示均值
          hovertemplate: (data) => {
            // 获取箱线图的统计数据
            const max = data.max; // 最大值
            const min = data.min; // 最小值
            const q1 = data.q1; // 下四分位数
            const q3 = data.q3; // 上四分位数
            const median = data.median; // 中位数
            const mean = data.mean; // 均值
            const iqr = q3 - q1; // 四分位距（IQR）
            const outliers = data.outliers || "无"; // 异常值（如果没有异常值，则显示“无”）

            return (
              `${xaixs}: %{x}<br>` + // 显示类别
              `<b>最大值</b>: ${max}<br>` + // 最大值
              `<b>最小值</b>: ${min}<br>` + // 最小值
              `<b>上四分位数 (Q3)</b>: ${q3}<br>` + // 上四分位数
              `<b>中位数 (Median)</b>: ${median}<br>` + // 中位数
              `<b>下四分位数 (Q1)</b>: ${q1}<br>` + // 下四分位数
              `<b>四分位距 (IQR)</b>: ${iqr}<br>` + // 四分位距
              `<b>均值 (Mean)</b>: ${mean}<br>` + // 均值
              `<b>异常值</b>: ${outliers}<br>` + // 异常值
              "<extra></extra>" // 额外的文本（可以留空）
            );
          },
        });

        // 如果有中位点数据且中位点数据不为空，添加中位点
        if (group.medians && group.medians.x.length > 0) {
          medianMarkers.push({
            x: group.medians.x,
            y: group.medians.y,
            mode: "markers",
            marker: {
              color: "#406DAB",
              size: 3,
            },
            name: `${group.title} - 中位点`,
            type: "scatter",
            hovertemplate: `${xaixs}: %{x} <br> ${yaixs}: %{y} <br><b>中位点</b>: %{y}<br><extra></extra>`,
          });
        }
      });

      const layout = {
        title: analysisTypeCode + data[0].engineName,
        xaxis: {
          title: xaixs,
          type: "date",
          tickformat: "%Y-%m-%d",
        },
        yaxis: {
          title: yaixs,
        },
        showlegend: true,
      };
      const getChartSetUp = (axisTitle) => {
        return this.setUpImgData.find((item) => item.text.includes(axisTitle));
      };
      // 更新x轴和y轴的范围与步长
      const xChartSetUp = getChartSetUp(layout.xaxis.title);
      if (xChartSetUp) {
        layout.xaxis.dtick = xChartSetUp.dtick;
        layout.xaxis.range = [xChartSetUp.min, xChartSetUp.max];
      }
      const yChartSetUp = getChartSetUp(layout.yaxis.title);
      if (yChartSetUp) {
        layout.yaxis.dtick = yChartSetUp.dtick;
        layout.yaxis.range = [yChartSetUp.min, yChartSetUp.max];
      }

      Plotly.newPlot(chartContainer, [...traces, ...medianMarkers], layout);
    },
  },
};
</script>

<style scoped>
/* 可根据需要自定义样式 */
</style>
