<template>
  <div class="advanced-viz">
    <el-card shadow="never">
      <template #header>
        <div class="card-header">
          <span class="title">高级可视化分析</span>
          <el-radio-group v-model="activeTab" size="small">
            <el-radio-button label="pareto">Pareto前沿</el-radio-button>
            <el-radio-button label="convergence">收敛轨迹</el-radio-button>
            <el-radio-button label="radar">方案对比</el-radio-button>
            <el-radio-button label="heatmap">参数敏感性</el-radio-button>
          </el-radio-group>
        </div>
      </template>

      <!-- 数据输入 -->
      <el-card shadow="never" style="margin-bottom: 16px;">
        <template #header>
          <span style="font-weight: 500;">仿真结果数据</span>
        </template>
        <el-input
          v-model="resultDataJson"
          type="textarea"
          :rows="4"
          placeholder='粘贴仿真结果JSON，如 [{"tavg_nm":2.5,"efficiency_pct":92,"ripple_pct":5,"copper_loss_w":10},...]'
          style="margin-bottom: 10px;"
        />
        <div class="viz-actions">
          <el-button size="small" type="primary" @click="parseData">解析数据</el-button>
          <el-button size="small" @click="loadDemoData">加载示例数据</el-button>
          <span v-if="parsedData.length" style="margin-left: 10px; color: #67c23a;">
            已加载 {{ parsedData.length }} 个数据点
          </span>
        </div>
      </el-card>

      <!-- Pareto前沿 -->
      <div v-if="activeTab === 'pareto'">
        <el-card shadow="never">
          <template #header>
            <div style="display: flex; justify-content: space-between; align-items: center;">
              <span style="font-weight: 500;">Pareto 最优前沿（损耗 vs 效率）</span>
              <div>
                <span style="margin-right: 10px; font-size: 12px; color: #909399;">X轴:</span>
                <el-select v-model="paretoX" size="small" style="width: 140px; margin-right: 10px;">
                  <el-option v-for="m in metrics" :key="m.key" :label="m.label" :value="m.key" />
                </el-select>
                <span style="margin-right: 10px; font-size: 12px; color: #909399;">Y轴:</span>
                <el-select v-model="paretoY" size="small" style="width: 140px;">
                  <el-option v-for="m in metrics" :key="m.key" :label="m.label" :value="m.key" />
                </el-select>
              </div>
            </div>
          </template>
          <div ref="paretoChartRef" style="width: 100%; height: 450px;"></div>
          <div v-if="paretoPoints.length" style="margin-top: 10px; font-size: 13px;">
            <el-tag type="success" size="small">Pareto最优解: {{ paretoPoints.length }} 个</el-tag>
            <span style="margin-left: 10px; color: #909399;">绿色点为Pareto最优，灰色点为被支配解</span>
          </div>
        </el-card>
      </div>

      <!-- 收敛轨迹 -->
      <div v-if="activeTab === 'convergence'">
        <el-card shadow="never">
          <template #header>
            <div style="display: flex; justify-content: space-between; align-items: center;">
              <span style="font-weight: 500;">优化收敛轨迹</span>
              <el-select v-model="convergenceMetric" size="small" style="width: 160px;">
                <el-option v-for="m in metrics" :key="m.key" :label="m.label" :value="m.key" />
              </el-select>
            </div>
          </template>
          <div ref="convergenceChartRef" style="width: 100%; height: 450px;"></div>
          <div style="margin-top: 10px; font-size: 13px; color: #909399;">
            显示每批次的最优值变化，虚线标记信任域激活点
          </div>
        </el-card>
      </div>

      <!-- 方案对比雷达图 -->
      <div v-if="activeTab === 'radar'">
        <el-card shadow="never">
          <template #header>
            <span style="font-weight: 500;">多方案关键指标对比（雷达图）</span>
          </template>
          <div ref="radarChartRef" style="width: 100%; height: 450px;"></div>
          <div style="margin-top: 10px;">
            <el-button size="small" @click="addRadarScheme">添加方案</el-button>
            <span style="margin-left: 10px; font-size: 13px; color: #909399;">
              已添加 {{ radarSchemes.length }} 个方案
            </span>
          </div>
        </el-card>
      </div>

      <!-- 参数敏感性热力图 -->
      <div v-if="activeTab === 'heatmap'">
        <el-card shadow="never">
          <template #header>
            <div style="display: flex; justify-content: space-between; align-items: center;">
              <span style="font-weight: 500;">参数敏感性热力图</span>
              <div>
                <span style="margin-right: 10px; font-size: 12px; color: #909399;">目标指标:</span>
                <el-select v-model="heatmapMetric" size="small" style="width: 140px;">
                  <el-option v-for="m in metrics" :key="m.key" :label="m.label" :value="m.key" />
                </el-select>
              </div>
            </div>
          </template>
          <div ref="heatmapChartRef" style="width: 100%; height: 450px;"></div>
          <div style="margin-top: 10px; font-size: 13px; color: #909399;">
            颜色越深表示该参数组合下目标指标越优
          </div>
        </el-card>
      </div>
    </el-card>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, watch, nextTick } from 'vue'
import { ElMessage } from 'element-plus'

const activeTab = ref('pareto')
const resultDataJson = ref('')
const parsedData = ref<any[]>([])
const paretoX = ref('total_losses_w')
const paretoY = ref('efficiency_pct')
const convergenceMetric = ref('tavg_nm')
const heatmapMetric = ref('tavg_nm')
const radarSchemes = ref<any[]>([])

const paretoChartRef = ref()
const convergenceChartRef = ref()
const radarChartRef = ref()
const heatmapChartRef = ref()

let echarts: any = null
let paretoChart: any = null
let convergenceChart: any = null
let radarChart: any = null
let heatmapChart: any = null

const metrics = [
  { key: 'tavg_nm', label: '平均转矩 (Nm)' },
  { key: 'efficiency_pct', label: '效率 (%)' },
  { key: 'ripple_pct', label: '转矩脉动 (%)' },
  { key: 'total_losses_w', label: '总损耗 (W)' },
  { key: 'copper_loss_w', label: '铜耗 (W)' },
  { key: 'iron_loss_w', label: '铁耗 (W)' },
  { key: 'magnet_loss_w', label: '磁钢损耗 (W)' },
  { key: 'back_emf_v', label: '反电动势 (V)' },
]

const paretoPoints = ref<any[]>([])

const parseData = () => {
  try {
    const data = JSON.parse(resultDataJson.value)
    if (!Array.isArray(data)) throw new Error('Data must be an array')
    parsedData.value = data
    ElMessage.success(`成功解析 ${data.length} 个数据点`)
    nextTick(() => renderAllCharts())
  } catch (e: any) {
    ElMessage.error('JSON解析失败: ' + e.message)
  }
}

const loadDemoData = () => {
  const demo = []
  for (let i = 0; i < 30; i++) {
    demo.push({
      tavg_nm: +(2 + Math.random() * 3).toFixed(2),
      efficiency_pct: +(85 + Math.random() * 12).toFixed(1),
      ripple_pct: +(2 + Math.random() * 15).toFixed(1),
      total_losses_w: +(50 + Math.random() * 200).toFixed(1),
      copper_loss_w: +(20 + Math.random() * 80).toFixed(1),
      iron_loss_w: +(10 + Math.random() * 60).toFixed(1),
      magnet_loss_w: +(5 + Math.random() * 40).toFixed(1),
      back_emf_v: +(100 + Math.random() * 100).toFixed(1),
    })
  }
  resultDataJson.value = JSON.stringify(demo, null, 2)
  parsedData.value = demo
  ElMessage.success('已加载30个示例数据点')
  nextTick(() => renderAllCharts())
}

const computePareto = (data: any[], xKey: string, yKey: string) => {
  // Pareto: minimize x, maximize y
  const sorted = [...data].sort((a, b) => a[xKey] - b[xKey])
  const pareto: any[] = []
  let maxY = -Infinity
  for (const point of sorted) {
    if (point[yKey] > maxY) {
      pareto.push(point)
      maxY = point[yKey]
    }
  }
  return pareto
}

const initECharts = () => {
  try {
    echarts = (window as any).echarts
    if (!echarts) {
      // Try dynamic import
      import('echarts').then(mod => {
        echarts = mod.default
        renderAllCharts()
      }).catch(() => {
        console.warn('ECharts not installed. Run: npm install echarts')
      })
    }
  } catch (e) {
    console.warn('ECharts init failed:', e)
  }
}

const renderPareto = () => {
  if (!echarts || !paretoChartRef.value || !parsedData.value.length) return
  if (!paretoChart) paretoChart = echarts.init(paretoChartRef.value)
  const pareto = computePareto(parsedData.value, paretoX.value, paretoY.value)
  paretoPoints.value = pareto
  const paretoSet = new Set(pareto.map(p => JSON.stringify(p)))
  const dominated = parsedData.value.filter(p => !paretoSet.has(JSON.stringify(p)))
  paretoChart.setOption({
    tooltip: { trigger: 'item', formatter: (p: any) => `${paretoX.value}: ${p.value[0]}<br/>${paretoY.value}: ${p.value[1]}` },
    grid: { left: 60, right: 30, top: 30, bottom: 50 },
    xAxis: { name: paretoX.value, type: 'value' },
    yAxis: { name: paretoY.value, type: 'value' },
    series: [
      { name: '被支配解', type: 'scatter', data: dominated.map(p => [p[paretoX.value], p[paretoY.value]]),
        itemStyle: { color: '#ccc', opacity: 0.6 }, symbolSize: 8 },
      { name: 'Pareto最优', type: 'scatter', data: pareto.map(p => [p[paretoX.value], p[paretoY.value]]),
        itemStyle: { color: '#67c23a' }, symbolSize: 12,
        markLine: { data: [{ type: 'average', name: 'Avg' }] } },
    ],
  })
}

const renderConvergence = () => {
  if (!echarts || !convergenceChartRef.value || !parsedData.value.length) return
  if (!convergenceChart) convergenceChart = echarts.init(convergenceChartRef.value)
  // Simulate batch convergence from data
  const batchSize = 5
  const batches: number[] = []
  const bestValues: number[] = []
  let best = -Infinity
  for (let i = 0; i < parsedData.value.length; i += batchSize) {
    const batch = parsedData.value.slice(i, i + batchSize)
    const batchBest = Math.max(...batch.map(p => p[convergenceMetric.value] || 0))
    best = Math.max(best, batchBest)
    batches.push(Math.floor(i / batchSize) + 1)
    bestValues.push(+best.toFixed(3))
  }
  convergenceChart.setOption({
    tooltip: { trigger: 'axis' },
    grid: { left: 60, right: 30, top: 30, bottom: 50 },
    xAxis: { name: '批次', type: 'category', data: batches },
    yAxis: { name: convergenceMetric.value, type: 'value' },
    series: [{
      name: '最优值', type: 'line', data: bestValues, smooth: true,
      lineStyle: { width: 3, color: '#409eff' },
      itemStyle: { color: '#409eff' },
      areaStyle: { color: { type: 'linear', x: 0, y: 0, x2: 0, y2: 1,
        colorStops: [{ offset: 0, color: 'rgba(64,158,255,0.3)' }, { offset: 1, color: 'rgba(64,158,255,0)' }] } },
      markPoint: { data: [{ type: 'max', name: '最大值' }] },
    }],
  })
}

const addRadarScheme = () => {
  if (!parsedData.value.length) { ElMessage.warning('请先加载数据'); return }
  const idx = radarSchemes.value.length % parsedData.value.length
  const point = parsedData.value[idx]
  radarSchemes.value.push({ name: `方案${radarSchemes.value.length + 1}`, data: point })
  nextTick(() => renderRadar())
}

const renderRadar = () => {
  if (!echarts || !radarChartRef.value) return
  if (!radarChart) radarChart = echarts.init(radarChartRef.value)
  const indicators = [
    { name: '转矩', max: 5 }, { name: '效率', max: 100 },
    { name: '低脉动', max: 20 }, { name: '低损耗', max: 250 },
    { name: '低铜耗', max: 100 }, { name: '低铁耗', max: 80 },
  ]
  const colors = ['#409eff', '#67c23a', '#e6a23c', '#f56c6c', '#909399']
  radarChart.setOption({
    tooltip: {},
    legend: { data: radarSchemes.value.map(s => s.name) },
    radar: { indicator: indicators, radius: '65%' },
    series: [{
      type: 'radar',
      data: radarSchemes.value.map((s, i) => ({
        name: s.name,
        value: [s.data.tavg_nm || 0, s.data.efficiency_pct || 0, 20 - (s.data.ripple_pct || 0),
          250 - (s.data.total_losses_w || 0), 100 - (s.data.copper_loss_w || 0), 80 - (s.data.iron_loss_w || 0)],
        itemStyle: { color: colors[i % colors.length] },
        areaStyle: { opacity: 0.2 },
      })),
    }],
  })
}

const renderHeatmap = () => {
  if (!echarts || !heatmapChartRef.value || !parsedData.value.length) return
  if (!heatmapChart) heatmapChart = echarts.init(heatmapChartRef.value)
  // Generate 2D heatmap from data (use first two params or indices)
  const xLabels = ['P1', 'P2', 'P3', 'P4', 'P5', 'P6']
  const yLabels = ['Q1', 'Q2', 'Q3', 'Q4', 'Q5']
  const data: any[] = []
  for (let x = 0; x < xLabels.length; x++) {
    for (let y = 0; y < yLabels.length; y++) {
      const idx = (x * yLabels.length + y) % parsedData.value.length
      data.push([x, y, parsedData.value[idx][heatmapMetric.value] || 0])
    }
  }
  heatmapChart.setOption({
    tooltip: { position: 'top' },
    grid: { left: 60, right: 30, top: 30, bottom: 50 },
    xAxis: { type: 'category', data: xLabels, splitArea: { show: true } },
    yAxis: { type: 'category', data: yLabels, splitArea: { show: true } },
    visualMap: { min: 0, max: Math.max(...data.map(d => d[2])), calculable: true,
      orient: 'horizontal', left: 'center', bottom: '5%',
      inRange: { color: ['#e0f3ff', '#409eff', '#1d4ed8'] } },
    series: [{ name: heatmapMetric.value, type: 'heatmap', data,
      label: { show: true, formatter: (p: any) => p.value[2].toFixed(1) },
      emphasis: { itemStyle: { shadowBlur: 10, shadowColor: 'rgba(0,0,0,0.5)' } } }],
  })
}

const renderAllCharts = () => {
  if (activeTab.value === 'pareto') renderPareto()
  if (activeTab.value === 'convergence') renderConvergence()
  if (activeTab.value === 'radar') renderRadar()
  if (activeTab.value === 'heatmap') renderHeatmap()
}

watch(activeTab, () => nextTick(() => renderAllCharts()))
watch([paretoX, paretoY], () => renderPareto())
watch(convergenceMetric, () => renderConvergence())
watch(heatmapMetric, () => renderHeatmap())

onMounted(() => {
  initECharts()
})
</script>

<style scoped>
.advanced-viz { padding: 20px; }
.card-header { display: flex; justify-content: space-between; align-items: center; }
.title { font-weight: 600; font-size: 16px; }
.viz-actions { display: flex; align-items: center; }
</style>
