<template>
  <div class="app-container">
    <!-- 顶部导航 -->
    <el-header class="app-header">
      <div class="header-left">
        <el-icon :size="28" color="#409eff"><Monitor /></el-icon>
        <h1>K8S 智能诊断平台</h1>
        <el-tag v-if="diagnosis" :type="statusTagType" size="large" effect="dark">
          健康评分: {{ diagnosis.score }}/100
        </el-tag>
      </div>
      <div class="header-right">
        <el-input v-model="namespace" placeholder="命名空间 (留空=全部)" clearable style="width: 200px" />
        <el-button type="primary" :loading="diagnosing" @click="runDiagnosis" :icon="Refresh" :disabled="diagnosing">
          {{ diagnosing ? '诊断中...' : '一键诊断' }}
        </el-button>
        <el-button type="success" :loading="analyzing" @click="runAnalysis" :icon="MagicStick" :disabled="!diagnosis || diagnosing || agentRunning">
          {{ analyzing ? 'AI 分析中...' : 'AI 分析' }}
        </el-button>
        <el-radio-group v-model="agentExecutionMode" :disabled="agentRunning" class="agent-mode-switch">
          <el-radio-button value="manual">手动执行命令</el-radio-button>
          <el-radio-button value="ai">AI 执行命令</el-radio-button>
        </el-radio-group>
        <el-button @click="openHistory" :disabled="diagnosing || analyzing || agentRunning">历史记录</el-button>
        <el-button type="warning" :loading="agentRunning" @click="runAgentDiagnosis" :disabled="!diagnosis || diagnosing || analyzing">
          {{ agentRunning ? 'Agent 诊断中...' : '自主诊断' }}
        </el-button>
      </div>
    </el-header>

    <el-main class="app-main">
      <!-- 未诊断时的欢迎页 -->
      <div v-if="!diagnosis && !diagnosing" class="welcome">
        <el-empty description="点击「一键诊断」开始集群健康检查">
          <el-button type="primary" size="large" @click="runDiagnosis" :icon="Refresh">开始诊断</el-button>
        </el-empty>
      </div>

      <!-- 诊断中 - 实时进度 -->
      <div v-if="diagnosing" class="progress-box">
        <el-card shadow="never" class="progress-card">
          <template #header>
            <div class="card-header">
              <span>🔍 正在执行集群诊断</span>
              <el-tag size="small" type="info">{{ progressStep }}/{{ progressTotal }}</el-tag>
            </div>
          </template>
          <el-progress :percentage="progressPercent" :stroke-width="10" :color="'#409eff'" style="margin-bottom: 20px" />
          <div class="progress-steps">
            <div v-for="item in progressList" :key="item.name" class="progress-item" :class="'status-' + item.status">
              <span class="step-icon">
                <el-icon v-if="item.status === 'running'" class="is-loading" color="#409eff"><Loading /></el-icon>
                <el-icon v-else-if="item.status === 'done'" color="#67c23a"><CircleCheckFilled /></el-icon>
                <el-icon v-else color="#c0c4cc"><CircleClose /></el-icon>
              </span>
              <span class="step-title">{{ item.title }}</span>
              <span v-if="item.status === 'done'" class="step-result">
                <el-tag v-if="item.issues > 0" size="small" :type="item.issues > 0 ? 'warning' : 'success'">
                  {{ item.issues }} 个问题
                </el-tag>
                <el-tag v-else size="small" type="success">正常</el-tag>
              </span>
              <span v-if="item.status === 'running'" class="step-running">检查中...</span>
            </div>
          </div>
        </el-card>
      </div>

      <!-- 集群连接失败 -->
      <div v-if="diagnosis && !diagnosing && diagnosis.connected === false" class="conn-error-box">
        <el-card shadow="never" class="conn-error-card">
          <div class="conn-error-icon">
            <el-icon :size="64" color="#f56c6c"><CircleCloseFilled /></el-icon>
          </div>
          <h2>无法连接到 Kubernetes 集群</h2>
          <div class="conn-error-detail">
            <el-alert type="error" :closable="false" show-icon>
              <template #title>错误信息</template>
              <pre class="conn-error-pre">{{ diagnosis.connectivity_error }}</pre>
            </el-alert>
            <el-alert v-if="diagnosis.connectivity_suggestion" type="warning" :closable="false" show-icon style="margin-top: 12px">
              <template #title>排查建议</template>
              <div>{{ diagnosis.connectivity_suggestion }}</div>
            </el-alert>
          </div>
          <div class="conn-error-actions">
            <el-button type="primary" @click="runDiagnosis" :icon="Refresh">重新诊断</el-button>
          </div>
        </el-card>
      </div>

      <!-- 诊断结果 -->
      <template v-if="diagnosis && !diagnosing && diagnosis.connected !== false">
        <!-- 概览卡片 -->
        <el-row :gutter="16" class="summary-row">
          <el-col :span="4">
            <el-card shadow="hover" class="score-card" :class="'score-' + diagnosis.status">
              <div class="score-number">{{ diagnosis.score }}</div>
              <div class="score-label">健康评分</div>
            </el-card>
          </el-col>
          <el-col :span="4">
            <el-card shadow="hover">
              <el-statistic title="严重问题" :value="diagnosis.critical_count">
                <template #suffix><el-icon color="#f56c6c"><WarningFilled /></el-icon></template>
              </el-statistic>
            </el-card>
          </el-col>
          <el-col :span="4">
            <el-card shadow="hover">
              <el-statistic title="警告" :value="diagnosis.warning_count">
                <template #suffix><el-icon color="#e6a23c"><Warning /></el-icon></template>
              </el-statistic>
            </el-card>
          </el-col>
          <el-col :span="4">
            <el-card shadow="hover">
              <el-statistic title="Pod 总数" :value="podSummary.total" />
            </el-card>
          </el-col>
          <el-col :span="4">
            <el-card shadow="hover">
              <el-statistic title="Node 就绪" :value="nodeSummary.ready + '/' + nodeSummary.total" />
            </el-card>
          </el-col>
          <el-col :span="4">
            <el-card shadow="hover">
              <el-statistic title="诊断耗时" :value="diagnosis.elapsed_seconds + 's'" />
            </el-card>
          </el-col>
        </el-row>

        <!-- 问题列表 -->
        <el-card v-if="diagnosis.issues.length" class="section-card" shadow="never">
          <template #header>
            <div class="card-header">
              <span>🔍 发现的问题 ({{ diagnosis.issues.length }})</span>
            </div>
          </template>
          <el-table :data="diagnosis.issues" stripe size="small" max-height="300">
            <el-table-column label="级别" width="80" align="center">
              <template #default="{ row }">
                <el-tag :type="row.level === 'critical' ? 'danger' : 'warning'" size="small" effect="dark">
                  {{ row.level === 'critical' ? '严重' : '警告' }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="check" label="检查项" width="160" />
            <el-table-column prop="resource" label="资源" width="260" />
            <el-table-column prop="message" label="问题描述" />
          </el-table>
        </el-card>

        <!-- 各检查项详情 -->
        <el-row :gutter="16">
          <el-col :span="12">
            <el-card class="section-card" shadow="never">
              <template #header><span>📦 Pod 状态</span></template>
              <div class="pod-stats">
                <el-tag type="success" size="large">Running: {{ podSummary.running }}</el-tag>
                <el-tag type="warning" size="large">Pending: {{ podSummary.pending }}</el-tag>
                <el-tag type="danger" size="large">Failed: {{ podSummary.failed }}</el-tag>
                <el-tag type="info" size="large">CrashLoop: {{ podSummary.crashloop }}</el-tag>
              </div>
            </el-card>
          </el-col>
          <el-col :span="12">
            <el-card class="section-card" shadow="never">
              <template #header><span>🖥️ Node 状态</span></template>
              <div class="pod-stats">
                <el-tag type="success" size="large">Ready: {{ nodeSummary.ready }}</el-tag>
                <el-tag type="danger" size="large">NotReady: {{ nodeSummary.not_ready }}</el-tag>
              </div>
              <div v-if="resourceNodes.length" style="margin-top: 12px">
                <div v-for="n in resourceNodes" :key="n.name" class="resource-bar">
                  <span class="res-name">{{ n.name }}</span>
                  <el-progress :percentage="n.cpu_pct" :color="barColor(n.cpu_pct)" :stroke-width="14" style="flex:1">
                    <span>CPU {{ n.cpu_pct }}%</span>
                  </el-progress>
                  <el-progress :percentage="n.mem_pct" :color="barColor(n.mem_pct)" :stroke-width="14" style="flex:1">
                    <span>MEM {{ n.mem_pct }}%</span>
                  </el-progress>
                </div>
              </div>
            </el-card>
          </el-col>
        </el-row>

        <!-- Deployment 状态 -->
        <el-card v-if="deployments.length" class="section-card" shadow="never">
          <template #header><span>🚀 Deployment 状态</span></template>
          <el-table :data="deployments" stripe size="small">
            <el-table-column prop="namespace" label="命名空间" width="160" />
            <el-table-column prop="name" label="名称" />
            <el-table-column label="副本" width="120" align="center">
              <template #default="{ row }">
                <el-tag :type="row.ready >= row.desired ? 'success' : 'danger'" size="small">
                  {{ row.ready }}/{{ row.desired }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="updated" label="已更新" width="80" align="center" />
          </el-table>
        </el-card>

        <!-- 异常事件 -->
        <el-card v-if="warningEvents.length" class="section-card" shadow="never">
          <template #header><span>⚡ 异常事件 (最近 {{ warningEvents.length }} 条)</span></template>
          <el-table :data="warningEvents" stripe size="small" max-height="250">
            <el-table-column prop="namespace" label="NS" width="120" />
            <el-table-column prop="object" label="对象" width="220" />
            <el-table-column prop="reason" label="原因" width="160" />
            <el-table-column prop="message" label="消息" show-overflow-tooltip />
            <el-table-column prop="count" label="次数" width="60" align="center" />
          </el-table>
        </el-card>

      </template>

      <!-- AI 分析结果 (连接成功或失败都显示) -->
      <el-card v-if="diagnosis && !diagnosing && (aiAnalysis || analyzing)" class="section-card ai-card" shadow="never">
        <template #header>
          <div class="card-header">
            <span>🤖 AI 智能分析</span>
            <div class="ai-header-meta">
              <el-tag v-if="analyzing" size="small" type="primary" effect="light">分析中</el-tag>
              <el-tag v-else-if="aiAnalysis" size="small" type="success" effect="light">已完成</el-tag>
              <el-tag v-if="aiModel" size="small" type="info">{{ aiModel }}</el-tag>
            </div>
          </div>
        </template>
        <div v-if="analysisProcess.length" class="analysis-process">
          <div class="process-heading">
            <span>分析过程</span>
            <span>{{ analysisCompleted }}/{{ analysisProcess.length }}</span>
          </div>
          <el-progress
            :percentage="analysisProgressPercent"
            :stroke-width="6"
            :show-text="false"
            :status="analysisProgressStatus"
          />
          <div class="analysis-step-list">
            <div v-for="item in analysisProcess" :key="item.step" class="analysis-step" :class="'status-' + item.status">
              <span class="analysis-step-icon">
                <el-icon v-if="item.status === 'running'" class="is-loading" color="#409eff"><Loading /></el-icon>
                <el-icon v-else-if="item.status === 'done'" color="#67c23a"><CircleCheckFilled /></el-icon>
                <el-icon v-else color="#c0c4cc"><CircleClose /></el-icon>
              </span>
              <div class="analysis-step-body">
                <strong>{{ item.title }}</strong>
                <span>{{ item.detail }}</span>
              </div>
              <el-tag v-if="item.status === 'running'" size="small" type="primary">处理中</el-tag>
              <el-tag v-else-if="item.status === 'done'" size="small" type="success">完成</el-tag>
              <el-tag v-else size="small" type="info">等待</el-tag>
            </div>
          </div>
        </div>
        <el-divider v-if="analysisProcess.length && (aiAnalysis || analyzing)" />
        <div v-if="analyzing && !aiAnalysis" class="ai-loading">
          <el-icon class="is-loading" color="#409eff"><Loading /></el-icon>
          <span>AI 正在生成分析结论，请稍候...</span>
        </div>
        <div class="ai-content" v-html="renderedAnalysis"></div>
      </el-card>

      <!-- 自主诊断 Agent -->
      <el-card v-if="diagnosis && !diagnosing && (agentRunning || agentEvents.length)" class="section-card agent-card" shadow="never">
        <template #header>
          <div class="card-header">
            <span>🧠 AI Agent 自主诊断</span>
            <div class="ai-header-meta">
              <el-tag :type="activeAgentMode === 'ai' ? 'success' : 'info'" size="small">
                {{ activeAgentMode === 'ai' ? 'AI 执行模式' : '手动执行模式' }}
              </el-tag>
              <el-tag v-if="activeAgentMode === 'ai'" type="warning" size="small">修改命令人工确认</el-tag>
            </div>
          </div>
        </template>
        <el-alert
          :title="activeAgentMode === 'ai'
            ? 'AI 执行模式：Agent 自动执行只读 kubectl 和系统诊断命令 (systemctl status、journalctl、crictl ps、df 等)，修改或交互命令仍需人工批准。'
            : '手动执行模式：Agent 只生成安全的诊断命令，不会在服务器上执行，请复制命令到终端手动运行。'"
          type="info"
          :closable="false"
          show-icon
          class="agent-alert"
        />
        <div class="agent-timeline">
          <div v-for="(event, index) in agentEvents" :key="index" class="agent-event" :class="'event-' + event.type">
            <div class="agent-event-title">
              <el-icon v-if="event.type === 'thinking'" class="is-loading" color="#409eff"><Loading /></el-icon>
              <el-icon v-else-if="event.type === 'result' || event.type === 'final'" color="#67c23a"><CircleCheckFilled /></el-icon>
              <el-icon v-else-if="event.type === 'approval_required'" color="#e6a23c"><WarningFilled /></el-icon>
              <el-icon v-else color="#909399"><Monitor /></el-icon>
              <strong>{{ agentEventTitle(event) }}</strong>
              <el-tag v-if="event.mode" :type="event.mode === 'read' ? 'success' : 'warning'" size="small">
                {{ event.mode === 'read' ? '只读' : '需审批' }}
              </el-tag>
            </div>
            <p v-if="event.message" class="agent-event-message">{{ event.message }}</p>
            <p v-if="event.reason" class="agent-event-message">目的：{{ event.reason }}</p>
            <pre v-if="event.command" class="agent-command">{{ event.command }}</pre>
            <pre v-if="event.stdout || event.stderr" class="agent-output">{{ event.stdout || event.stderr }}</pre>
            <div v-if="event.type === 'final'" class="ai-content" v-html="renderMd(event.content)"></div>
            <div v-if="event.type === 'manual_command'" class="manual-actions">
              <el-button type="primary" plain @click="copyAgentCommand(event.command)">复制命令</el-button>
              <span>请在你的终端中执行，Agent 不会自动运行该命令。</span>
            </div>
            <div v-if="event.type === 'approval_required' && !event.resolved" class="approval-actions">
              <el-button type="danger" @click="resolveApproval(event, true)" :loading="event.executing">确认执行</el-button>
              <el-button @click="resolveApproval(event, false)" :disabled="event.executing">拒绝</el-button>
            </div>
            <el-alert v-if="event.approvalResult" :title="event.approvalResult" :type="event.approvalSuccess ? 'success' : 'info'" :closable="false" />
          </div>
          <div v-if="agentRunning" class="agent-running">
            <el-icon class="is-loading" color="#409eff"><Loading /></el-icon>
            <span>Agent 正在分析命令结果并规划下一步...</span>
          </div>
        </div>
      </el-card>

      <!-- AI 对话 (连接成功或失败都显示) -->
      <el-card v-if="diagnosis && !diagnosing" class="section-card" shadow="never">
        <template #header><span>💬 追问 AI 助手</span></template>
        <div class="chat-box" ref="chatBoxRef">
          <div v-for="(msg, i) in chatMessages" :key="i" :class="'chat-msg ' + msg.role">
            <div class="chat-bubble" v-html="msg.role === 'assistant' ? renderMd(msg.content) : msg.content"></div>
          </div>
          <div v-if="chatLoading && !chatMessages.length" class="chat-msg assistant">
            <div class="chat-bubble"><el-icon class="is-loading"><Loading /></el-icon> 思考中...</div>
          </div>
        </div>
        <div class="chat-input">
          <el-input v-model="chatInput" placeholder="输入问题，如：为什么 Pod 一直 CrashLoopBackOff？" @keyup.enter="sendChat" :disabled="chatLoading" />
          <el-button type="primary" @click="sendChat" :loading="chatLoading" :icon="Promotion">发送</el-button>
        </div>
      </el-card>
    </el-main>

    <el-drawer v-model="historyVisible" title="历史诊断与处理记录" size="75%" @open="loadHistory">
      <div class="history-toolbar">
        <el-select v-model="historyStatus" placeholder="全部状态" clearable style="width: 150px" @change="loadHistory">
          <el-option label="健康" value="healthy" />
          <el-option label="警告" value="warning" />
          <el-option label="严重" value="critical" />
        </el-select>
        <el-input v-model="historyNamespace" placeholder="命名空间" clearable style="width: 180px" @keyup.enter="loadHistory" />
        <el-button type="primary" @click="loadHistory" :loading="historyLoading">查询</el-button>
      </div>
      <el-table :data="historyItems" stripe highlight-current-row @row-click="loadHistoryDetail" v-loading="historyLoading">
        <el-table-column prop="created_at" label="诊断时间" min-width="180" />
        <el-table-column prop="namespace" label="命名空间" min-width="110" />
        <el-table-column prop="score" label="评分" width="80" />
        <el-table-column label="状态" width="90">
          <template #default="{ row }"><el-tag :type="historyStatusType(row.status)">{{ historyStatusText(row.status) }}</el-tag></template>
        </el-table-column>
        <el-table-column prop="critical_count" label="严重" width="75" />
        <el-table-column prop="warning_count" label="警告" width="75" />
        <el-table-column prop="run_count" label="处理记录" width="100" />
        <el-table-column label="操作" width="100">
          <template #default="{ row }"><el-button link type="primary" @click.stop="loadHistoryDetail(row)">查看详情</el-button></template>
        </el-table-column>
      </el-table>

      <div v-if="historyDetail" class="history-detail">
        <el-divider content-position="left">诊断详情</el-divider>
        <el-descriptions :column="4" border>
          <el-descriptions-item label="时间">{{ historyDetail.created_at }}</el-descriptions-item>
          <el-descriptions-item label="命名空间">{{ historyDetail.diagnosis.namespace }}</el-descriptions-item>
          <el-descriptions-item label="健康评分">{{ historyDetail.diagnosis.score }}</el-descriptions-item>
          <el-descriptions-item label="状态">{{ historyStatusText(historyDetail.diagnosis.status) }}</el-descriptions-item>
        </el-descriptions>
        <el-collapse class="history-collapse">
          <el-collapse-item title="完整诊断报告" name="report">
            <pre class="history-report">{{ historyDetail.report }}</pre>
          </el-collapse-item>
          <el-collapse-item v-for="run in historyDetail.runs" :key="run.id" :name="run.id">
            <template #title>
              <span>{{ runKindText(run.kind) }} · {{ run.started_at }} · {{ runStatusText(run.status) }}</span>
            </template>
            <el-descriptions :column="3" size="small" border>
              <el-descriptions-item label="模式">{{ run.mode || '-' }}</el-descriptions-item>
              <el-descriptions-item label="问题">{{ run.question || '-' }}</el-descriptions-item>
              <el-descriptions-item label="结束时间">{{ run.finished_at || '-' }}</el-descriptions-item>
            </el-descriptions>
            <div v-for="(event, index) in run.events" :key="index" class="history-event">
              <div class="history-event-head"><el-tag size="small">{{ event.type }}</el-tag><span>{{ event.created_at }}</span></div>
              <pre>{{ formatHistoryEvent(event) }}</pre>
            </div>
          </el-collapse-item>
        </el-collapse>
      </div>
    </el-drawer>
  </div>
</template>

<script setup>
import { ref, computed, nextTick } from 'vue'
import { marked } from 'marked'
import { Refresh, MagicStick, Loading, WarningFilled, Warning, Promotion, Monitor, CircleCheckFilled, CircleClose, CircleCloseFilled } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'

const API = '/api'

const namespace = ref('')
const diagnosing = ref(false)
const analyzing = ref(false)
const agentRunning = ref(false)
const agentExecutionMode = ref('manual')
const activeAgentMode = ref('manual')
const agentEvents = ref([])
const diagnosis = ref(null)
const aiAnalysis = ref('')
const aiModel = ref('')
const analysisProcess = ref([])
const historyVisible = ref(false)
const historyLoading = ref(false)
const historyItems = ref([])
const historyDetail = ref(null)
const historyStatus = ref('')
const historyNamespace = ref('')
const chatMessages = ref([])
const chatInput = ref('')
const chatLoading = ref(false)
const chatBoxRef = ref(null)

// 诊断进度
const progressList = ref([])
const progressStep = ref(0)
const progressTotal = ref(9)

const progressPercent = computed(() => {
  if (progressTotal.value === 0) return 0
  return Math.round((progressStep.value / progressTotal.value) * 100)
})

const statusTagType = computed(() => {
  if (!diagnosis.value) return 'info'
  const s = diagnosis.value.status
  return s === 'healthy' ? 'success' : s === 'warning' ? 'warning' : 'danger'
})

const podSummary = computed(() => diagnosis.value?.checks?.pods?.summary || { total: 0, running: 0, pending: 0, failed: 0, crashloop: 0 })
const nodeSummary = computed(() => diagnosis.value?.checks?.nodes?.summary || { total: 0, ready: 0, not_ready: 0 })
const deployments = computed(() => diagnosis.value?.checks?.deployments?.deployments || [])
const warningEvents = computed(() => (diagnosis.value?.checks?.events?.events || []).filter(e => e.type === 'Warning').slice(-30))
const resourceNodes = computed(() => diagnosis.value?.checks?.resource_usage?.nodes || [])

const renderedAnalysis = computed(() => aiAnalysis.value ? renderMd(aiAnalysis.value) : '')
const analysisCompleted = computed(() => analysisProcess.value.filter(item => item.status === 'done').length)
const analysisProgressPercent = computed(() => {
  if (!analysisProcess.value.length) return 0
  return Math.round((analysisCompleted.value / analysisProcess.value.length) * 100)
})
const analysisProgressStatus = computed(() => analysisProgressPercent.value === 100 ? 'success' : '')

function renderMd(text) {
  return marked.parse(text || '', { breaks: true })
}

function barColor(pct) {
  if (pct > 90) return '#f56c6c'
  if (pct > 75) return '#e6a23c'
  return '#67c23a'
}

async function runDiagnosis() {
  diagnosing.value = true
  aiAnalysis.value = ''
  diagnosis.value = null
  progressList.value = []
  progressStep.value = 0
  progressTotal.value = 9

  try {
    const params = new URLSearchParams()
    if (namespace.value) params.set('namespace', namespace.value)
    const url = `${API}/diagnose/stream?${params.toString()}`

    const resp = await fetch(url)
    const reader = resp.body.getReader()
    const decoder = new TextDecoder()
    let buffer = ''

    while (true) {
      const { done, value } = await reader.read()
      if (done) break

      buffer += decoder.decode(value, { stream: true })
      const lines = buffer.split('\n')
      buffer = lines.pop() || ''

      for (const line of lines) {
        if (!line.startsWith('data: ')) continue
        const jsonStr = line.slice(6)
        if (!jsonStr) continue

        try {
          const msg = JSON.parse(jsonStr)

          if (msg.type === 'progress') {
            progressTotal.value = msg.total
            progressStep.value = msg.step

            if (msg.status === 'running') {
              progressList.value.push({ name: msg.name, title: msg.title, status: 'running', issues: 0 })
            } else if (msg.status === 'done') {
              const item = progressList.value.find(i => i.name === msg.name)
              if (item) {
                item.status = 'done'
                item.issues = msg.issues
              }
            }
          } else if (msg.type === 'complete') {
            diagnosis.value = msg.diagnosis
            ElMessage.success(`诊断完成，评分 ${msg.diagnosis.score}/100`)
          }
        } catch (e) {
          // ignore parse errors on partial data
        }
      }
    }
  } catch (e) {
    ElMessage.error('诊断失败: ' + e.message)
  } finally {
    diagnosing.value = false
  }
}

async function runAnalysis() {
  analyzing.value = true
  aiAnalysis.value = ''
  aiModel.value = ''
  analysisProcess.value = []
  try {
    const resp = await fetch(`${API}/analyze/stream`)
    const reader = resp.body.getReader()
    const decoder = new TextDecoder()
    let buffer = ''

    while (true) {
      const { done, value } = await reader.read()
      if (done) break

      buffer += decoder.decode(value, { stream: true })
      const lines = buffer.split('\n')
      buffer = lines.pop() || ''

      for (const line of lines) {
        if (!line.startsWith('data: ')) continue
        const jsonStr = line.slice(6)
        if (!jsonStr) continue
        try {
          const msg = JSON.parse(jsonStr)
          if (msg.type === 'start') {
            aiModel.value = msg.model || ''
          } else if (msg.type === 'process') {
            const item = analysisProcess.value.find(process => process.step === msg.step)
            if (item) {
              item.status = msg.status
              item.title = msg.title
              item.detail = msg.detail
            } else {
              analysisProcess.value.push({
                step: msg.step,
                title: msg.title,
                detail: msg.detail,
                status: msg.status,
              })
            }
          } else if (msg.type === 'chunk') {
            aiAnalysis.value += msg.content
          } else if (msg.type === 'error') {
            aiAnalysis.value = msg.message
            ElMessage.warning('AI 分析异常')
          } else if (msg.type === 'done') {
            ElMessage.success('AI 分析完成')
          }
        } catch (e) {
          // ignore
        }
      }
    }
  } catch (e) {
    aiAnalysis.value = 'AI 分析失败: ' + e.message
    ElMessage.error('AI 分析失败: ' + e.message)
  } finally {
    analyzing.value = false
  }
}

function openHistory() {
  historyVisible.value = true
}

async function loadHistory() {
  historyLoading.value = true
  historyDetail.value = null
  try {
    const params = new URLSearchParams({ limit: '200' })
    if (historyStatus.value) params.set('status', historyStatus.value)
    if (historyNamespace.value) params.set('namespace', historyNamespace.value)
    const resp = await fetch(`${API}/history/diagnoses?${params.toString()}`)
    if (!resp.ok) throw new Error(`HTTP ${resp.status}`)
    const data = await resp.json()
    historyItems.value = data.items || []
  } catch (e) {
    ElMessage.error('加载历史记录失败: ' + e.message)
  } finally {
    historyLoading.value = false
  }
}

async function loadHistoryDetail(row) {
  historyLoading.value = true
  try {
    const resp = await fetch(`${API}/history/diagnoses/${row.id}`)
    if (!resp.ok) throw new Error(`HTTP ${resp.status}`)
    historyDetail.value = await resp.json()
  } catch (e) {
    ElMessage.error('加载历史详情失败: ' + e.message)
  } finally {
    historyLoading.value = false
  }
}

function historyStatusType(status) {
  return status === 'healthy' ? 'success' : status === 'warning' ? 'warning' : status === 'critical' ? 'danger' : 'info'
}

function historyStatusText(status) {
  return { healthy: '健康', warning: '警告', critical: '严重' }[status] || status
}

function runKindText(kind) {
  return { analysis: 'AI 分析', agent: 'Agent 自主诊断', chat: 'AI 对话' }[kind] || kind
}

function runStatusText(status) {
  return { running: '运行中', completed: '已完成', waiting: '等待处理', failed: '失败', rejected: '已拒绝' }[status] || status
}

function formatHistoryEvent(event) {
  const { type, created_at, ...payload } = event
  return JSON.stringify(payload, null, 2)
}

async function runAgentDiagnosis() {
  activeAgentMode.value = agentExecutionMode.value
  agentRunning.value = true
  agentEvents.value = []
  try {
    const params = new URLSearchParams()
    params.set('execution_mode', activeAgentMode.value)
    if (namespace.value) params.set('question', `重点检查命名空间 ${namespace.value}`)
    const resp = await fetch(`${API}/agent/diagnose/stream?${params.toString()}`)
    if (!resp.ok || !resp.body) throw new Error(`HTTP ${resp.status}`)
    const reader = resp.body.getReader()
    const decoder = new TextDecoder()
    let buffer = ''

    while (true) {
      const { done, value } = await reader.read()
      if (done) break
      buffer += decoder.decode(value, { stream: true })
      const lines = buffer.split('\n')
      buffer = lines.pop() || ''
      for (const line of lines) {
        if (!line.startsWith('data: ')) continue
        try {
          const event = JSON.parse(line.slice(6))
          if (!['start', 'done'].includes(event.type)) agentEvents.value.push(event)
          if (event.type === 'error') ElMessage.error(event.message)
        } catch (e) {
          // ignore partial events
        }
      }
    }
  } catch (e) {
    ElMessage.error('自主诊断失败: ' + e.message)
  } finally {
    agentRunning.value = false
  }
}

function agentEventTitle(event) {
  const titles = {
    thinking: 'Agent 思考', command: '准备执行命令', result: '命令执行结果',
    manual_command: '请手动执行命令',
    approval_required: '发现修改命令，等待审批', command_rejected: '命令已被安全策略拒绝',
    verification_required: '需要继续复检', response_rejected: 'AI 响应格式已自动纠正',
    final: '自主诊断结论', error: 'Agent 执行异常',
  }
  return titles[event.type] || event.type
}

async function copyAgentCommand(command) {
  try {
    await navigator.clipboard.writeText(command)
    ElMessage.success('命令已复制，请在终端中手动执行')
  } catch (e) {
    ElMessage.error('复制失败，请手动选择命令文本')
  }
}

async function resolveApproval(event, approved) {
  event.executing = true
  try {
    const resp = await fetch(`${API}/agent/approve`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ approval_id: event.approval_id, approved }),
    })
    if (!resp.ok) {
      const error = await resp.json()
      throw new Error(error.detail || `HTTP ${resp.status}`)
    }

    if (!approved) {
      const result = await resp.json()
      event.resolved = true
      event.approvalSuccess = false
      event.approvalResult = '已拒绝执行该命令'
      ElMessage.info(event.approvalResult)
      return
    }

    if (!resp.body) throw new Error('审批接口未返回流式响应')
    event.resolved = true
    agentRunning.value = true
    const reader = resp.body.getReader()
    const decoder = new TextDecoder()
    let buffer = ''
    while (true) {
      const { done, value } = await reader.read()
      if (done) break
      buffer += decoder.decode(value, { stream: true })
      const lines = buffer.split('\n')
      buffer = lines.pop() || ''
      for (const line of lines) {
        if (!line.startsWith('data: ')) continue
        const nextEvent = JSON.parse(line.slice(6))
        if (nextEvent.type === 'approved_result') {
          event.approvalSuccess = nextEvent.returncode === 0
          event.approvalResult = nextEvent.returncode === 0 ? '命令执行成功，Agent 继续诊断中' : `命令执行失败：${nextEvent.stderr || nextEvent.returncode}`
          agentEvents.value.push({ type: 'result', ...nextEvent })
        } else if (!['start', 'done'].includes(nextEvent.type)) {
          agentEvents.value.push(nextEvent)
          if (nextEvent.type === 'error') ElMessage.error(nextEvent.message)
        }
      }
    }
    ElMessage.success('审批命令已执行，Agent 已继续诊断')
  } catch (e) {
    ElMessage.error('审批处理失败: ' + e.message)
  } finally {
    event.executing = false
    agentRunning.value = false
  }
}

async function sendChat() {
  const q = chatInput.value.trim()
  if (!q || chatLoading.value) return
  chatMessages.value.push({ role: 'user', content: q })
  chatInput.value = ''
  chatLoading.value = true
  await nextTick()
  scrollChat()

  // 添加一个空的 assistant 消息用于流式填充
  const assistantIdx = chatMessages.value.length
  chatMessages.value.push({ role: 'assistant', content: '' })

  try {
    const resp = await fetch(`${API}/chat/stream`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        messages: chatMessages.value.slice(0, -1).map(m => ({ role: m.role, content: m.content })),
      }),
    })
    const reader = resp.body.getReader()
    const decoder = new TextDecoder()
    let buffer = ''

    while (true) {
      const { done, value } = await reader.read()
      if (done) break

      buffer += decoder.decode(value, { stream: true })
      const lines = buffer.split('\n')
      buffer = lines.pop() || ''

      for (const line of lines) {
        if (!line.startsWith('data: ')) continue
        const jsonStr = line.slice(6)
        if (!jsonStr) continue
        try {
          const msg = JSON.parse(jsonStr)
          if (msg.type === 'chunk') {
            chatMessages.value[assistantIdx].content += msg.content
            await nextTick()
            scrollChat()
          } else if (msg.type === 'error') {
            chatMessages.value[assistantIdx].content = msg.message
          }
        } catch (e) {
          // ignore
        }
      }
    }
  } catch (e) {
    chatMessages.value[assistantIdx].content = '请求失败: ' + e.message
  } finally {
    chatLoading.value = false
    await nextTick()
    scrollChat()
  }
}

function scrollChat() {
  if (chatBoxRef.value) chatBoxRef.value.scrollTop = chatBoxRef.value.scrollHeight
}
</script>

<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; background: #f0f2f5; }

.app-container { min-height: 100vh; display: flex; flex-direction: column; }

.app-header {
  display: flex; align-items: center; justify-content: space-between;
  background: #fff; padding: 0 24px; height: 64px;
  box-shadow: 0 1px 4px rgba(0,0,0,.08); position: sticky; top: 0; z-index: 100;
}
.header-left { display: flex; align-items: center; gap: 12px; }
.header-left h1 { font-size: 20px; font-weight: 600; color: #303133; }
.header-right { display: flex; align-items: center; gap: 12px; }

.app-main { flex: 1; padding: 20px 24px; max-width: 1400px; margin: 0 auto; width: 100%; }

.welcome { display: flex; justify-content: center; align-items: center; min-height: 400px; }

/* 诊断进度 */
.progress-box { display: flex; justify-content: center; padding-top: 40px; }
.progress-card { width: 600px; }

/* 连接失败 */
.conn-error-box { display: flex; justify-content: center; padding-top: 40px; }
.conn-error-card { width: 700px; text-align: center; padding: 20px 0; }
.conn-error-icon { margin-bottom: 16px; }
.conn-error-card h2 { font-size: 22px; color: #303133; margin-bottom: 20px; }
.conn-error-detail { text-align: left; margin: 0 20px; }
.conn-error-pre { white-space: pre-wrap; word-break: break-all; font-size: 13px; margin: 8px 0 0; color: #f56c6c; }
.conn-error-actions { margin-top: 24px; }
.progress-steps { display: flex; flex-direction: column; gap: 4px; }
.progress-item {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: 6px; transition: background .2s;
}
.progress-item.status-running { background: #ecf5ff; }
.progress-item.status-done { background: #f0f9eb; }
.step-icon { display: flex; align-items: center; width: 20px; }
.step-title { flex: 1; font-size: 14px; color: #303133; }
.step-result { font-size: 12px; }
.step-running { font-size: 12px; color: #409eff; }

.summary-row { margin-bottom: 16px; }
.score-card { text-align: center; }
.score-number { font-size: 42px; font-weight: 700; line-height: 1.2; }
.score-label { font-size: 13px; color: #909399; margin-top: 4px; }
.score-healthy .score-number { color: #67c23a; }
.score-warning .score-number { color: #e6a23c; }
.score-critical .score-number { color: #f56c6c; }

.section-card { margin-bottom: 16px; }
.card-header { display: flex; align-items: center; justify-content: space-between; }

.pod-stats { display: flex; gap: 12px; flex-wrap: wrap; }

.resource-bar { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
.res-name { width: 140px; font-size: 13px; color: #606266; text-align: right; flex-shrink: 0; }

.ai-card { border: 1px solid #d9ecff; }
.ai-header-meta { display: flex; align-items: center; gap: 8px; }
.analysis-process { padding: 4px 0; }
.process-heading { display: flex; justify-content: space-between; margin-bottom: 10px; color: #606266; font-size: 13px; font-weight: 600; }
.analysis-step-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-top: 14px; }
.analysis-step {
  display: flex; align-items: center; gap: 10px; min-height: 64px;
  padding: 11px 12px; border: 1px solid #ebeef5; border-radius: 8px; background: #fafafa;
}
.analysis-step.status-running { border-color: #a0cfff; background: #ecf5ff; }
.analysis-step.status-done { border-color: #b3e19d; background: #f0f9eb; }
.analysis-step-icon { display: flex; align-items: center; flex-shrink: 0; }
.analysis-step-body { display: flex; flex: 1; min-width: 0; flex-direction: column; gap: 4px; }
.analysis-step-body strong { color: #303133; font-size: 14px; }
.analysis-step-body span { color: #909399; font-size: 12px; line-height: 1.4; }
.ai-loading { display: flex; align-items: center; gap: 8px; color: #409eff; padding: 6px 0 12px; }
.ai-content { line-height: 1.8; font-size: 14px; }
.ai-content h1, .ai-content h2, .ai-content h3 { margin: 16px 0 8px; }
.ai-content code { background: #f5f7fa; padding: 2px 6px; border-radius: 4px; font-size: 13px; }
.ai-content pre { background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow-x: auto; margin: 12px 0; }
.ai-content pre code { background: none; color: inherit; }
.ai-content ul, .ai-content ol { padding-left: 24px; }
.ai-content table { border-collapse: collapse; width: 100%; margin: 12px 0; }
.ai-content th, .ai-content td { border: 1px solid #ebeef5; padding: 8px 12px; text-align: left; }

.agent-card { border: 1px solid #f3d19e; }
.agent-mode-switch { flex-shrink: 0; }
.agent-alert { margin-bottom: 16px; }
.agent-timeline { display: flex; flex-direction: column; gap: 12px; }
.agent-event { padding: 14px; border: 1px solid #ebeef5; border-radius: 8px; background: #fafafa; }
.agent-event.event-thinking { border-color: #a0cfff; background: #ecf5ff; }
.agent-event.event-approval_required { border-color: #eebe77; background: #fdf6ec; }
.agent-event.event-final { border-color: #b3e19d; background: #f0f9eb; }
.agent-event-title { display: flex; align-items: center; gap: 8px; color: #303133; }
.agent-event-message { margin-top: 8px; color: #606266; font-size: 13px; }
.agent-command, .agent-output {
  margin-top: 10px; padding: 12px; border-radius: 6px; overflow-x: auto;
  white-space: pre-wrap; word-break: break-all; font-size: 13px;
}
.agent-command { color: #d4d4d4; background: #1e1e1e; }
.agent-output { max-height: 320px; color: #303133; background: #f4f4f5; }
.approval-actions { display: flex; gap: 8px; margin-top: 12px; }
.manual-actions { display: flex; align-items: center; gap: 12px; margin-top: 12px; color: #606266; font-size: 13px; }
.agent-running { display: flex; align-items: center; gap: 8px; color: #409eff; padding: 8px; }

.history-toolbar { display: flex; gap: 10px; margin-bottom: 16px; }
.history-detail { margin-top: 20px; }
.history-collapse { margin-top: 16px; }
.history-report { max-height: 480px; padding: 14px; overflow: auto; border-radius: 6px; background: #f4f4f5; white-space: pre-wrap; }
.history-event { margin-top: 10px; padding: 12px; border: 1px solid #ebeef5; border-radius: 6px; }
.history-event-head { display: flex; align-items: center; gap: 10px; color: #909399; font-size: 12px; }
.history-event pre { max-height: 300px; margin-top: 8px; padding: 10px; overflow: auto; background: #f4f4f5; white-space: pre-wrap; }

.chat-box { max-height: 400px; overflow-y: auto; padding: 12px 0; display: flex; flex-direction: column; gap: 12px; }
.chat-msg { display: flex; }
.chat-msg.user { justify-content: flex-end; }
.chat-msg.assistant { justify-content: flex-start; }
.chat-bubble {
  max-width: 80%; padding: 10px 16px; border-radius: 12px; font-size: 14px; line-height: 1.6;
}
.chat-msg.user .chat-bubble { background: #409eff; color: #fff; border-bottom-right-radius: 4px; }
.chat-msg.assistant .chat-bubble { background: #f4f4f5; color: #303133; border-bottom-left-radius: 4px; }
.chat-bubble pre { background: #1e1e1e; color: #d4d4d4; padding: 12px; border-radius: 6px; overflow-x: auto; margin: 8px 0; }
.chat-bubble code { background: rgba(0,0,0,.06); padding: 1px 4px; border-radius: 3px; font-size: 13px; }
.chat-bubble pre code { background: none; }
.chat-input { display: flex; gap: 8px; margin-top: 12px; }

@media (max-width: 900px) {
  .app-header { height: auto; padding: 12px 16px; align-items: flex-start; gap: 12px; }
  .header-left, .header-right { flex-wrap: wrap; }
  .analysis-step-list { grid-template-columns: 1fr; }
}
</style>
