<template>
  <div class="app-container">
    <el-card shadow="never">
      <el-form :inline="true" :model="queryForm" size="small">
        <el-form-item label="时间范围">
          <el-date-picker v-model="timeRange" type="datetimerange" value-format="YYYY-MM-DD HH:mm:ss"
            range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" style="width: 380px" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="Search" @click="handleQuery">查询</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 桑基图 -->
    <el-card shadow="never" class="mt-4">
      <template #header>
        <div class="card-header">
          <span class="font-bold">温区流转桑基图</span>
          <HelpButton title="桑基图（Sankey Diagram）" :content="ADVANCED_HELP" />
        </div>
      </template>
      <div ref="sankeyChartRef" class="chart-container-lg" />
    </el-card>

    <!-- 主题河流图 -->
    <el-card shadow="never" class="mt-4">
      <template #header>
        <div class="card-header">
          <span class="font-bold">温度主题河流图</span>
          <HelpButton title="主题河流图（ThemeRiver）" :content="ADVANCED_HELP" />
        </div>
      </template>
      <div ref="themeRiverChartRef" class="chart-container-lg" />
    </el-card>

    <!-- 矩形树图 + 旭日图 -->
    <el-row :gutter="16" class="mt-4">
      <el-col :xs="24" :sm="12">
        <el-card shadow="never">
          <template #header>
            <div class="card-header">
              <span class="font-bold">温度矩形树图（按测点平均温度）</span>
              <HelpButton title="矩形树图（Treemap）" :content="ADVANCED_HELP" />
            </div>
          </template>
          <div ref="treemapChartRef" class="chart-container-lg" />
        </el-card>
      </el-col>
      <el-col :xs="24" :sm="12">
        <el-card shadow="never">
          <template #header>
            <div class="card-header">
              <span class="font-bold">温度旭日图（温区→测点）</span>
              <HelpButton title="旭日图（Sunburst）" :content="ADVANCED_HELP" />
            </div>
          </template>
          <div ref="sunburstChartRef" class="chart-container-lg" />
        </el-card>
      </el-col>
    </el-row>

    <!-- 平行坐标图 -->
    <el-card shadow="never" class="mt-4">
      <template #header>
        <div class="card-header">
          <span class="font-bold">测点多维温度画像（平行坐标图）</span>
          <HelpButton title="平行坐标图（Parallel Coordinates）" :content="ADVANCED_HELP" />
        </div>
      </template>
      <div ref="parallelChartRef" class="chart-container-lg" />
    </el-card>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, nextTick } from 'vue'
import * as echarts from 'echarts'
import { getSankeyData, getThemeRiverData, getTreemapData, getSunburstData, getParallelData } from '@/api/ems/report/tempBoard'
import type { TempBoardQuery, TempBoardAdvancedVO } from '@/api/ems/report/tempBoard'
import HelpButton from '../components/HelpButton.vue'
import { ADVANCED_HELP } from '../components/helpContent'
import { useChartResize } from '../components/useChartResize'

defineOptions({ name: 'TempBoardAdvanced' })

const timeRange = ref<[string, string]>(['', ''])
const queryForm = reactive<TempBoardQuery>({})
const loading = ref(false)
const sankeyChartRef = ref<HTMLElement>()
const themeRiverChartRef = ref<HTMLElement>()
const treemapChartRef = ref<HTMLElement>()
const sunburstChartRef = ref<HTMLElement>()
const parallelChartRef = ref<HTMLElement>()

const { getChart } = useChartResize(sankeyChartRef, themeRiverChartRef, treemapChartRef, sunburstChartRef, parallelChartRef)

/** 初始化默认时间范围：昨天8:30 ~ 今天8:30 */
function initTimeRange() {
  const now = new Date()
  const end = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 8, 30, 0)
  const start = new Date(end.getTime() - 24 * 3600 * 1000)
  const p = (n: number) => n.toString().padStart(2, '0')
  const fmt = (d: Date) => `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`
  timeRange.value = [fmt(start), fmt(end)]
}

async function handleQuery() {
  if (timeRange.value?.[0]) { queryForm.startTime = timeRange.value[0]; queryForm.endTime = timeRange.value[1] }
  loading.value = true
  try {
    const [skRes, trRes, tmRes, sbRes, plRes] = await Promise.all([
      getSankeyData(queryForm), getThemeRiverData(queryForm),
      getTreemapData(queryForm), getSunburstData(queryForm), getParallelData(queryForm)
    ])
    await nextTick()
    renderSankey(skRes.data)
    renderThemeRiver(trRes.data)
    renderTreemap(tmRes.data)
    renderSunburst(sbRes.data)
    renderParallel(plRes.data)
  } finally { loading.value = false }
}

/** 桑基图 */
function renderSankey(data: TempBoardAdvancedVO[]) {
  const chart = getChart(sankeyChartRef)
  if (!chart || !data.length) return
  const nodes = new Set<string>()
  data.forEach(d => { nodes.add(d.fromNode!); nodes.add(d.toNode!) })
  chart.setOption({
    tooltip: {
      trigger: 'item',
      formatter: (p: any) => p.dataType === 'edge'
        ? `${p.data.source} → ${p.data.target}<br/>流量: <b>${p.data.value}</b>`
        : `${p.name}`
    },
    series: [{
      type: 'sankey',
      layout: 'none',
      emphasis: { focus: 'adjacency' },
      data: [...nodes].map(n => ({ name: n })),
      links: data.map(d => ({ source: d.fromNode, target: d.toNode, value: d.flowCount })),
      lineStyle: { color: 'gradient', curveness: 0.5 },
      label: { color: '#333', fontSize: 12 },
      itemStyle: { borderWidth: 0 }
    }]
  })
}

/** 主题河流图 */
function renderThemeRiver(data: TempBoardAdvancedVO[]) {
  const chart = getChart(themeRiverChartRef)
  if (!chart || !data.length) return
  chart.setOption({
    tooltip: {
      trigger: 'axis',
      formatter: (params: any) => {
        const p = params[0]
        return `${p.data[2]}<br/>时间: ${p.data[0]}<br/>温度: <b>${p.data[1]}℃</b>`
      }
    },
    legend: { top: 0, textStyle: { color: '#666' } },
    singleAxis: { type: 'time', axisLabel: { color: '#666' } },
    series: [{
      type: 'themeRiver',
      data: data.map(d => [d.statTime, d.avgTemp, d.monitorName || d.monitorId]),
      emphasis: { itemStyle: { shadowBlur: 20, shadowColor: 'rgba(0,0,0,0.8)' } },
      label: { show: false }
    }]
  })
}

/** 矩形树图 */
function renderTreemap(data: TempBoardAdvancedVO[]) {
  const chart = getChart(treemapChartRef)
  if (!chart || !data.length) return
  chart.setOption({
    tooltip: {
      formatter: (p: any) => {
        const item = data.find(d => d.monitorName === p.name || d.monitorId === p.name)
        return `${p.name}<br/>平均温度: <b>${p.value?.toFixed(2)}℃</b>${item ? `<br/>样本数: ${item.sampleCount}` : ''}`
      }
    },
    series: [{
      type: 'treemap',
      data: data.map(d => ({
        name: d.monitorName || d.monitorId,
        value: d.avgTemp,
        itemStyle: {
          color: d.avgTemp >= 30 ? '#f56c6c' : d.avgTemp >= 20 ? '#e6a23c' : d.avgTemp >= 10 ? '#67c23a' : '#409eff'
        }
      })),
      leafDepth: 1,
      roam: false,
      label: { show: true, formatter: '{b}\n{c}℃', fontSize: 12, color: '#fff' },
      upperLabel: { show: true, height: 24, color: '#fff' },
      itemStyle: { borderColor: '#fff', borderWidth: 2, gapWidth: 2 },
      levels: [
        { itemStyle: { borderColor: '#333', borderWidth: 2, gapWidth: 2 } },
        { itemStyle: { borderColor: '#fff', borderWidth: 1, gapWidth: 1 } }
      ]
    }]
  })
}

/** 旭日图 */
function renderSunburst(data: TempBoardAdvancedVO[]) {
  const chart = getChart(sunburstChartRef)
  if (!chart || !data.length) return
  // 构建层级数据：温区 → 测点
  const bucketMap = new Map<string, { name: string; value: number; children: any[] }>()
  const colorMap: Record<string, string> = {
    '低温': '#409eff', '偏低': '#67c23a', '正常': '#95de64',
    '偏高': '#e6a23c', '高温': '#f56c6c'
  }
  data.forEach(d => {
    if (!bucketMap.has(d.tempBucket!)) {
      bucketMap.set(d.tempBucket!, { name: d.tempBucket!, value: 0, children: [] })
    }
    const bucket = bucketMap.get(d.tempBucket!)!
    bucket.children.push({
      name: d.monitorName || d.monitorId,
      value: d.sampleCount,
      itemStyle: { color: colorMap[d.tempBucket!] || undefined }
    })
    bucket.value += d.sampleCount ?? 0
  })
  chart.setOption({
    tooltip: { formatter: '{b}: {c}样本' },
    series: [{
      type: 'sunburst',
      data: [...bucketMap.values()].map(b => ({
        ...b,
        itemStyle: { color: colorMap[b.name] || undefined }
      })),
      radius: ['15%', '90%'],
      label: { rotate: 'radial', fontSize: 11, color: '#333' },
      itemStyle: { borderWidth: 2, borderColor: '#fff' },
      emphasis: { focus: 'ancestor' }
    }]
  })
}

/** 平行坐标图 */
function renderParallel(data: TempBoardAdvancedVO[]) {
  const chart = getChart(parallelChartRef)
  if (!chart || !data.length) return
  const dimNames = ['测点', '平均温度', '最高温度', '最低温度', '标准差', '平均延迟(s)']
  const fields = ['avgTemp', 'maxTemp', 'minTemp', 'tempStddev', 'avgDelay'] as const
  const colors = ['#409eff', '#67c23a', '#e6a23c', '#f56c6c', '#9b59b6', '#1abc9c', '#e74c3c', '#2ecc71']

  // 基于IQR（四分位距）动态计算每根轴的范围，避免异常值导致线条超出可视区域
  function calcAxisRange(field: string): { min: number; max: number } {
    const values = data.map(d => (d as any)[field] as number).filter(v => v != null).sort((a, b) => a - b)
    if (values.length === 0) return { min: 0, max: 100 }
    if (values.length <= 2) {
      // 数据太少时直接用实际范围，加一点余量
      const range = values[values.length - 1] - values[0]
      const pad = Math.max(range * 0.1, 1)
      return { min: Math.floor(values[0] - pad), max: Math.ceil(values[values.length - 1] + pad) }
    }
    const q1 = values[Math.floor(values.length * 0.25)]
    const q3 = values[Math.floor(values.length * 0.75)]
    const iqr = q3 - q1
    // 上下限：Q1 - 1.5*IQR ~ Q3 + 1.5*IQR，并兜底覆盖全部数据
    const lower = Math.min(q1 - 1.5 * iqr, values[0])
    const upper = Math.max(q3 + 1.5 * iqr, values[values.length - 1])
    const pad = Math.max((upper - lower) * 0.05, 0.5)
    return { min: Math.floor(lower - pad), max: Math.ceil(upper + pad) }
  }

  // 为数值维度预计算轴范围
  const axisRanges = fields.map(f => calcAxisRange(f))

  chart.setOption({
    tooltip: { trigger: 'item' },
    legend: {
      data: data.map(d => d.monitorName || d.monitorId),
      top: 0,
      type: 'scroll',
      textStyle: { color: '#666', fontSize: 11 }
    },
    parallelAxis: [
      { type: 'category', data: data.map(d => d.monitorName || d.monitorId), dim: 0, name: dimNames[0], axisLabel: { rotate: 30, color: '#666' } },
      ...fields.map((f, i) => ({
        type: 'value',
        dim: i + 1,
        name: dimNames[i + 1],
        min: axisRanges[i].min,
        max: axisRanges[i].max,
        nameLocation: 'end',
        nameTextStyle: { color: '#333', fontSize: 12 },
        axisLabel: { color: '#666', fontSize: 11 },
        splitLine: { show: true, lineStyle: { color: '#eee' } },
        axisTick: { show: true }
      }))
    ],
    parallel: { left: 100, right: 50, top: 50, bottom: 30 },
    series: data.map((d, idx) => ({
      name: d.monitorName || d.monitorId,
      type: 'parallel',
      data: [[d.monitorName || d.monitorId, d.avgTemp, d.maxTemp, d.minTemp, d.tempStddev, d.avgDelay]],
      lineStyle: { width: 2, opacity: 0.7, color: colors[idx % colors.length] },
      smooth: true
    }))
  })
}

onMounted(() => { initTimeRange(); handleQuery() })
</script>

<style scoped>
.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.chart-container-lg {
  width: 100%;
  min-height: 400px;
}
</style>
