<template>
  <!-- 招商 - littlegreen - 补充form和label -->
  <div
    :class="className"
    :style="{ height: '100%', width: width, padding: '20px' }"
  >
    <div class="select-container">
      <el-form
        :model="form"
        :rules="rules"
        ref="ruleForm"
        style="
          display: grid;
          grid-template-columns: 1fr 1fr;
          align-items: center;
          grid-gap: 20px;
        "
      >
        <el-form-item
          label="新增企业月均工业产值"
          label-width="200px"
          prop="newMonthValue"
        >
          <div style="display: flex; align-items: cente">
            <el-input
              v-model.number="form.newMonthValue"
              placeholder="请输入企业月均工业产值"
              clearable
            />
            <p style="flex: 0 0 auto; margin: 0 10px">万元</p>
          </div>
        </el-form-item>
        <el-form-item label="行业代码" label-width="100px" prop="selectedCode">
          <el-select v-model="form.selectedCode" style="width: 100%" filterable>
            <el-option
              v-for="item in selectedIndustryArray"
              :key="item.key"
              :label="item.value"
              :value="item.key"
            >
            </el-option> </el-select
        ></el-form-item>
        <el-form-item
          label="新增企业年实缴税金"
          label-width="200px"
          prop="newYearTax"
        >
          <!-- <el-input
            v-model="form.newYearTax"
            placeholder="请输入企业年实缴税金"
            clearable
          /> -->
          <div style="display: flex; align-items: center">
            <el-input
              v-model.number="form.newYearTax"
              placeholder="请输入企业年实缴税金"
              clearable
            />
            <p style="flex: 0 0 auto; margin: 0 10px">万元</p>
          </div>
        </el-form-item>
        <el-form-item label="年度" style="margin-bottom: 0" label-width="100px" prop="selectedYear">
          <el-select v-model="form.selectedYear" style="width: 100%">
            <el-option
              v-for="item in selectedYearArray"
              :key="item.key"
              :label="item.value"
              :value="item.key"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label-width="100px">
          <el-button type="primary" size="mini" @click="submit">计算</el-button>
          <el-button icon="el-icon-refresh" size="mini" @click="resetForm"
            >重置</el-button
          >
        </el-form-item>
      </el-form>
    </div>
    <div>
      <h4 v-show="calShow == 'low'" style="padding: 10px; text-align: center">
        重新计算后输出：企业新增后比新增前行业得分平均降低{{ rate }}%
      </h4>
      <h4 v-show="calShow == 'high'" style="padding: 10px; text-align: center">
        重新计算后输出：企业新增后比新增前行业得分平均提高{{ rate }}%
      </h4>
      <h4 v-show="calShow == 'same'" style="padding: 10px; text-align: center">
        重新计算后输出：企业新增后与新增前行业得分平均一致
      </h4>
    </div>
    <div ref="chart" :style="{ height: height, width: width }"></div>
    <el-table :data="tableData" border style="width: 100%">
      <el-table-column prop="year" label="年度" width="200"> </el-table-column>
      <el-table-column prop="enterpriseId" label="企业ID"></el-table-column>
      <el-table-column
        prop="totalIndustrialValue"
        label="企业月均工业产值"
        width="200"
      ></el-table-column>
      <el-table-column
        prop="value"
        label="Z-score得分"
        width="200"
      ></el-table-column>
    </el-table>
  </div>
</template>

<script>
import * as echarts from "echarts";
import { listAllIndustry } from "@/api/industry/industry"; // 导入行业数据的接口
import { listAllIndustry_run } from "@/api/industry_run/industry_run"; // 导入行业数据的接口
require("echarts/theme/macarons"); // echarts theme
import resize from "@/views/dashboard/mixins/resize";
import { Decimal } from "decimal.js";
import { getIndexData } from "@/api/home";

export default {
  mixins: [resize],
  props: {
    className: {
      type: String,
      default: "chart",
    },
    width: {
      type: String,
      default: "100%",
    },
    height: {
      type: String,
      default: "400px",
    },
  },
  data() {
    return {
      selectedYearArray: [],
      calShow: "init",
      rate: null,
      chart: null,
      chartData: [],
      industryData: [],
      industryMap: new Map(),
      selectedDataKey: "totalIndustrialValueScore", // 默认选择的字段
      form: {
        selectedCode: null,
        newMonthValue: null,
        newYearTax: null,
        selectedYear: null
      },
      rules: {
        selectedCode: [
          { required: true, message: "请选择行业", trigger: "blur" },
        ],
        newMonthValue: [
          {
            required: true,
            message: "请输入企业月均工业产值",
            trigger: "blur",
          },
          { type: "number", message: "企业月均工业产值必须为数字" },
        ],
        newYearTax: [
          {
            type: "number",
            message: "企业年实缴税金必须为数字",
            trigger: "blur",
          },
        ],
        selectedYear: [
          { required: true, message: "请选择年度", trigger: "blur" },
        ]
      },
      selectedIndustryArray: [],
      selectedYear: null,
      selectedRange: 0.1, // 不能为 0， - littlegreen - 固定0.1
      // littlegreen - 检测区间 和 表格数据
      detectMin: null,
      detectMax: null,
      tableData: [],
      scoreData: [],
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.fetchData();
    });
  },
  beforeDestroy() {
    if (this.chart) {
      this.chart.dispose();
    }
  },
  methods: {
    // 拉取初始数据
    async fetchData() {
      const that = this;
      // 获得所有行业
      // that.selectedYear = new Date().getUTCFullYear() + "";
      await listAllIndustry()
        .then((res) => {
          if (res && res?.rows) {
            that.selectedIndustryArray = res.rows.map((item) => {
              return {
                key: item.code,
                value: item.code + item.industryName,
              };
            });
          }
        })
        .catch((error) => {
          console.error("Error fetching data:", error);
        });

      await getIndexData({
        year: 0,
      })
        .then((res) => {
          if (res && res?.rows) {
            that.selectedYearArray = res.rows[0].years.map((v) => {
              return {
                key: v,
                value: v,
              };
            });
          }
        })
        .catch((error) => {
          console.error("Error fetching data:", error);
        });
    },
    // 提交表单
    submit() {
      this.$refs.ruleForm.validate((valid) => {
        if (valid) {
          this.handleData();
        } else {
          console.error("error submit!!");
          return false;
        }
      });
    },
    // 处理数据
    handleData() {
      // 1.拿当前年份和code的企业运行数据过来
      // 2.计算每个企业的z-score
      // 3.画图
      const that = this;
      listAllIndustry_run({
        code: that.form.selectedCode,
        year: that.form.selectedYear,
      })
        .then((res) => {
          if (res && res.rows) {
            that.scoreData = res.rows;
            that.initChart();
          }
        })
        .catch((error) => {
          console.error("Error fetching data:", error);
        });
    },
    initChart() {
      if (this.chart) {
        this.chart.dispose();
      }
      this.chart = echarts.init(this.$refs.chart, "macarons");
      this.updateChart();
    },
    updateChart() {
      const that = this;
      if (!this.chart) {
        return;
      }
      let newMonthValue = new Decimal(that.form.newMonthValue).toNumber();
      let total = [newMonthValue]; //总值
      const result = Object.values(
        that.scoreData.reduce((acc, item) => {
          const key = item.enterpriseName; // 根据企业名称分组
          let totalIndustrialValue = new Decimal(item.totalIndustrialValue);
          if (!acc[key]) {
            acc[key] = {
              name: key,
              data: [],
              totalValue: new Decimal(0),
              count: 0,
            }; // 创建对象并初始化
          }

          acc[key].data.push(item); // 添加到对应的类别中
          acc[key].totalValue = acc[key].totalValue.plus(totalIndustrialValue); // 累加 totalIndustrialValue
          acc[key].count++; // 企业数 +1
          return acc;
        }, {})
      ).map(({ name, data, totalValue, count }) => {
        const totalIndustrialValue = totalValue.dividedBy(count).toNumber(); // 计算均值
        total.push(totalIndustrialValue);
        return { name, data, totalIndustrialValue }; // 返回结果
      });
      result.push({
        name: "新企业",
        data: [],
        totalIndustrialValue: newMonthValue,
      });

      // littlegreen --计算增加新企业之后工业产值变化 计算全体企业 totalIndustrialValue 均值
      const totalValues = result.map(
        (e) => new Decimal(e.totalIndustrialValue)
      );
      const overallMean = totalValues
        .reduce((sum, value) => sum.plus(value), new Decimal(0))
        .dividedBy(totalValues.length);

      // 计算不包括“新企业”的均值
      const filteredValues = result
        .filter((e) => e.name !== "新企业")
        .map((e) => new Decimal(e.totalIndustrialValue));

      const filteredMean = filteredValues
        .reduce((sum, value) => sum.plus(value), new Decimal(0))
        .dividedBy(filteredValues.length);
      const relativeChange = overallMean.minus(filteredMean).dividedBy(filteredMean).mul(new Decimal(100));
      // 显示增加/降低/一致
      that.calShow = relativeChange.greaterThan(0) ? "high" : (relativeChange.lessThan(0)? "low" : "same")
      // 增加的比率
      that.rate = relativeChange.abs().toNumber().toFixed(2)

      // 获取基础数据：最大值，最小值，平均值，标准差
      function getBebeQ(numbers, digit = 2) {
        let sum = numbers.reduce(
          (acc, num) => acc.add(new Decimal(num)),
          new Decimal(0)
        );

        let max = Math.max.apply(null, numbers);
        let min = Math.min.apply(null, numbers);

        // 平均值
        let mean = sum.dividedBy(numbers.length);

        // 计算每个数与均值的差的平方
        const squaredDiffs = numbers.map((num) => {
          const diff = new Decimal(num).minus(mean);
          return diff.pow(2);
        });

        // 计算平方差的均值
        const sumOfSquaredDiffs = squaredDiffs.reduce(
          (acc, diff) => acc.add(diff),
          new Decimal(0)
        );

        const variance = sumOfSquaredDiffs.dividedBy(numbers.length);

        // 开平方得到标准差
        const standardDeviation = variance.sqrt();

        // 向上取整到最近的 0.1
        const ceilingRoundedMax = Math.ceil(max * 10) / 10;

        // 向下取整到最近的 0.1
        const floorRoundedMin = Math.floor(min * 10) / 10;

        return {
          max: ceilingRoundedMax,
          min: floorRoundedMin,
          avg: parseFloat(mean.toNumber().toFixed(digit)) || 0,
          stdDev: parseFloat(standardDeviation.toNumber().toFixed(digit)),
        };
      }

      // 示例数据
      const betaData = getBebeQ(total);
      let newZScore;
      const values = result.map((item) => {
        let num = item.totalIndustrialValue;
        const zScore = new Decimal(num)
          .minus(betaData.avg)
          .dividedBy(betaData.stdDev);
        let scoreNum = zScore.toNumber();
        if (new Decimal(num).equals(new Decimal(that.form.newMonthValue))) {
          newZScore = scoreNum;
        }
        item.score = scoreNum;
        return scoreNum;
      });
      // 计算 z-score 的基础数据
      const scoreBasic = getBebeQ(values);
      const center = new Decimal(scoreBasic.avg); // 确保 center 是 Decimal 类型
      const interval = new Decimal(0.1);

      // 使用 Decimal 来处理 minLimit 和 maxLimit
      let minLimit = new Decimal(scoreBasic.min); // 向下取整到最近的0.1
      let maxLimit = new Decimal(scoreBasic.max); // 向上取整到最近的0.1

      // 确保 minLimit 和 maxLimit 关于 center 对称
      if (!center.minus(minLimit).equals(maxLimit.minus(center))) {
        const distanceToCenter = center
          .minus(minLimit)
          .gt(maxLimit.minus(center))
          ? center.minus(minLimit)
          : maxLimit.minus(center);

        maxLimit = center.plus(distanceToCenter); // 更新 maxLimit 保持对称
        minLimit = center.minus(distanceToCenter); // 更新 minLimit 保持对称
      }

      const intervals = [];
      // 乘以1000 是将小数变成整数去计算，小数计算会有误差
      for (
        let i = minLimit * 1000;
        i <= maxLimit * 1000;
        i += interval * 1000
      ) {
        intervals.push(parseFloat((i / 1000).toFixed(2)));
      }
      // // 计算每个间隔的频次
      const frequency = new Array(intervals.length - 1).fill(0); // 初始化频次数组

      let intervalArr = intervals.slice(0, -1);
      const intervalStrings = [];
      for (let i = 0; i < intervalArr.length; i++) {
        const start = intervalArr[i].toFixed(1); // 保留一位小数
        const end = ((intervalArr[i] * 1000 + interval * 1000) / 1000).toFixed(
          1
        ); // 保留一位小数
        intervalStrings.push({
          name: `${start}-${end}`,
          max: end,
          min: start,
        }); // 构建区间字符串
      }

      values.forEach((value) => {
        for (let j = 0; j < intervalStrings.length; j++) {
          // 保证包含右边界
          let v = parseFloat(value) * 1000;
          if (
            v >= parseFloat(intervalStrings[j].min) * 1000 &&
            v < parseFloat(intervalStrings[j].max) * 1000
          ) {
            frequency[j]++;
            break; // 找到对应区间后可以跳出循环
          }
        }
      });

      // // 确保处理最大值等于maxLimit的情况
      if (
        values.some(
          (value) => parseFloat(value) * 1000 == parseFloat(maxLimit) * 1000
        )
      ) {
        frequency[frequency.length - 1]++;
      }
      // 1.计算正态分布值
      const normalDistributionValues = intervals
        .slice(0, -1)
        .map((intervalStart, index) => {
          const intervalEnd = intervals[index + 1];
          const midpoint = (intervalStart + intervalEnd) / 2;

          // 使用 Decimal 进行更高精度的计算
          const midPointDecimal = new Decimal(midpoint);
          const avgDecimal = new Decimal(scoreBasic.avg);
          const stdDevDecimal = new Decimal(scoreBasic.stdDev);

          const exponent = midPointDecimal
            .minus(avgDecimal)
            .dividedBy(stdDevDecimal)
            .pow(2)
            .negated()
            .dividedBy(new Decimal(2));
          const exponentValue = new Decimal(Math.exp(exponent.toNumber())); // 取自然指数
          const coefficient = new Decimal(1).dividedBy(
            stdDevDecimal.times(new Decimal(Math.sqrt(2 * Math.PI)))
          );

          return coefficient.times(exponentValue).toNumber(); // 返回计算结果
        });
      const option = {
        color: ["rgba(245,0,0,0.6)"],
        dataZoom: [
          {
            type: "inside", // 内置于坐标系中
            start: 0,
            end: 100,
            xAxisIndex: [0],
          },
        ],
        tooltip: {
          trigger: "axis",
          axisPointer: {
            type: "shadow",
          },
          formatter: (params) => {
            // 使用箭头函数来保持 this 的上下文
            const seriesName = params[0].name; // 系列名称
            const dataIndex = params[0].dataIndex; // 数据索引
            const value = params[0].data; // 实际的数据值
            const xAxisLabel = params[0].axisValueLabel; // x轴的标签
            const yAxisLabel = params[0].seriesName;
            // 构建自定义的 tooltip 内容，包含年份
            return `${xAxisLabel}</br> ${yAxisLabel}： ${value} `;
          },
        },
        legend: {
          data: [`${that.form.selectedYear}工业生产总值企业数统计`, "正态分布"],
        },
        grid: {
          left: "3%",
          right: "4%",
          bottom: "50px",
          containLabel: true,
        },
        xAxis: {
          type: "category",
          name: "分布区间",
          // data: histogramData.map((item) => item.name),
          data: intervalStrings.map((item) => item.name),
          axisLabel: {
            fontSize: 12,
            rotate: 0,
            // padding: [0, 0, 0, -200]
          },
        },
        yAxis: [
          {
            name: "企业数",
            type: "value",
            minInterval: 1,
          },
          {
            name: "正态分布",
            type: "value",
          },
        ],
        series: [
          {
            name: `${that.form.selectedYear}工业生产总值企业数统计`,
            type: "bar",
            barWidth: "30%",
            itemStyle: {
              // color: "rgba(245,0,0,0.6)",
              normal: {
                color: function (params) {
                  const value = params.dataIndex; // 获取当前柱子在数据中的索引
                  let min = parseFloat(intervalStrings[value].min) * 1000;
                  let max = parseFloat(intervalStrings[value].max) * 1000;
                  if (newZScore * 1000 >= min && newZScore * 1000 < max) {
                    return "#ffcc00";
                  } else if (
                    newZScore * 1000 == maxLimit * 1000 &&
                    max == maxLimit * 1000
                  ) {
                    return "#ffcc00";
                  }
                  return "rgba(245,0,0,0.6)";
                  // 默认颜色
                },
              },
            },
            // data: histogramData.map((item) => item.value),
            data: frequency,
            label: {
              show: false, // 将show属性设置为false，去掉柱子上的数字
            },
          },
          {
            name: "正态分布",
            yAxisIndex: 1,
            type: "line",
            data: normalDistributionValues,
            lineStyle: {
              color: "#1a7cc8",
            },
            symbol: "none",
          },
        ],
      };
      this.chart.setOption(option);
      this.chart.on("click", function (param) {
        if (
          typeof param.dataIndex === "number" &&
          param.dataIndex >= 0 &&
          param.dataIndex < intervalStrings.length
        ) {
          let dataIndexValue = intervalStrings[param.dataIndex];
          const filteredArray = result.filter((item) => {
            let score = new Decimal(item.score);
            let max = new Decimal(dataIndexValue.max);
            let min = new Decimal(dataIndexValue.min);
            let maxL = new Decimal(maxLimit);
            const isMaxValEqual = max.equals(maxL);
            const lowerBoundCheck = score.greaterThan(min) || score.equals(min);
            const upperBoundCheck = isMaxValEqual
              ? score.lessThan(max) || score.equals(max)
              : score.lessThan(max);
            return lowerBoundCheck && upperBoundCheck;
          });
          that.tableData = filteredArray.map((item) => {
            return {
              totalIndustrialValue: item.totalIndustrialValue.toFixed(2),
              enterpriseId: item.name,
              year: that.form.selectedYear,
              value: item.score.toFixed(2),
            };
          });
        }
      });
    },
    // 重置表单
    resetForm() {
      this.$refs.ruleForm.resetFields();
      this.calShow = "init";
    },
  },
  watch: {},
};
</script>

<style scoped>
.select-container {
  margin: 10px 0;
  font-size: 16px; /* 调整字号大小 */
}

.select-container select {
  padding: 10px 20px; /* 增加内边距 */
  margin-right: 10px; /* 增加右边距 */
  border: 1px solid #121315; /* 蓝色边框 */
  border-radius: 4px; /* 圆角边框 */
  background-color: white; /* 背景色 */
  color: #121315; /* 文字颜色 */
  font-size: 16px; /* 调整字号大小 */
  cursor: pointer; /* 鼠标悬停时的指针样式 */
  outline: none; /* 移除焦点时的轮廓 */
}

.select-container select:hover {
  border-color: #1a7cc8; /* 鼠标悬停时的边框颜色 */
}

.select-container select:focus {
  border-color: #121315; /* 焦点时的边框颜色 */
  box-shadow: 0 0 0 2px rgba(64, 159, 255, 0.2); /* 焦点时的阴影效果 */
}
</style>
