<template>
  <div v-loading="loading" class="app-container">
    <VibrationBoardFilter
      :selection-label="queryForm.selectionLabel"
      :time-range="daterangeRecordTime"
      :sampling-interval="queryForm.samplingInterval"
      :vibration-param="queryForm.vibrationParam"
      show-metric
      @update:time-range="setTimeRange"
      @update:sampling-interval="setSamplingInterval"
      @update:vibration-param="setVibrationParam"
      @query="handleQuery"
    />

    <el-row :gutter="16" class="mt-4">
      <el-col :span="6">
        <VibrationBoardDeviceTree :loading="treeLoading" :tree-data="monitorTreeOptions" :tree-props="treeProps" @node-click="handleTreeNodeClick" />
      </el-col>
      <el-col :span="18">
        <el-row :gutter="16">
          <el-col :span="12">
            <el-card>
              <template #header>区间分布</template>
              <Chart ref="intervalChart" class="chart-lg" />
            </el-card>
          </el-col>
          <el-col :span="12">
            <el-card>
              <template #header>直方图</template>
              <Chart ref="histogramChart" class="chart-lg" />
            </el-card>
          </el-col>
        </el-row>
        <el-card class="mt-4">
          <template #header>日历热力图</template>
          <Chart ref="calendarChart" class="chart-lg" />
        </el-card>
        <el-card class="mt-4">
          <template #header>小时热力图</template>
          <Chart ref="hourlyChart" class="chart-xl" />
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script setup lang="ts">
import Chart from '@/components/Charts/Chart.vue';
import { getVibrationDistributionData, type VibrationDistributionPageVO } from '@/api/ems/report/vibrationBoard';
import VibrationBoardFilter from '../components/VibrationBoardFilter.vue';
import VibrationBoardDeviceTree from '../components/VibrationBoardDeviceTree.vue';
import { useVibrationBoardQueryState } from '../components/useVibrationBoardQueryState';

defineOptions({ name: 'VibrationBoardDistribution' });

const intervalChart = ref<any>();
const histogramChart = ref<any>();
const calendarChart = ref<any>();
const hourlyChart = ref<any>();

const {
  loading,
  treeLoading,
  monitorTreeOptions,
  treeProps,
  daterangeRecordTime,
  queryForm,
  loadTree,
  handleTreeNodeClick,
  setTimeRange,
  setSamplingInterval,
  setVibrationParam,
  buildQuery
} = useVibrationBoardQueryState();

const distributionData = ref<VibrationDistributionPageVO>({
  intervalBuckets: [],
  histogramBuckets: [],
  calendarHeatmap: [],
  hourlyHeatmap: []
});

const toNumber = (value: number | string | undefined) => Number(value ?? 0);

const renderCharts = () => {
  const intervalData = distributionData.value.intervalBuckets || [];
  const histogramData = distributionData.value.histogramBuckets || [];
  const calendarData = (distributionData.value.calendarHeatmap || []).map((item) => [item.statDate, toNumber(item.avgValue)]);
  const hourlyData = (distributionData.value.hourlyHeatmap || []).map((item) => [toNumber(item.statHour), item.statDate, toNumber(item.avgValue)]);
  const days = [...new Set(hourlyData.map((item) => item[1] as string))].sort();
  if (!intervalData.length && !histogramData.length && !calendarData.length && !hourlyData.length) {
    return;
  }

  intervalChart.value?.setData({
    tooltip: { trigger: 'item' },
    series: [
      {
        type: 'pie',
        radius: ['40%', '70%'],
        data: intervalData.map((item) => ({ name: item.label, value: toNumber(item.count) })),
        label: { formatter: '{b}\n{d}%' }
      }
    ]
  });

  histogramChart.value?.setData({
    tooltip: { trigger: 'axis' },
    xAxis: { type: 'category', data: histogramData.map((item) => `${toNumber(item.startValue).toFixed(1)}~${toNumber(item.endValue).toFixed(1)}`) },
    yAxis: { type: 'value' },
    series: [{ type: 'bar', data: histogramData.map((item) => toNumber(item.count)), itemStyle: { color: '#5b8ff9' } }]
  });

  calendarChart.value?.setData({
    tooltip: { trigger: 'item' },
    visualMap: {
      min: calendarData.length ? Math.min(...calendarData.map((item) => item[1] as number)) : 0,
      max: calendarData.length ? Math.max(...calendarData.map((item) => item[1] as number)) : 0,
      calculable: true,
      orient: 'horizontal',
      left: 'center',
      bottom: 0
    },
    calendar: { range: calendarData.length ? [calendarData[0][0], calendarData[calendarData.length - 1][0]] : [] },
    series: [{ type: 'heatmap', coordinateSystem: 'calendar', data: calendarData }]
  });

  hourlyChart.value?.setData({
    tooltip: { trigger: 'item' },
    xAxis: { type: 'category', data: Array.from({ length: 24 }, (_, index) => `${index.toString().padStart(2, '0')}:00`) },
    yAxis: { type: 'category', data: days },
    visualMap: {
      min: hourlyData.length ? Math.min(...hourlyData.map((item) => item[2] as number)) : 0,
      max: hourlyData.length ? Math.max(...hourlyData.map((item) => item[2] as number)) : 0,
      calculable: true,
      orient: 'horizontal',
      left: 'center',
      bottom: 0
    },
    series: [{ type: 'heatmap', data: hourlyData }]
  });
};

const handleQuery = async () => {
  loading.value = true;
  try {
    const { data } = await getVibrationDistributionData(buildQuery());
    distributionData.value = data || {
      intervalBuckets: [],
      histogramBuckets: [],
      calendarHeatmap: [],
      hourlyHeatmap: []
    };
    await nextTick();
    renderCharts();
  } finally {
    loading.value = false;
  }
};

onMounted(async () => {
  await loadTree();
  await handleQuery();
});
</script>

<style scoped>
.chart-lg {
  height: 360px;
}

.chart-xl {
  height: 420px;
}
</style>
