<script setup>
import * as echarts from 'echarts'
import { ArrowLeft, VideoPlay, VideoPause, Download, DataAnalysis } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
  onMounted,
  onBeforeUnmount,
  ref,
  computed,
  nextTick,
} from 'vue'
import { useRouter, useRoute } from 'vue-router'
import {
  getExperiment,
  startExperiment,
  stopExperiment,
  getDataPoints,
  getReport,
  exportToHistory,
} from '@/api/realtimeMonitor'

const router = useRouter()
const route = useRoute()
const expId = Number(route.params.id)

// ── 试验状态 ───────────────────────────────────────────────────────────────────
const experiment = ref(null)
const loadingExp = ref(false)

const loadExperiment = async () => {
  loadingExp.value = true
  try {
    experiment.value = await getExperiment(expId)
  } finally {
    loadingExp.value = false
  }
}

const isRunning = computed(() => experiment.value?.status === 'running')
const isStopped = computed(() => experiment.value?.status === 'stopped')

// ── 实时数据 ───────────────────────────────────────────────────────────────────
const dataPoints = ref([])      // 全部数据点
let nextFromStep = 0            // 下次轮询起始步
let pollTimer = null

const fetchNewPoints = async () => {
  try {
    const newPts = await getDataPoints(expId, nextFromStep)
    if (newPts.length) {
      dataPoints.value = [...dataPoints.value, ...newPts]
      nextFromStep = dataPoints.value[dataPoints.value.length - 1].step_idx + 1
      updateCharts()
    }
    // 更新试验状态
    const latest = await getExperiment(expId)
    experiment.value = latest
    if (latest.status !== 'running') {
      stopPolling()
    }
  } catch {
    // 静默处理轮询错误
  }
}

const startPolling = () => {
  if (pollTimer) return
  pollTimer = setInterval(fetchNewPoints, 2000)
}

const stopPolling = () => {
  if (pollTimer) {
    clearInterval(pollTimer)
    pollTimer = null
  }
}

// ── 控制操作 ───────────────────────────────────────────────────────────────────
const controlling = ref(false)

const handleStart = async () => {
  controlling.value = true
  try {
    await startExperiment(expId)
    experiment.value = await getExperiment(expId)
    ElMessage.success('MPC 控制已启动')
    startPolling()
  } finally {
    controlling.value = false
  }
}

const handleStop = async () => {
  controlling.value = true
  try {
    await stopExperiment(expId)
    stopPolling()
    experiment.value = await getExperiment(expId)
    // 加载全部数据点
    const all = await getDataPoints(expId, 0)
    dataPoints.value = all
    updateCharts()
    ElMessage.success('控制已停止')
  } finally {
    controlling.value = false
  }
}

// ── 报告 ───────────────────────────────────────────────────────────────────────
const reportVisible = ref(false)
const reportData = ref(null)
const loadingReport = ref(false)

const handleReport = async () => {
  loadingReport.value = true
  try {
    reportData.value = await getReport(expId)
    reportVisible.value = true
  } finally {
    loadingReport.value = false
  }
}

// ── 导出 ───────────────────────────────────────────────────────────────────────
const exporting = ref(false)

const handleExport = async () => {
  try {
    await ElMessageBox.confirm('确定将本次试验数据导出到历史数据吗？', '导出确认', { type: 'info' })
    exporting.value = true
    await exportToHistory(expId)
    experiment.value = await getExperiment(expId)
    ElMessage.success('已导出到历史数据')
  } catch {
    // 取消
  } finally {
    exporting.value = false
  }
}

// ── 图表 ───────────────────────────────────────────────────────────────────────
const tempChartRef = ref(null)
const currChartRef = ref(null)
let tempChart = null
let currChart = null

const MAX_CHART_POINTS = 300   // 超过时抽样显示

const buildDisplayData = () => {
  const pts = dataPoints.value
  if (!pts.length) return []
  const step = pts.length > MAX_CHART_POINTS ? Math.ceil(pts.length / MAX_CHART_POINTS) : 1
  return pts.filter((_, i) => i % step === 0)
}

const initCharts = () => {
  if (tempChartRef.value && !tempChart) {
    tempChart = echarts.init(tempChartRef.value)
  }
  if (currChartRef.value && !currChart) {
    currChart = echarts.init(currChartRef.value)
  }
  updateCharts()
}

const updateCharts = () => {
  const display = buildDisplayData()
  const xData = display.map((d) => `步${d.step_idx}`)
  const actuals = display.map((d) => d.actual_temp)
  const refs = display.map((d) => d.reference_temp)
  const currents = display.map((d) => d.current_output)
  const targetLine = display.map(() => experiment.value?.target_temp ?? null)

  // ── 温度图 ────────────────────────────────────────────────────────────────
  if (tempChart) {
    tempChart.setOption(
      {
        animation: false,
        color: ['#409EFF', '#67C23A', '#F56C6C'],
        tooltip: {
          trigger: 'axis',
          backgroundColor: 'rgba(255,255,255,0.96)',
          borderColor: '#e2e8f0',
          borderWidth: 1,
          formatter(params) {
            if (!params?.length) return ''
            const lines = [`<div style="margin-bottom:4px;font-weight:600">${params[0].axisValue}</div>`]
            params.forEach((p) => {
              const v = p.data != null ? Number(p.data).toFixed(3) + ' °C' : '--'
              lines.push(
                `<div style="display:flex;justify-content:space-between;gap:16px">
                  <span>${p.marker}${p.seriesName}</span><strong>${v}</strong>
                </div>`,
              )
            })
            return lines.join('')
          },
        },
        legend: {
          bottom: 4,
          itemWidth: 18,
          itemHeight: 8,
          textStyle: { color: '#475569', fontSize: 12 },
        },
        grid: { top: 16, left: 16, right: 16, bottom: 52, containLabel: true },
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: xData,
          axisLabel: { color: '#64748b', fontSize: 11, interval: Math.max(0, Math.floor(xData.length / 10) - 1) },
          axisLine: { lineStyle: { color: '#cbd5e1' } },
        },
        yAxis: {
          type: 'value',
          name: '温度 (°C)',
          nameTextStyle: { color: '#64748b', fontSize: 11 },
          axisLabel: { color: '#64748b', fontSize: 11 },
          splitLine: { lineStyle: { color: '#e2e8f0' } },
        },
        series: [
          {
            name: '实际温度',
            type: 'line',
            data: actuals,
            smooth: true,
            symbol: 'none',
            lineStyle: { width: 2 },
          },
          {
            name: '参考轨迹',
            type: 'line',
            data: refs,
            smooth: true,
            symbol: 'none',
            lineStyle: { width: 1.5, type: 'dashed' },
          },
          {
            name: '目标温度',
            type: 'line',
            data: targetLine,
            symbol: 'none',
            lineStyle: { width: 1.5, type: 'dotted', color: '#F56C6C' },
          },
        ],
      },
      true,
    )
  }

  // ── 电流图 ────────────────────────────────────────────────────────────────
  if (currChart) {
    currChart.setOption(
      {
        animation: false,
        color: ['#E6A23C'],
        tooltip: {
          trigger: 'axis',
          backgroundColor: 'rgba(255,255,255,0.96)',
          borderColor: '#e2e8f0',
          borderWidth: 1,
          formatter(params) {
            if (!params?.length) return ''
            const v = params[0].data != null ? Number(params[0].data).toFixed(3) + ' A' : '--'
            return `<div style="font-weight:600">${params[0].axisValue}</div>
                    <div>${params[0].marker}电流输出：<strong>${v}</strong></div>`
          },
        },
        legend: {
          bottom: 4,
          itemWidth: 18,
          itemHeight: 8,
          textStyle: { color: '#475569', fontSize: 12 },
        },
        grid: { top: 16, left: 16, right: 16, bottom: 52, containLabel: true },
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: xData,
          axisLabel: { color: '#64748b', fontSize: 11, interval: Math.max(0, Math.floor(xData.length / 10) - 1) },
          axisLine: { lineStyle: { color: '#cbd5e1' } },
        },
        yAxis: {
          type: 'value',
          name: '电流 (A)',
          nameTextStyle: { color: '#64748b', fontSize: 11 },
          axisLabel: { color: '#64748b', fontSize: 11 },
          splitLine: { lineStyle: { color: '#e2e8f0' } },
          min: 0,
        },
        series: [
          {
            name: '电流输出',
            type: 'line',
            data: currents,
            smooth: false,
            symbol: 'none',
            lineStyle: { width: 2 },
            areaStyle: { opacity: 0.08 },
          },
        ],
      },
      true,
    )
  }
}

// ── 窗口 resize ────────────────────────────────────────────────────────────────
const onResize = () => {
  tempChart?.resize()
  currChart?.resize()
}

// ── 生命周期 ───────────────────────────────────────────────────────────────────
onMounted(async () => {
  await loadExperiment()
  // 加载已有数据点
  const pts = await getDataPoints(expId, 0)
  dataPoints.value = pts
  if (pts.length) nextFromStep = pts[pts.length - 1].step_idx + 1

  await nextTick()
  initCharts()

  if (experiment.value?.status === 'running') {
    startPolling()
  }

  window.addEventListener('resize', onResize)
})

onBeforeUnmount(() => {
  stopPolling()
  window.removeEventListener('resize', onResize)
  tempChart?.dispose()
  currChart?.dispose()
})

// ── 状态辅助 ───────────────────────────────────────────────────────────────────
const statusType = (s) => ({ idle: 'info', running: 'success', stopped: '' }[s] ?? 'info')
const statusLabel = (s) => ({ idle: '未开始', running: '运行中', stopped: '已停止' }[s] ?? s)

const latestPoint = computed(() => {
  const pts = dataPoints.value
  return pts.length ? pts[pts.length - 1] : null
})
</script>

<template>
  <div class="detail-page" v-loading="loadingExp">
    <!-- 顶部导航 -->
    <div class="page-header">
      <el-button :icon="ArrowLeft" link @click="router.back()">返回列表</el-button>
      <span class="header-title">{{ experiment?.name ?? '试验详情' }}</span>
      <el-tag v-if="experiment" :type="statusType(experiment.status)" size="small">
        {{ statusLabel(experiment.status) }}
      </el-tag>
    </div>

    <template v-if="experiment">
      <!-- 信息卡 + 控制面板 -->
      <el-row :gutter="16" class="info-row">
        <!-- 试验信息 -->
        <el-col :span="16">
          <el-card shadow="hover" class="info-card">
            <div class="info-grid">
              <div class="info-item">
                <span class="label">预测模型</span>
                <span class="value">{{ experiment.model_name }}</span>
              </div>
              <div class="info-item">
                <span class="label">初始数据包</span>
                <span class="value">{{ experiment.package_name }}</span>
              </div>
              <div class="info-item">
                <span class="label">目标温度</span>
                <span class="value highlight">{{ experiment.target_temp?.toFixed(1) }} °C</span>
              </div>
              <div class="info-item">
                <span class="label">已采集步数</span>
                <span class="value">{{ experiment.total_steps }}</span>
              </div>
              <div class="info-item">
                <span class="label">采样周期</span>
                <span class="value">{{ experiment.sampling_interval ?? 1.0 }} s</span>
              </div>
              <div class="info-item">
                <span class="label">开始时间</span>
                <span class="value">{{ experiment.start_time ?? '--' }}</span>
              </div>
              <div class="info-item">
                <span class="label">停止时间</span>
                <span class="value">{{ experiment.stop_time ?? '--' }}</span>
              </div>
            </div>
            <div v-if="experiment.error_msg" class="error-msg">
              ⚠ {{ experiment.error_msg }}
            </div>
          </el-card>
        </el-col>

        <!-- 实时读数 + 操作 -->
        <el-col :span="8">
          <el-card shadow="hover" class="control-card">
            <div class="realtime-stats">
              <div class="stat-item">
                <div class="stat-label">当前温度</div>
                <div class="stat-value temp">
                  {{ latestPoint ? latestPoint.actual_temp.toFixed(3) : '--' }} °C
                </div>
              </div>
              <div class="stat-item">
                <div class="stat-label">参考轨迹</div>
                <div class="stat-value ref">
                  {{ latestPoint ? latestPoint.reference_temp.toFixed(3) : '--' }} °C
                </div>
              </div>
              <div class="stat-item">
                <div class="stat-label">当前电流</div>
                <div class="stat-value curr">
                  {{ latestPoint ? latestPoint.current_output.toFixed(3) : '--' }} A
                </div>
              </div>
              <div class="stat-item">
                <div class="stat-label">目标温度</div>
                <div class="stat-value target">
                  {{ experiment.target_temp?.toFixed(1) }} °C
                </div>
              </div>
            </div>

            <div class="control-btns">
              <el-button
                v-if="!isRunning"
                type="success"
                :icon="VideoPlay"
                :loading="controlling"
                :disabled="isStopped && experiment.total_steps >= 600"
                style="width:100%;margin-bottom:10px"
                @click="handleStart"
              >
                开始 MPC 控制
              </el-button>
              <el-button
                v-else
                type="danger"
                :icon="VideoPause"
                :loading="controlling"
                style="width:100%;margin-bottom:10px"
                @click="handleStop"
              >
                停止控制
              </el-button>

              <el-button
                type="primary"
                :icon="DataAnalysis"
                :loading="loadingReport"
                :disabled="!experiment.total_steps"
                style="width:100%;margin-bottom:10px"
                plain
                @click="handleReport"
              >
                查看报告
              </el-button>

              <el-button
                :icon="Download"
                :loading="exporting"
                :disabled="isRunning || !experiment.total_steps || experiment.exported"
                style="width:100%"
                plain
                @click="handleExport"
              >
                {{ experiment.exported ? '已导出' : '导出到历史数据' }}
              </el-button>
            </div>
          </el-card>
        </el-col>
      </el-row>

      <!-- MPC 参数展示 -->
      <el-card shadow="hover" class="params-card">
        <template #header>
          <span class="card-title">MPC 控制参数</span>
        </template>
        <div class="params-row" v-if="experiment.mpc_params">
          <span v-for="(v, k) in experiment.mpc_params" :key="k" class="param-chip">
            <span class="param-key">{{ k }}</span>
            <span class="param-val">{{ v }}</span>
          </span>
        </div>
      </el-card>

      <!-- 温度曲线图 -->
      <el-card shadow="hover" class="chart-card">
        <template #header>
          <div class="chart-header">
            <span class="card-title">温度曲线</span>
            <span v-if="isRunning" class="live-badge">● 实时更新中</span>
          </div>
        </template>
        <div v-if="!dataPoints.length" class="empty-chart">
          <el-empty description="暂无数据，请启动 MPC 控制" :image-size="80" />
        </div>
        <div v-else ref="tempChartRef" class="chart-body" />
      </el-card>

      <!-- 电流曲线图 -->
      <el-card shadow="hover" class="chart-card">
        <template #header>
          <span class="card-title">电流输出曲线</span>
        </template>
        <div v-if="!dataPoints.length" class="empty-chart">
          <el-empty description="暂无数据" :image-size="80" />
        </div>
        <div v-else ref="currChartRef" class="chart-body" />
      </el-card>
    </template>

    <!-- 报告对话框 -->
    <el-dialog v-model="reportVisible" title="试验报告" width="620px">
      <template v-if="reportData">
        <el-descriptions :column="2" border size="small" class="report-desc">
          <el-descriptions-item label="试验名称" :span="2">
            {{ reportData.experiment?.name }}
          </el-descriptions-item>
          <el-descriptions-item label="目标温度">
            {{ reportData.summary?.target_temp?.toFixed(1) }} °C
          </el-descriptions-item>
          <el-descriptions-item label="最终温度">
            {{ reportData.summary?.final_temp?.toFixed(3) }} °C
          </el-descriptions-item>
          <el-descriptions-item label="初始温度">
            {{ reportData.summary?.initial_temp?.toFixed(3) }} °C
          </el-descriptions-item>
          <el-descriptions-item label="采集步数">
            {{ reportData.summary?.total_steps }}
          </el-descriptions-item>
          <el-descriptions-item label="仿真时长">
            {{ reportData.summary?.duration_s }} s
          </el-descriptions-item>
          <el-descriptions-item label="调节时间（步）">
            {{ reportData.summary?.settling_step ?? '未稳定' }}
          </el-descriptions-item>
          <el-descriptions-item label="MAE (°C)">
            {{ reportData.summary?.mae }}
          </el-descriptions-item>
          <el-descriptions-item label="RMSE (°C)">
            {{ reportData.summary?.rmse }}
          </el-descriptions-item>
          <el-descriptions-item label="最大超调 (°C)">
            {{ reportData.summary?.overshoot }}
          </el-descriptions-item>
          <el-descriptions-item label="平均电流 (A)">
            {{ reportData.summary?.avg_current }}
          </el-descriptions-item>
          <el-descriptions-item label="最大电流 (A)">
            {{ reportData.summary?.max_current }}
          </el-descriptions-item>
        </el-descriptions>
      </template>
      <template #footer>
        <el-button @click="reportVisible = false">关闭</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<style lang="scss" scoped>
.detail-page {
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.page-header {
  display: flex;
  align-items: center;
  gap: 12px;

  .header-title {
    font-size: 16px;
    font-weight: 600;
    color: var(--text-primary);
    flex: 1;
  }
}

.info-row {
  margin: 0 !important;
}

.info-card {
  height: 100%;

  .info-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px 24px;
  }

  .info-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }

  .label {
    font-size: 12px;
    color: var(--text-tertiary);
  }

  .value {
    font-size: 14px;
    color: var(--text-primary);
    font-weight: 500;

    &.highlight {
      color: #165dff;
      font-size: 18px;
      font-weight: 700;
    }
  }

  .error-msg {
    margin-top: 12px;
    color: #f56c6c;
    font-size: 13px;
    background: #fff0f0;
    padding: 8px 12px;
    border-radius: 4px;
  }
}

.control-card {
  .realtime-stats {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    margin-bottom: 16px;
  }

  .stat-item {
    text-align: center;
    padding: 10px 8px;
    border-radius: 6px;
    background: var(--bg-page);
  }

  .stat-label {
    font-size: 11px;
    color: var(--text-tertiary);
    margin-bottom: 4px;
  }

  .stat-value {
    font-size: 16px;
    font-weight: 700;

    &.temp { color: #409eff; }
    &.ref  { color: #67c23a; }
    &.curr { color: #e6a23c; }
    &.target { color: #f56c6c; }
  }
}

.params-card {
  .params-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
  }

  .param-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 10px;
    border-radius: 12px;
    background: var(--primary-light);
    font-size: 12px;

    .param-key {
      color: var(--text-secondary);
    }

    .param-val {
      color: var(--primary);
      font-weight: 600;
    }
  }
}

.chart-card {
  .chart-header {
    display: flex;
    align-items: center;
    gap: 12px;
  }

  .live-badge {
    font-size: 12px;
    color: #67c23a;
    animation: blink 1.2s ease-in-out infinite;
  }

  .empty-chart {
    height: 240px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .chart-body {
    height: 280px;
    width: 100%;
  }
}

.card-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
}

.report-desc {
  :deep(.el-descriptions__label) {
    width: 140px;
  }
}

@keyframes blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}
</style>
