<template>
  <el-config-provider :locale="zhCn">
    <el-dialog
        v-model="visible"
        title="📈 设备数据详情"
        width="90%"
        top="5vh"
        destroy-on-close
        @closed="disposeCharts"
        append-to-body
    >
      <div class="dialog-header-bar">
        <div class="device-info">
          <span class="d-name">{{ formatDisplayName(deviceName) }}</span>
          <el-tag size="small" type="info" v-if="currentSource">Source: {{ currentSource }}</el-tag>
          <span class="latest-time-hint" v-if="dataTimestamp">
            (数据时间: {{ dataTimestamp }})
          </span>
        </div>

        <div class="date-filter">
          <span class="label">选择日期：</span>
          <el-date-picker
              v-model="selectedDate"
              type="date"
              placeholder="选择日期"
              :disabled-date="disabledDate"
              format="YYYY-MM-DD"
              value-format="YYYY-MM-DD"
              @change="handleDateChange"
              :clearable="false"
              style="width: 150px;"
          />
          <el-button
              circle
              icon="Refresh"
              type="primary"
              plain
              @click="loadData"
              style="margin-left: 10px"
              title="刷新当前数据"
          />
        </div>
      </div>

      <div class="monitor-dialog-content" v-loading="loading">
        <el-empty
            v-if="!loading && chartModules.length === 0"
            :description="emptyText"
        >
          <template #default>
            <div>{{ emptyText }}</div>
            <div style="font-size: 12px; color: #999; margin-top: 5px;" v-if="emptyText.includes('解析失败')">
              (请按 F12 查看控制台 Console 日志以排查数据格式)
            </div>
          </template>
        </el-empty>

        <div v-else class="charts-scroll-container">
          <div
              v-for="(module, index) in chartModules"
              :key="index"
              class="chart-wrapper"
          >
            <div :ref="(el) => setChartRef(el, index)" class="echart-container"></div>
          </div>
        </div>
      </div>
    </el-dialog>
  </el-config-provider>
</template>

<script setup>
import { ref, nextTick, onBeforeUnmount } from 'vue'
import request from '../utils/request' // 确保 request 工具路径正确
import * as echarts from 'echarts'
import { ElConfigProvider } from 'element-plus'
import zhCn from 'element-plus/es/locale/lang/zh-cn'

// --- 状态定义 ---
const visible = ref(false)
const loading = ref(false)
const deviceName = ref('')
const currentSource = ref('')
const selectedDate = ref('')
const dataTimestamp = ref('')
const chartModules = ref([])
const emptyText = ref('暂无数据')

// --- ECharts 实例管理 ---
let chartInstances = []
const chartRefs = ref([])

// 动态 Ref 设置函数
const setChartRef = (el, index) => {
  if (el) chartRefs.value[index] = el
}

// 日期禁用逻辑
const disabledDate = (time) => {
  return time.getTime() > Date.now()
}

// 格式化设备名称
const formatDisplayName = (name) => (name ? name.toUpperCase().replace(/_/g, ' ') : '')

// 获取今天的日期字符串 YYYY-MM-DD
const getTodayString = () => {
  const today = new Date()
  const y = today.getFullYear()
  const m = String(today.getMonth() + 1).padStart(2, '0')
  const d = String(today.getDate()).padStart(2, '0')
  return `${y}-${m}-${d}`
}

// --- 核心入口 ---
const open = (row) => {
  visible.value = true
  deviceName.value = row.name
  currentSource.value = row.source
  chartModules.value = []

  // 处理初始日期
  if (row.latest_time && row.latest_time !== 'N/A') {
    dataTimestamp.value = row.latest_time
    try {
      const datePart = row.latest_time.split(' ')[0].split('T')[0]
      selectedDate.value = datePart
    } catch (e) {
      console.warn('时间格式解析异常，回退到今天', row.latest_time)
      selectedDate.value = getTodayString()
    }
  } else {
    selectedDate.value = getTodayString()
    dataTimestamp.value = ''
  }

  loadData()
}

// 日期改变回调
const handleDateChange = () => {
  dataTimestamp.value = ''
  loadData()
}

// --- 数据加载逻辑 (已修复崩溃问题) ---
const loadData = async () => {
  if (!deviceName.value || !selectedDate.value) return

  loading.value = true
  chartModules.value = []
  emptyText.value = '加载中...'

  disposeCharts()

  try {
    const res = await request.get('/api/device_data_by_date', {
      params: {
        name: deviceName.value,
        date: selectedDate.value
      }
    })

    // 1. 获取原始数据
    const rawContent = res.data.content
    const source = res.data.source

    // 2. 关键修复：安全转换。如果 content 是 null/undefined，转为空字符串；如果是对象，转为字符串。
    let safeContent = ''
    if (rawContent !== null && rawContent !== undefined) {
      safeContent = typeof rawContent === 'object' ? JSON.stringify(rawContent) : String(rawContent)
    }

    const effectiveSource = source || currentSource.value

    // Debug日志
    console.log(`[LoadData] Source: ${effectiveSource}, Safe Content Length: ${safeContent.length}`)

    // 3. 判空逻辑
    // 注意：有时候后端返回字符串 "null" 或 "{}" 也代表空
    if (!safeContent || safeContent === 'null' || safeContent === '{}' || safeContent === '""') {
      emptyText.value = `${selectedDate.value} 无数据记录`
    } else {
      // 4. 解析数据
      const modules = parseChartData({
        name: deviceName.value,
        content: safeContent, // 传入处理后的安全字符串
        source: effectiveSource
      })

      chartModules.value = modules

      if (modules.length === 0) {
        // 安全截取字符串，避免报错
        console.warn('解析结果为空。原始内容片段:', safeContent.substring(0, 100))
        emptyText.value = '数据解析失败 (格式不匹配)'
      } else {
        await nextTick()
        initCharts()
      }
    }
  } catch (e) {
    if (e.response && e.response.status === 404) {
      emptyText.value = `${selectedDate.value} 无数据记录`
    } else {
      console.error('Data Load Error:', e)
      emptyText.value = '数据加载异常'
    }
  } finally {
    loading.value = false
  }
}

// --- 解析器：106 系列 ---
function parse106Data(content) {
  if (typeof content !== 'string') return []
  const modules = []

  // 宽松正则：不强制开头，允许空格，允许跨行匹配
  const blockRegex = /(?:FS\d_Info|Info)?[\s\S]*?Model\s*,\s*([^,\r\n]+)[\s\S]*?SN\s*,\s*([^,\r\n]+)[\s\S]*?Wavelength\s*,\s*([0-9\.,\s]+)/gi

  let match
  blockRegex.lastIndex = 0

  while ((match = blockRegex.exec(content)) !== null) {
    const modelRaw = match[1].trim()
    const snRaw = match[2].trim()
    const waveRaw = match[3]

    const wavelengths = waveRaw.split(',').map(Number).filter((n) => !isNaN(n))
    if (wavelengths.length === 0) continue

    const series = []

    for (let p = 1; p <= 4; p++) {
      // 转义 Model 名称中的特殊字符
      const escapedModel = modelRaw.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')

      const pRegex = new RegExp(`${escapedModel}_P${p}[^0-9-]*([\\d\\.,\\s-]+)`, 'i')

      const dMatch = content.match(pRegex)
      if (dMatch) {
        const vals = dMatch[1].split(',').map((v) => parseFloat(v))
        if (vals.some((v) => v !== null && !isNaN(v))) {
          series.push({
            name: `P${p}`,
            data: vals,
            color: ['#5470c6', '#91cc75', '#fac858', '#ee6666'][p - 1],
          })
        }
      }
    }

    if (series.length) {
      modules.push({ type: '106', model: modelRaw, sn: snRaw, xAxis: wavelengths, series })
    }
  }
  return modules
}

// --- 解析器：82 系列 ---
function parse82Data(content, deviceName) {
  try {
    const d = typeof content === 'string' ? JSON.parse(content) : content

    if (d && (d.wavelenth || d.wavelength)) {
      const xData = d.wavelenth || d.wavelength
      return [{
        type: '82',
        title: deviceName,
        xAxis: xData,
        series: [
          { name: 'DownSpec', data: d.downspec, color: '#409EFF' },
          { name: 'UpSpec', data: d.upspec, color: '#67C23A' },
        ],
      }]
    }
    return []
  } catch (e) {
    console.warn('JSON Parse 82 Error', e)
    return []
  }
}

// --- 主解析入口 ---
function parseChartData(device) {
  if (!device || !device.content) return []

  // 这里的 content 已经是经过 loadData 转换的安全字符串了
  const contentStr = device.content.trim()

  const is106Source = (device.source && device.source.includes('106'))
  // 判断是否像 106 文本 (不以{开头 且 包含Model关键字)
  const looksLike106Text = !contentStr.startsWith('{') && /Model/i.test(contentStr)

  if (is106Source || looksLike106Text) {
    return parse106Data(contentStr)
  } else {
    return parse82Data(contentStr, device.name)
  }
}

// --- ECharts 配置 ---
function getChartOption(moduleData, isMobile = false) {
  const titleText = moduleData.type === '106'
      ? `Model: ${moduleData.model} (SN: ${moduleData.sn})`
      : moduleData.title

  return {
    title: {
      text: titleText,
      left: 'center',
      top: 10,
      textStyle: { fontSize: isMobile ? 14 : 16 },
    },
    tooltip: {
      trigger: 'axis',
      confine: true,
      axisPointer: { type: 'cross' }
    },
    legend: { top: 35, type: 'scroll' },
    toolbox: {
      feature: {
        saveAsImage: { title: '保存' },
        dataZoom: { title: { zoom: '缩放', back: '还原' } }
      }
    },
    grid: {
      top: 80,
      bottom: 30,
      right: isMobile ? 10 : 40,
      left: isMobile ? 40 : 50
    },
    xAxis: {
      type: 'category',
      data: moduleData.xAxis,
      boundaryGap: false,
      name: 'nm'
    },
    yAxis: {
      type: 'value',
      min: 'dataMin',
      max: 'dataMax',
      scale: true
    },
    series: moduleData.series.map((s) => ({
      name: s.name,
      type: 'line',
      data: s.data,
      connectNulls: false,
      smooth: true,
      showSymbol: false,
      lineStyle: { width: 1.5, color: s.color },
      areaStyle: { opacity: 0.1, color: s.color },
    })),
  }
}

// --- ECharts 初始化 ---
const initCharts = () => {
  if (chartModules.value.length === 0) return
  const isMobile = window.innerWidth < 768

  chartModules.value.forEach((mod, index) => {
    const el = chartRefs.value[index]
    if (el) {
      const oldInstance = echarts.getInstanceByDom(el)
      if (oldInstance) oldInstance.dispose()

      const chart = echarts.init(el)
      chart.setOption(getChartOption(mod, isMobile))
      chartInstances.push(chart)
    }
  })
}

// --- ECharts 销毁 ---
const disposeCharts = () => {
  chartInstances.forEach((chart) => chart && chart.dispose())
  chartInstances = []
  chartRefs.value = []
}

defineExpose({ open })
onBeforeUnmount(() => disposeCharts())
</script>

<style scoped>
.dialog-header-bar {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 20px; padding-bottom: 15px; border-bottom: 1px solid #EBEEF5;
}
.device-info { display: flex; align-items: center; gap: 10px; }
.d-name { font-size: 18px; font-weight: bold; color: #303133; }
.latest-time-hint { font-size: 12px; color: #909399; margin-left: 5px; }

.date-filter { display: flex; align-items: center; }
.label { font-size: 14px; color: #606266; margin-right: 8px; }

.monitor-dialog-content { min-height: 400px; padding: 10px; }
.charts-scroll-container { display: flex; flex-direction: column; gap: 20px; }
.chart-wrapper {
  background: #fff; border-radius: 8px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
  padding: 10px; border: 1px solid #EBEEF5;
}
.echart-container { width: 100%; height: 450px; }

@media screen and (max-width: 768px) {
  .dialog-header-bar { flex-direction: column; align-items: flex-start; gap: 10px; }
  .echart-container { height: 350px; }
}
</style>
