<script setup lang="ts">
/**
 * @Name: IndicatorHeatmap.vue
 * @Description: 搜索词-分析页-热力图
 * @Author: Cheney
 */

import * as echarts from 'echarts';
import { inject, onBeforeUnmount, Ref, ref } from 'vue';
import * as api from './api';
import emitter from '/@/utils/emitter';

const filter = inject<Ref>('filter');
const hasData = ref(true);
const heatmapLoading = ref(false);
const chartRef = ref<HTMLElement | null>(null);
let chart: echarts.ECharts | null = null;
let resizeObserver: ResizeObserver | null = null;

onBeforeUnmount(() => {
  emitter.all.clear();
  // 清理 ResizeObserver
  if (resizeObserver) {
    resizeObserver.disconnect();
  }
  if (chart) {
    chart.dispose();
    chart = null;
  }
});

emitter.on('QueryCondition-sendRequest', () => {
  fetchHeatmapData();
});

async function fetchHeatmapData() {
  heatmapLoading.value = true;
  const query = {
    date_start: filter.value.reportDate[0],
    date_end: filter.value.reportDate[1],
    layer_type: filter.value.layerType,
    search_term: filter.value.searchTerm,
    report_range: filter.value.reportType,
    [filter.value.layerType.split('_')[0]]: filter.value.variable,
    metric: filter.value.metric,
  };
  try {
    const responseData = await api.getHeatmapData(query);
    if (!responseData.data || responseData.data.length === 0) {
      // 处理空数据的情况
      hasData.value = false;
      if (chart) {
        chart.clear();
      }
      return;
    }
    hasData.value = true;
    const days = [...new Set(responseData.data.map(item => item.Reporting_Date))]; // x轴数据
    const keywords = [...new Set(responseData.data.flatMap(item =>
        Object.keys(item).filter(key => key !== 'Reporting_Date')
    ))]; // y轴数据
    const data = [];

    // 找出所有数值的最大值，用于设置 visualMap 的 max 值
    const maxValue = Math.max(
        ...responseData.data.flatMap(item =>
            Object.values(item).filter(value => typeof value === 'number') as number[]
        )
    );

    responseData.data.forEach(item => {
      const dayIndex = days.indexOf(item.Reporting_Date);
      keywords.forEach((keyword: any, keywordIndex) => {
        if (item[keyword] !== undefined && item[keyword] !== null) {
          data.push([dayIndex, keywordIndex, item[keyword]]); // [x, y, value]
        }
      });
    });

    const option = {
      title: {
        text: '搜索词时间段对比热力图',
      },
      position: 'top',
      tooltip: {
        position: 'top',
        formatter: function(params) {
          const keyword = keywords[params.value[1]]; // 获取当前悬浮的关键词
          return `${keyword}<br>${params.seriesName}: ${params.value[2]}`;
        }
      },
      grid: {
        // height: '65%',
        top: '10%',
        bottom: '15%',
        left: '15%',
        right: '5%',
      },
      series: [
        {
          name: keywords,
          type: 'heatmap',
          data: data,
          label: {
            show: true,
          },
          emphasis: {
            itemStyle: {
              shadowBlur: 10,
              shadowColor: 'rgba(0, 0, 0, 0.5)',
            },
          },
        },
      ],
      xAxis: {
        type: 'category',
        name: '日期',
        nameGap: 20,
        nameLocation: 'start',
        nameTextStyle: {
          fontWeight: 'bold',
          fontSize: 14,
          color: '#333',
        },
        axisLabel: {
          formatter: function (value) {
            if (value.length > 10) {
              return value.substring(0, 10) + '...';
            }
            return value;
          },
        },
        data: days,
        splitArea: {
          show: true,
        },
      },
      yAxis: {
        type: 'category',
        name: '搜索词',
        nameGap: 20,
        nameTextStyle: {
          fontWeight: 'bold',
          fontSize: 14,
          color: '#333',
        },
        data: keywords,
        splitArea: {
          show: true,
        },
        axisLabel: {
          interval: 0,  // 显示所有标签
          width: 280,  // 增加标签区域的宽度以适应文本
          rotate: 15,  // 标签旋转角度
        },
      },
      dataZoom: [
        {
          type: 'slider',  // 纵向滚动条类型
          yAxisIndex: 0,  // 指定作用于 Y 轴
          // start: 100,  // 初始位置，百分比形式，数值越小，滚动条越靠下
          // end: 30,
          startValue: 80,  // 初始位置，数值形式，数值越小，滚动条越靠上
          endValue: 100,
          zoomLock: true,  // 锁定缩放，避免同时缩放两个滚动条
          showDetail: false,  // 显示缩放的细节
          brushSelect: false,
        },
        {
          type: 'inside',  // 内置型数据区域缩放组件（使用鼠标滚轮和拖拽）
          yAxisIndex: 0,
          zoomOnMouseWheel: false,
          moveOnMouseMove: true,
          moveOnMouseWheel: true,
        }
      ],
      visualMap: {
        min: 0,
        max: maxValue, // 使用计算出的最大值
        itemHeight: 500,
        calculable: true,
        orient: 'horizontal',
        left: 'center',
        bottom: '2%',
      },
    };

    if (!chart) {
      chart = echarts.init(chartRef.value);
    }
    chart.setOption(option);

    // 添加 ResizeObserver 以处理图表大小变化
    if (!resizeObserver) {
      resizeObserver = new ResizeObserver(() => {
        chart?.resize();
      });
      resizeObserver.observe(chartRef.value);
    }
  } catch (error) {
    hasData.value = false;
    console.error('==Error==', error);
  } finally {
    heatmapLoading.value = false;
  }
}
</script>

<template>
  <el-card shadow="never" v-loading="heatmapLoading" class="flex flex-col" body-class="w-full">

    <div class="text-center flex justify-center items-center">
      <span class="font-medium mr-1.5">指标 </span>
      <el-select v-model="filter.metric" @change="fetchHeatmapData" style="width: 200px">
        <el-option label="搜索查询分数" value="Search_Query_Score"></el-option>
        <el-option label="搜索查询数量" value="Search_Query_Volume"></el-option>

        <el-option label="展示量-总数" value="Impressions_Total_Count"></el-option>
        <el-option v-if="filter.layerType === 'asin_view'" label="展示量-ASIN数量" value="Impressions_A_B_Count"></el-option>
        <el-option v-if="filter.layerType === 'brand_view'" label="展示量-品牌数量" value="Impressions_A_B_Count"></el-option>

        <el-option label="点击量-总数" value="Clicks_Total_Count"></el-option>
        <el-option v-if="filter.layerType === 'asin_view'" label="点击量-ASIN数量" value="Clicks_A_B_Count"></el-option>
        <el-option v-if="filter.layerType === 'brand_view'" label="点击量-品牌数量" value="Clicks_A_B_Count"></el-option>
        <el-option label="点击量-价格中位数" value="Clicks_Price_Median"></el-option>
        <el-option v-if="filter.layerType === 'asin_view'" label="点击量-ASIN价格中位数" value="Clicks_A_B_Price_Median"></el-option>
        <el-option v-if="filter.layerType === 'brand_view'" label="点击量-品牌价格中位数" value="Clicks_A_B_Price_Median"></el-option>

        <el-option label="加购-总数" value="Cart_Adds_Total_Count"></el-option>
        <el-option v-if="filter.layerType === 'asin_view'" label="加购-ASIN数量" value="Cart_Adds_A_B_Count"></el-option>
        <el-option v-if="filter.layerType === 'brand_view'" label="加购-品牌数量" value="Cart_Adds_A_B_Count"></el-option>
        <el-option label="加购-价格中位数" value="Cart_Adds_Price_Median"></el-option>
        <el-option v-if="filter.layerType === 'asin_view'" label="加购-ASIN价格中位数" value="Cart_Adds_A_B_Price_Median"></el-option>
        <el-option v-if="filter.layerType === 'brand_view'" label="加购-品牌价格中位数" value="Cart_Adds_A_B_Price_Median"></el-option>


        <el-option label="购买-总数" value="Purchases_Total_Count"></el-option>
        <el-option v-if="filter.layerType === 'asin_view'" label="购买-ASIN数量" value="Purchases_A_B_Count"></el-option>
        <el-option v-if="filter.layerType === 'brand_view'" label="购买-品牌数量" value="Purchases_A_B_Count"></el-option>
        <el-option label="购买-价格中位数" value="Purchases_Price_Median"></el-option>
        <el-option v-if="filter.layerType === 'asin_view'" label="购买-ASIN价格中位数" value="Purchases_A_B_Price_Median"></el-option>
        <el-option v-if="filter.layerType === 'brand_view'" label="购买-品牌价格中位数" value="Purchases_A_B_Price_Median"></el-option>
      </el-select>
    </div>

    <div class="w-full" style="min-height: 800px">
      <div v-show="!heatmapLoading && !hasData" style="min-height: 800px" class="flex justify-center items-center">
        <el-empty :image-size="300"  />
      </div>
      <div v-show="hasData" ref="chartRef" style="width: 100%; height: 800px"></div>
    </div>
  </el-card>
</template>

<style scoped></style>
