<script lang="ts" setup>
import { computed, onBeforeUnmount, onMounted, Ref, ref, watch } from 'vue';
import * as echarts from 'echarts';
import { spCampaignMetricsEnum } from '/@/views/adManage/utils/enum.js';
import MetricsCards from '/@/components/MetricsCards/index.vue';
import XEUtils from 'xe-utils';
import { parseQueryParams } from '/@/views/adManage/utils/tools.js';

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

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

const props = withDefaults(defineProps<Props>(), {
  initMetric: () => [
    { metric: 'Impression', color: '#0085ff', label: '曝光量' },
    { metric: 'Click', color: '#3fd4cf', label: '点击量' },
    { metric: 'Spend', color: '#ff9500', label: '花费' },
  ],
  metricEnum: () => spCampaignMetricsEnum,
});

const metrics = ref(props.initMetric);
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: 'Name',
        y: '',
      },
      barWidth: '16px',
      yAxisIndex: 0,
      itemStyle: {
        color: '',
        borderRadius: [4, 4, 4, 4],
      },
    },
    {
      id: 1,
      name: '',
      type: 'line',
      encode: {
        x: 'Name',
        y: '',
      },
      symbolSize: 6,
      symbol: 'circle',
      smooth: true,
      yAxisIndex: 1,
      itemStyle: {
        // color: '#ff9500',
        // borderColor: '#ff9500'
      },
      areaStyle: {
        // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
        //   { offset: 0, color: '#3fd4cf53' },
        //   { offset: 1, color: '#3fd4cf03' },
        // ]),
      },
      emphasis: {
        focus: 'series',
      },
    },
    {
      id: 2,
      name: '',
      type: 'line',
      encode: {
        x: 'Name',
        y: '',
      },
      symbolSize: 6,
      symbol: 'circle',
      smooth: true,
      yAxisIndex: 2,
      itemStyle: {},
      areaStyle: {},
      emphasis: {
        focus: 'series',
      },
    },
  ],
};
const loading = ref(true);
const queryParams = computed(() => parseQueryParams(props.query));

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

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

watch(props.query, async () => {
  // console.log("------watch-----queryParams", props.query)
  loading.value = true;
  await getMetricsItems();
  const items = await getDataset();
  const opt = { dataset: { source: items } };
  chartObj.setOption(opt);
  loading.value = false;
});

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

async function getMetricsItems() {
  const resp = await props.fetchCard(queryParams.value);
  const data = resp.data;
  metricsItems.value.length = 0;
  XEUtils.arrayEach(props.metricEnum, (info) => {
    const tmp: MetricData = {
      label: info.label,
      value: info.value,
      metricVal: data[info.value],
      gapVal: data[`gap${info.value}`],
      preVal: data[`prev${info.value}`],
    };
    metricsItems.value.push(tmp);
  });
}

async function initLine() {
  chartObj = echarts.init(chartRef.value);
  option.dataset.source = await getDataset();

  // 初始化系列和 y 轴
  option.series = metrics.value.map((metric, index) => ({
    id: index,
    name: metric.label,
    type: index === 0 ? 'bar' : 'line',
    encode: { x: 'Name', y: metric.metric },
    yAxisIndex: index,
    itemStyle: { color: option.series.type == 'bar' ? '#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,
  }));

  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,
  }));

  // 初始化图例
  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);
  loading.value = false;
}

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: 'Name', y: metric.metric },
      yAxisIndex: index,
      itemStyle: { color: metric.color, borderRadius: [6, 6, 6, 6] },
      lineStyle: { color: metric.color },
      barMaxWidth: '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,
  }));

  // 确保只有必要的 y 轴
  while (option.yAxis.length > metrics.value.length) {
    option.yAxis.pop();
  }

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

async function changeStatDim() {
  loading.value = true;
  let source = await getDataset();
  if (source.length > 0) {
    chartObj.setOption({ dataset: { source: source } });
  }
  loading.value = false;
}

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 label="week" :disabled="!props.fetchLineWeek">周</el-radio-button>
      <el-radio-button label="month" :disabled="!props.fetchLineWeek">月</el-radio-button>
    </el-radio-group>
    <div style="height: 350px" ref="chartRef"></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>
