<script lang="ts" setup>
import * as echarts from 'echarts';
import { computed, onBeforeUnmount, onMounted, provide, Ref, ref, watch } from 'vue';
import { dayMetricsEnum, weekInitData } from '/src/views/reportManage/dataCenter/utils/enum';
import XEUtils from 'xe-utils';
import MetricsCards from '../MetricsCards/index.vue';
import emitter from '/src/utils/emitter';
import { parseQueryParams } from '/src/views/reportManage/dataCenter/utils/tools';
import { get } from 'lodash-es';

defineOptions({
  name: 'DataTendencyChart',
});

interface Props {
  fetchCard: Function;
  fetchCardWeek?: Function;
  fetchCardMonth?: Function;
  fetchLine: Function;
  fetchLineMonth?: Function;
  fetchLineWeek?: Function;
  query: { [key: string]: any };
  initMetric?: ShowMetric[];
  metricEnum?: { [key: string]: string }[];
}

const props = withDefaults(defineProps<Props>(), {
  initMetric: () => weekInitData.value,
  metricEnum: () => dayMetricsEnum,
});

const metrics = ref(props.initMetric);
const dataSet = ref([]);
const metricsItems: Ref<MetricData[]> = ref([]);
let chartObj: any;
const chartRef = ref();
const statDim = ref('day');
const option: any = {
  dataset: {
    source: [],
  },
  tooltip: {
    trigger: 'axis',
    axisPointer: {
      label: {
        backgroundColor: '#6a7985',
      },
    },
  },
  legend: {
    selected: {}, // 控制显隐
    show: false,
  },
  grid: {
    top: 50,
    right: 150,
    bottom: 30,
    left: 65,
  },
  xAxis: {
    type: 'category',
  },
  yAxis: [
    {
      id: 0,
      type: 'value',
      name: '',
      splitLine: {
        show: true, // 设置显示分割线
      },
      axisLine: {
        show: true,
        lineStyle: { color: '' },
      },
      show: true,
    },
    {
      id: 1,
      type: 'value',
      name: '',
      position: 'right',
      splitLine: {
        show: false,
      },
      axisLine: {
        show: true,
        lineStyle: {
          color: '',
        },
      },
      show: true,
    },
    {
      id: 2,
      type: 'value',
      position: 'right',
      offset: 90,
      name: '',
      splitLine: {
        show: false,
      },
      axisLine: {
        show: true,
        lineStyle: {
          color: '',
        },
      },
      show: true,
    },
  ],
  series: [
    {
      id: 0,
      name: '',
      type: 'bar',
      encode: {
        x: 'data_datetime',
        y: '',
      },
      barWidth: '16px',
      yAxisIndex: 0,
      itemStyle: {
        color: '',
        borderRadius: 4,
      },
    },
    {
      id: 1,
      name: '',
      type: 'line',
      encode: {
        x: 'data_datetime',
        y: '',
      },
      barWidth: '16px',
      yAxisIndex: 0,
      itemStyle: {
        color: '',
        borderRadius: 4,
      },
    },
    {
      id: 2,
      name: '',
      type: 'line',
      encode: {
        x: 'data_datetime',
        y: '',
      },
      symbolSize: 6,
      symbol: 'circle',
      smooth: true,
      yAxisIndex: 2,
      itemStyle: {},
      areaStyle: {},
      emphasis: {
        focus: 'series',
      },
    },
  ],
};
const loading = ref(true);
const queryParams = computed(() => parseQueryParams(props.query));
provide('statDim', statDim);

onMounted(() => {
  //getDataset()
  //getMetricsItems();
  addResize();
  setTimeout(() => {
    initLine();
  }, 0);
});

onBeforeUnmount(() => {
  if (chartObj) {
    chartObj.dispose();
    chartObj = null;
  }
  removeResize();
});

//初始化y轴
function initYAxis() {
  option.yAxis = metrics.value.map((metric, index) => ({
    id: index,
    name: metric.label,
    type: 'value',
    position: index === 0 ? 'left' : 'right',
    offset: index > 1 ? (index - 1) * 80 : 0,
    axisLine: { show: true, lineStyle: { color: metric.color } },
    splitLine: { show: index === 0 },
    show: true,
  }));
}

async function initLine() {
  chartObj = echarts.init(chartRef.value);
  option.dataset.source = dataSet.value;
  // 初始化系列和 y 轴
  option.series = metrics.value.map((metric, index) => ({
    id: index,
    name: metric.label,
    type: index === 0 ? 'bar' : 'line',
    encode: { x: 'data_datetime', y: metric.metric },
    yAxisIndex: index,
    itemStyle: { color: index === 0 ? '#0085ff' : metric.color, borderRadius: [6, 6, 6, 6] },
    lineStyle: { color: metric.color },
    barMaxWidth: '16px',
    areaStyle: index !== 0 ? {
      color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
        { offset: 0, color: metric.color + '53' },
        { offset: 1, color: metric.color + '03' },
      ]),
    } : undefined,
  }));
  initYAxis();

  // 初始化图例
  option.legend.selected = props.metricEnum.reduce((acc: any, metric) => {
    acc[metric.label] = metrics.value.some((m) => m.metric === metric.value);
    return acc;
  }, {});

  chartObj.setOption(option);

  // 获取所有 y 轴的刻度标签
  if (statDim.value !== 'week') {
    const salesLabels = ['销售额', '上年销售额', '上月销售额'];
    let commonMin = Infinity;
    let commonMax = -Infinity;

    option.yAxis.forEach((yAxis, index) => {
      if (salesLabels.includes(yAxis.name)) {
        const yAxisModel = chartObj.getModel().getComponent('yAxis', index);
        const [min, max] = yAxisModel.axis.scale.getExtent();
        commonMin = Math.min(commonMin, min);
        commonMax = Math.max(commonMax, max);
      }
    });

    // 确保标题为 "销售额"、"上年销售额" 和 "上月销售额" 的 y 轴使用相同的刻度标签
    option.yAxis.forEach((yAxis, index) => {
      if (salesLabels.includes(yAxis.name)) {
        option.yAxis[index] = {
          ...yAxis,
          min: commonMin,
          max: commonMax,
          interval: (commonMax - commonMin) / 5,
        };
      }
    });
    // 重新设置 option 以应用更改
    chartObj.setOption(option, true);
  }
  loading.value = false;
}

async function getDataset() {
  let resp;
  if (statDim.value === 'week') {
    if (props.fetchLineWeek) {
      resp = await props.fetchLineWeek(queryParams.value);
    }
  } else if (statDim.value === 'month') {
    if (props.fetchLineMonth) {
      resp = await props.fetchLineMonth(queryParams.value);
    }
  } else {
    resp = await props.fetchLine(queryParams.value);
  }
  dataSet.value = resp.data;
}

const getMetricsItems = async () => {
  let resp;
  if (statDim.value === 'week' && props.fetchCardWeek) {
    resp = await props.fetchCardWeek(queryParams.value);
  } else if (statDim.value === 'month' && props.fetchCardMonth) {
    resp = await props.fetchCardMonth(queryParams.value);
  } else if (props.fetchCard) {
    resp = await props.fetchCard(queryParams.value);
  }
  const data = resp.data;
  metricsItems.value.length = 0;
  XEUtils.arrayEach(props.metricEnum, (info) => {
    //console.log('info', info);
    const tmp: MetricData = {
      label: info.label,
      value: info.value,
      metricVal: data[info.value],
      gapVal: data[`gap${ info.value }`],
      preVal: data[`prev${ info.value }`],
    };
    // console.log('122', tmp);
    metricsItems.value.push(tmp);
  });
};

function changeMetric() {
  // 更新图例选中状态
  option.legend.selected = props.metricEnum.reduce((acc: any, metric) => {
    acc[metric.label] = metrics.value.some((m) => m.metric === metric.value);
    return acc;
  }, {});

  // 重新创建 series 数组，只包含选中的指标
  option.series = metrics.value.map((metric, index) => {
    const baseConfig: any = {
      id: index,
      name: metric.label,
      type: metric.color === '#0085ff' ? 'bar' : 'line',
      encode: { x: 'data_datetime', y: metric.metric },
      yAxisIndex: index,
      itemStyle: { color: metric.color, borderRadius: [6, 6, 6, 6] },
      lineStyle: { color: metric.color },
      barWidth: '16px',
    };

    if (baseConfig.type != 'bar') {
      baseConfig.areaStyle = {
        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
          { offset: 0, color: metric.color + '53' },
          { offset: 1, color: metric.color + '03' },
        ]),
      };
    }

    return baseConfig;
  });

  // 更新 y 轴显示状态
  option.yAxis = metrics.value.map((metric, index) => ({
    id: index,
    name: metric.label,
    type: 'value',
    position: index === 0 ? 'left' : 'right',
    offset: index > 1 ? (index - 1) * 80 : 0,
    axisLine: {
      show: true,
      lineStyle: { color: metric.color },
    },
    splitLine: { show: index === 0 },
    show: true,
  }));

  while (option.yAxis.length > metrics.value.length) {
    option.yAxis.pop();
  }

  chartObj.setOption(option, true); // 使用 true 作为第二个参数，强制完全刷新

  // 获取所有 y 轴的刻度标签
  if (statDim.value != 'week') {
    const salesLabels = ['销售额', '上年销售额', '上月销售额'];
    let commonMin = Infinity;
    let commonMax = -Infinity;

    option.yAxis.forEach((yAxis, index) => {
      if (salesLabels.includes(yAxis.name)) {
        const yAxisModel = chartObj.getModel().getComponent('yAxis', index);
        const [min, max] = yAxisModel.axis.scale.getExtent();
        commonMin = Math.min(commonMin, min);
        commonMax = Math.max(commonMax, max);
      }
    });

    // 确保标题为 "销售额"、"上年销售额" 和 "上月销售额" 的 y 轴使用相同的刻度标签
    option.yAxis.forEach((yAxis, index) => {
      if (salesLabels.includes(yAxis.name)) {
        option.yAxis[index] = {
          ...yAxis,
          min: commonMin,
          max: commonMax,
          interval: (commonMax - commonMin) / 5,
        };
      }
    });

    // 重新设置 option 以应用更改
    chartObj.setOption(option, true);

  }
  loading.value = false;
}

async function changeStatDim() {
  emitter.emit('DateTendency-dateChange', statDim.value);
  initYAxis();
  chartObj.setOption(option, true);
}

let initialized = false;
watch(props.query, async () => {
  if (!initialized) {
    initialized = true;
    return;
  }
  loading.value = true;
  await getMetricsItems();
  initYAxis();
  chartObj.setOption(option, true);
  await getDataset()
  await initLine();
  loading.value = false;
});

watch(
    () => props.initMetric,
    (newVal) => {
      metrics.value = newVal;
    },
    { immediate: true }
);

function resizeChart() {
  chartObj.resize();
}

function addResize() {
  window.addEventListener('resize', resizeChart);
}

function removeResize() {
  window.removeEventListener('resize', resizeChart);
}
</script>

<template>
  <div v-loading="loading">
    <MetricsCards v-model="metrics" :metric-items="metricsItems" @change="changeMetric"></MetricsCards>
    <el-radio-group v-model="statDim" class="chart-button-group" @change="changeStatDim">
      <el-radio-button label="day">日</el-radio-button>
      <el-radio-button :disabled="!props.fetchLineWeek" label="week">周</el-radio-button>
      <el-radio-button :disabled="!props.fetchLineWeek" label="month">月</el-radio-button>
    </el-radio-group>
    <div ref="chartRef" style="height: 350px"></div>
  </div>
</template>

<style scoped>
.metrics-cards {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  width: 100%;
}

.chart-button-group {
  display: flex;
  justify-content: flex-end;
  margin-top: 5px;
}
</style>
