<!--
  组件名称：ReportPanel.vue
  组件描述：性能测试报告查看面板 - 摘要信息 / 指标统计 / 快照趋势图

  @author czj
  @date 2026-08-12
-->

<template>
  <div class="report-panel">
    <!-- 无任务时提示 → 提供任务选择器 + 执行历史 -->
    <div v-if="!taskId && !executionId" class="empty-state">
      <el-icon :size="48"><Document /></el-icon>
      <p style="margin-bottom: 16px;">请选择要查看报告的任务</p>
      <el-select
        v-model="selectedTaskId"
        placeholder="选择任务"
        filterable
        clearable
        style="width: 360px"
        @change="onTaskSelected"
      >
        <el-option
          v-for="t in availableTasks"
          :key="t.id"
          :label="`${t.name} (${t.id.slice(0, 8)}...)`"
          :value="t.id"
        />
      </el-select>
      <el-button
        v-if="selectedTaskId"
        type="primary"
        style="margin-left: 12px;"
        @click="onTaskSelected(selectedTaskId)"
      >查看报告</el-button>
      <p v-if="tasksLoading" style="margin-top: 12px; color: #909399; font-size: 13px;">
        加载中...
      </p>

      <!-- 最近执行记录 -->
      <div style="width: 100%; max-width: 960px; margin-top: 32px;">
        <h4 style="margin-bottom: 12px; color: #303133;">最近执行记录</h4>
        <el-table
          :data="recentExecutions"
          v-loading="loadingExecutions"
          size="small"
          stripe
          border
          empty-text="暂无执行记录"
          style="width: 100%"
        >
          <el-table-column prop="taskName" label="任务名" min-width="140" show-overflow-tooltip />
          <el-table-column prop="status" label="状态" width="100">
            <template #default="{ row }">
              <el-tag :type="statusTagType(row.status)" size="small">{{ statusLabel(row.status) }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="开始时间" width="170">
            <template #default="{ row }">{{ formatTime(row.startTime) }}</template>
          </el-table-column>
          <el-table-column label="时长" width="80">
            <template #default="{ row }">{{ row.durationActual ? `${row.durationActual.toFixed(0)}s` : '-' }}</template>
          </el-table-column>
          <el-table-column label="TPS" width="80">
            <template #default="{ row }">{{ row.actualTps != null ? row.actualTps.toFixed(1) : '-' }}</template>
          </el-table-column>
          <el-table-column label="查看报告" width="120" fixed="right">
            <template #default="{ row }">
              <el-button
                link type="primary" size="small"
                @click="router.push({ path: '/performance/report', query: { taskId: row.taskId, executionId: row.id } })"
              >查看报告</el-button>
            </template>
          </el-table-column>
        </el-table>
        <el-pagination
          v-if="executionTotal > 20"
          small
          layout="prev, pager, next"
          :total="executionTotal"
          :page-size="20"
          :current-page="executionPage"
          @current-change="loadExecutions"
          style="margin-top: 12px; justify-content: center;"
        />
      </div>
    </div>

    <template v-else>
      <div class="report-header">
        <div class="report-header-left">
          <el-select
            v-if="executionOptions.length > 1"
            v-model="selectedExecutionId"
            placeholder="切换执行记录"
            size="small"
            style="width: 400px;"
            @change="switchExecution"
          >
            <el-option
              v-for="opt in executionOptions"
              :key="opt.id"
              :label="opt.label"
              :value="opt.id"
            />
          </el-select>
        </div>
        <div class="report-header-right">
          <el-button type="primary" :loading="loading" @click="loadReport">
            <el-icon><Refresh /></el-icon>刷新报告
          </el-button>
          <el-button v-if="report" @click="exportReport">
            <el-icon><Download /></el-icon>导出 JSON
          </el-button>
          <el-button v-if="report" type="warning" :loading="aiLoading" @click="triggerAiAnalysis">
            <el-icon><MagicStick /></el-icon>AI 分析
          </el-button>
        </div>
      </div>

      <!-- 加载中 -->
      <el-skeleton v-if="loading" :rows="8" animated />

      <template v-else-if="report">
        <!-- 摘要信息 -->
        <el-descriptions title="执行摘要 Summary" :column="3" border class="summary-block">
          <el-descriptions-item label="任务名称 Task Name">{{ report.summary.taskName }}</el-descriptions-item>
          <el-descriptions-item label="目标 URL Target">{{ report.summary.targetUrl }}</el-descriptions-item>
          <el-descriptions-item label="HTTP 方法 Method">{{ report.summary.method }}</el-descriptions-item>
          <el-descriptions-item label="压测模式 Mode">{{ modeLabel(report.summary.mode) }}</el-descriptions-item>
          <el-descriptions-item label="场景类型 Scenario">
            <el-tag v-if="report.summary.scenarioType === 'burst'" type="warning" size="small">瞬时并发 Burst</el-tag>
            <el-tag v-else-if="report.summary.scenarioType === 'endurance'" type="danger" size="small">长稳压测 Endurance</el-tag>
            <span v-else style="color: #909399;">标准 Standard</span>
          </el-descriptions-item>
          <el-descriptions-item label="并发数 Concurrency">{{ report.summary.concurrency }}</el-descriptions-item>
          <el-descriptions-item label="账号 Account">{{ report.summary.accountKey || '-' }}</el-descriptions-item>
          <el-descriptions-item label="开始时间 Start">{{ formatTime(report.summary.startTime) }}</el-descriptions-item>
          <el-descriptions-item label="结束时间 End">{{ formatTime(report.summary.endTime) }}</el-descriptions-item>
          <el-descriptions-item label="实际时长 Duration">{{ report.summary.durationActual != null ? report.summary.durationActual.toFixed(1) + 's' : '-' }}</el-descriptions-item>
        </el-descriptions>

        <!-- 事务标记（仅事务任务） -->
        <el-tag v-if="report.transactionSummary" type="warning" size="large" style="margin-bottom: 12px;">
          <el-icon style="margin-right: 4px; vertical-align: middle;"><List /></el-icon>
          多步骤事务 Transaction Task — {{ report.transactionSummary.totalTransactions }} 次事务,
          成功 {{ report.transactionSummary.successCount }},
          失败 {{ report.transactionSummary.failCount }}
        </el-tag>

        <!-- 核心指标卡片（第一行：请求统计） -->
        <el-row :gutter="12" class="metrics-row">
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value">{{ report.metrics.totalRequests }}</div>
              <div class="metric-label">Total Requests（总请求数）</div>
            </el-card>
          </el-col>
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value">{{ report.metrics.successCount }}</div>
              <div class="metric-label">Success Count（成功数）</div>
            </el-card>
          </el-col>
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value">{{ report.metrics.failCount }}</div>
              <div class="metric-label">Fail Count（失败数）</div>
            </el-card>
          </el-col>
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value" :style="{ color: report.metrics.errorRate > 5 ? '#f56c6c' : '#67c23a' }">
                {{ (report.metrics.errorRate * 100).toFixed(2) }}%
              </div>
              <div class="metric-label">Error Rate（错误率）</div>
            </el-card>
          </el-col>
        </el-row>

        <!-- 第二行：吞吐 + 响应时间 -->
        <el-row :gutter="12" class="metrics-row">
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value">{{ report.metrics.actualTps.toFixed(1) }}</div>
              <div class="metric-label">Actual TPS（实际吞吐量）</div>
            </el-card>
          </el-col>
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value">{{ report.metrics.peakTps.toFixed(1) }}</div>
              <div class="metric-label">Peak TPS（峰值吞吐量）</div>
            </el-card>
          </el-col>
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value">{{ report.metrics.avgResponseTime.toFixed(1) }}ms</div>
              <div class="metric-label">Avg Response Time（平均响应时间）</div>
            </el-card>
          </el-col>
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value" :style="{ color: rtPerfColor(report.metrics.p95ResponseTime) }">
                {{ report.metrics.p95ResponseTime.toFixed(1) }}ms
              </div>
              <div class="metric-label">P95 Response Time（P95 响应时间）</div>
            </el-card>
          </el-col>
        </el-row>

        <!-- 第三行：稳定性 + 网络分解 -->
        <el-row :gutter="12" class="metrics-row">
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value">{{ report.metrics.stdDev.toFixed(1) }}ms</div>
              <div class="metric-label">Std Dev（响应时间标准差）</div>
            </el-card>
          </el-col>
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value" :style="{ color: apdexColor(report.metrics.apdex) }">
                {{ report.metrics.apdex.toFixed(2) }}
              </div>
              <div class="metric-label">Apdex（用户满意度）</div>
            </el-card>
          </el-col>
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value">{{ report.metrics.latencyAvg.toFixed(1) }}ms</div>
              <div class="metric-label">Latency Avg（平均首字节延迟）</div>
            </el-card>
          </el-col>
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value">{{ report.metrics.connectTimeAvg.toFixed(1) }}ms</div>
              <div class="metric-label">Connect Time Avg（平均连接时间）</div>
            </el-card>
          </el-col>
        </el-row>

        <!-- 第四行：带宽 + 极值 -->
        <el-row :gutter="12" class="metrics-row">
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value">{{ report.metrics.sentKbPerSec.toFixed(1) }}</div>
              <div class="metric-label">Sent KB/s（发送速率）</div>
            </el-card>
          </el-col>
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value">{{ report.metrics.receivedKbPerSec.toFixed(1) }}</div>
              <div class="metric-label">Received KB/s（接收速率）</div>
            </el-card>
          </el-col>
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value">{{ report.metrics.minResponseTime.toFixed(1) }}ms</div>
              <div class="metric-label">Min Response Time（最小响应时间）</div>
            </el-card>
          </el-col>
          <el-col :span="6">
            <el-card shadow="never" class="metric-card">
              <div class="metric-value">{{ report.metrics.maxResponseTime.toFixed(1) }}ms</div>
              <div class="metric-label">Max Response Time（最大响应时间）</div>
            </el-card>
          </el-col>
        </el-row>

        <!-- 响应时间分位数 -->
        <el-row :gutter="12">
          <el-col :span="12">
            <el-card shadow="never" class="chart-card">
              <template #header><span>响应时间分位数 Percentile Table</span></template>
              <el-table :data="quantileRows" size="small">
                <el-table-column prop="label" label="Percentile（分位数）" width="120" />
                <el-table-column prop="value" label="Value（值）" />
              </el-table>
            </el-card>
          </el-col>
          <el-col :span="12">
            <el-card shadow="never" class="chart-card">
              <template #header><span>错误分类统计 Error Types</span></template>
              <el-table :data="errorTypeRows" size="small" v-if="hasErrorTypes">
                <el-table-column prop="label" label="错误类型" />
                <el-table-column prop="count" label="数量" width="80" />
                <el-table-column prop="percent" label="占比" width="100" />
              </el-table>
              <el-empty v-else description="无错误分类数据" :image-size="60" />
            </el-card>
          </el-col>
        </el-row>

        <!-- 状态码分布表 -->
        <el-card shadow="never" class="chart-card">
          <template #header><span>状态码分布 Status Code Distribution</span></template>
          <el-table :data="statusRows" size="small">
            <el-table-column prop="code" label="状态码" width="120" />
            <el-table-column prop="count" label="数量" />
            <el-table-column prop="percent" label="占比" />
          </el-table>
        </el-card>

        <!-- 接口级统计明细（endurance 多接口场景） -->
        <template v-if="report.apiSummary && report.apiSummary.length">
          <el-card shadow="never" class="chart-card">
            <template #header>
              <span>接口级统计明细 API Summary（长稳压测多接口）</span>
              <el-tag type="danger" size="small" style="margin-left: 8px; vertical-align: middle;">Endurance</el-tag>
            </template>
            <el-table :data="report.apiSummary" size="small" stripe border>
              <el-table-column prop="name" label="接口名称 API" min-width="140" show-overflow-tooltip />
              <el-table-column label="总请求数 Total" width="110">
                <template #default="{ row }">{{ row.totalRequests }}</template>
              </el-table-column>
              <el-table-column label="成功 Success" width="100">
                <template #default="{ row }">
                  <span style="color: #67c23a;">{{ row.successCount }}</span>
                </template>
              </el-table-column>
              <el-table-column label="失败 Fail" width="90">
                <template #default="{ row }">
                  <span :style="{ color: row.failCount > 0 ? '#f56c6c' : '#909399' }">{{ row.failCount }}</span>
                </template>
              </el-table-column>
              <el-table-column label="错误率 Error Rate" width="110">
                <template #default="{ row }">
                  <span :style="{ color: row.errorRate > 5 ? '#f56c6c' : '#67c23a' }">
                    {{ (row.errorRate * 100).toFixed(1) }}%
                  </span>
                </template>
              </el-table-column>
              <el-table-column label="TPS（吞吐量）" width="100">
                <template #default="{ row }">{{ row.actualTps.toFixed(1) }}</template>
              </el-table-column>
              <el-table-column label="平均 Avg ms" width="110">
                <template #default="{ row }">{{ row.avgResponseTime.toFixed(1) }}</template>
              </el-table-column>
              <el-table-column label="最小 Min ms" width="100">
                <template #default="{ row }">{{ row.minResponseTime.toFixed(1) }}</template>
              </el-table-column>
              <el-table-column label="最大 Max ms" width="100">
                <template #default="{ row }">{{ row.maxResponseTime.toFixed(1) }}</template>
              </el-table-column>
              <el-table-column label="P50 ms" width="90">
                <template #default="{ row }">{{ row.p50ResponseTime.toFixed(1) }}</template>
              </el-table-column>
              <el-table-column label="P95 ms" width="90">
                <template #default="{ row }">{{ row.p95ResponseTime.toFixed(1) }}</template>
              </el-table-column>
              <el-table-column label="P99 ms" width="90">
                <template #default="{ row }">{{ row.p99ResponseTime.toFixed(1) }}</template>
              </el-table-column>
              <el-table-column label="标准差 Std Dev" width="110">
                <template #default="{ row }">{{ row.stdDev.toFixed(1) }}</template>
              </el-table-column>
            </el-table>
          </el-card>
        </template>

        <!-- 网络延迟分解卡（发送/接收总字节） -->
        <el-card shadow="never" class="chart-card">
          <template #header><span>网络传输统计 Network Traffic</span></template>
          <el-descriptions :column="4" border size="small">
            <el-descriptions-item label="总发送字节 Total Sent">{{ formatBytes(report.metrics.totalSentBytes) }}</el-descriptions-item>
            <el-descriptions-item label="总接收字节 Total Received">{{ formatBytes(report.metrics.totalReceivedBytes) }}</el-descriptions-item>
            <el-descriptions-item label="平均发送速率 Avg Sent">{{ report.metrics.sentKbPerSec.toFixed(1) }} KB/s</el-descriptions-item>
            <el-descriptions-item label="平均接收速率 Avg Received">{{ report.metrics.receivedKbPerSec.toFixed(1) }} KB/s</el-descriptions-item>
          </el-descriptions>
        </el-card>

        <!-- AI 分析卡片 -->
        <el-card v-if="aiResult" shadow="never" class="chart-card ai-card" style="margin-top: 12px;">
          <template #header>
            <div class="ai-card-header">
              <span>
                <el-icon style="vertical-align: middle; margin-right: 4px;"><MagicStick /></el-icon>
                AI 性能分析
                <el-tag v-if="aiResult.source === 'rule'" size="small" type="warning" style="margin-left: 8px;">规则分析</el-tag>
                <el-tag v-else size="small" type="success" style="margin-left: 8px;">AI 分析</el-tag>
              </span>
              <el-button size="small" :loading="aiLoading" @click="triggerAiAnalysis">重新分析</el-button>
            </div>
          </template>

          <el-skeleton :rows="6" animated v-if="aiLoading" />

          <template v-else>
            <!-- 总体评价 -->
            <div class="ai-section">
              <h4 class="ai-section-title">📊 总体评价</h4>
              <div class="ai-markdown" v-html="renderMarkdown(aiResult.overallVerdict)" />
            </div>

            <!-- 关键发现 -->
            <div v-if="aiResult.keyFindings.length" class="ai-section">
              <h4 class="ai-section-title">🔑 关键发现</h4>
              <el-table :data="aiResult.keyFindings" size="small" stripe>
                <el-table-column prop="type" label="类型" width="120" />
                <el-table-column prop="description" label="描述" min-width="200" />
                <el-table-column prop="severity" label="严重度" width="100">
                  <template #default="{ row }">
                    <el-tag v-if="row.severity === 'high'" type="danger" size="small">高</el-tag>
                    <el-tag v-else-if="row.severity === 'medium'" type="warning" size="small">中</el-tag>
                    <el-tag v-else size="info">低</el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="evidence" label="数据支撑" min-width="160" show-overflow-tooltip />
              </el-table>
            </div>

            <!-- 瓶颈分析 -->
            <div v-if="aiResult.bottlenecks.length" class="ai-section">
              <h4 class="ai-section-title">🎯 瓶颈分析</h4>
              <el-table :data="aiResult.bottlenecks" size="small" stripe>
                <el-table-column prop="type" label="瓶颈类型" width="120" />
                <el-table-column prop="location" label="位置" width="140" />
                <el-table-column prop="severity" label="严重度" width="80">
                  <template #default="{ row }">
                    <el-tag v-if="row.severity === 'high'" type="danger" size="small">高</el-tag>
                    <el-tag v-else-if="row.severity === 'medium'" type="warning" size="small">中</el-tag>
                    <el-tag v-else size="info">低</el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="description" label="描述" min-width="200" />
                <el-table-column prop="evidence" label="数据支撑" min-width="160" show-overflow-tooltip />
              </el-table>
            </div>

            <!-- 优化建议 -->
            <div v-if="aiResult.suggestions.length" class="ai-section">
              <h4 class="ai-section-title">💡 优化建议</h4>
              <el-table :data="aiResult.suggestions" size="small" stripe>
                <el-table-column label="优先级" width="80">
                  <template #default="{ row }">
                    <el-tag v-if="row.priority === 'P0'" type="danger" size="small">P0</el-tag>
                    <el-tag v-else-if="row.priority === 'P1'" type="warning" size="small">P1</el-tag>
                    <el-tag v-else size="info">P2</el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="content" label="建议内容" min-width="250" show-overflow-tooltip />
                <el-table-column prop="expectedEffect" label="预期效果" min-width="200" show-overflow-tooltip />
              </el-table>
            </div>

            <!-- 资源分析 -->
            <div v-if="aiResult.resourceAnalysis" class="ai-section">
              <h4 class="ai-section-title">🖥 资源分析</h4>
              <div class="ai-markdown" v-html="renderMarkdown(aiResult.resourceAnalysis)" />
            </div>

            <!-- 对比分析 -->
            <div v-if="aiResult.comparison && aiResult.comparison.length" class="ai-section">
              <h4 class="ai-section-title">📈 版本对比分析</h4>
              <el-table :data="aiResult.comparison" size="small" stripe>
                <el-table-column prop="metric" label="指标" width="140" />
                <el-table-column prop="baseValue" label="基准值" width="120" />
                <el-table-column prop="currentValue" label="当前值" width="120" />
                <el-table-column prop="changePercent" label="变化率" width="100">
                  <template #default="{ row }">
                    <span :style="{ color: row.direction === 'regressed' ? '#f56c6c' : row.direction === 'improved' ? '#67c23a' : '#909399' }">
                      {{ row.changePercent }}
                    </span>
                  </template>
                </el-table-column>
                <el-table-column label="评估" width="100">
                  <template #default="{ row }">
                    <el-tag v-if="row.direction === 'improved'" type="success" size="small">改善</el-tag>
                    <el-tag v-else-if="row.direction === 'regressed'" type="danger" size="small">退化</el-tag>
                    <el-tag v-else size="info">稳定</el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="assessment" label="说明" min-width="200" show-overflow-tooltip />
              </el-table>
            </div>
          </template>
        </el-card>

        <!-- 快照趋势图 -->
        <el-row :gutter="12">
          <el-col :span="12">
            <el-card shadow="never" class="chart-card">
              <template #header><span>TPS 趋势（吞吐量趋势）</span></template>
              <div ref="tpsChartRef" class="chart" />
            </el-card>
          </el-col>
          <el-col :span="12">
            <el-card shadow="never" class="chart-card">
              <template #header><span>响应时间趋势 Response Time（含 P95）</span></template>
              <div ref="rtChartRef" class="chart" />
            </el-card>
          </el-col>
        </el-row>

        <!-- 延迟分解趋势图（首字节延迟 + 连接时间） -->
        <el-row :gutter="12">
          <el-col :span="12">
            <el-card shadow="never" class="chart-card">
              <template #header><span>延迟分解趋势 Latency / Connect Time</span></template>
              <div ref="latencyChartRef" class="chart" />
            </el-card>
          </el-col>
          <el-col :span="12">
            <el-card shadow="never" class="chart-card">
              <template #header><span>带宽趋势 Bandwidth（发送 / 接收）</span></template>
              <div ref="bandwidthChartRef" class="chart" />
            </el-card>
          </el-col>
        </el-row>

        <!-- 执行机资源汇总（仅当有数据时显示） -->
        <template v-if="report.resourceSummary">
          <el-divider content-position="left">执行机资源汇总 Resource Summary</el-divider>

          <el-row :gutter="12" class="metrics-row">
            <el-col :span="4">
              <el-card shadow="never" class="metric-card">
                <div class="metric-value" :style="{ color: report.resourceSummary.stats.avgCpuPercent > 85 ? '#f56c6c' : '#409eff' }">
                  {{ report.resourceSummary.stats.avgCpuPercent.toFixed(1) }}%
                </div>
                <div class="metric-label">CPU Avg（平均 CPU 使用率）</div>
              </el-card>
            </el-col>
            <el-col :span="4">
              <el-card shadow="never" class="metric-card">
                <div class="metric-value" :style="{ color: report.resourceSummary.stats.maxCpuPercent > 85 ? '#f56c6c' : '#409eff' }">
                  {{ report.resourceSummary.stats.maxCpuPercent.toFixed(1) }}%
                </div>
                <div class="metric-label">CPU Max（最大 CPU 使用率）</div>
              </el-card>
            </el-col>
            <el-col :span="4">
              <el-card shadow="never" class="metric-card">
                <div class="metric-value" :style="{ color: report.resourceSummary.stats.avgMemPercent > 85 ? '#f56c6c' : '#409eff' }">
                  {{ report.resourceSummary.stats.avgMemPercent.toFixed(1) }}%
                </div>
                <div class="metric-label">Memory Avg（平均内存使用率）</div>
              </el-card>
            </el-col>
            <el-col :span="4">
              <el-card shadow="never" class="metric-card">
                <div class="metric-value" :style="{ color: report.resourceSummary.stats.maxMemPercent > 85 ? '#f56c6c' : '#409eff' }">
                  {{ report.resourceSummary.stats.maxMemPercent.toFixed(1) }}%
                </div>
                <div class="metric-label">Memory Max（最大内存使用率）</div>
              </el-card>
            </el-col>
            <el-col :span="4">
              <el-card shadow="never" class="metric-card">
                <div class="metric-value">{{ report.resourceSummary.stats.avgSentKbS.toFixed(1) }}</div>
                <div class="metric-label">Sent Avg（平均发送 KB/s）</div>
              </el-card>
            </el-col>
            <el-col :span="4">
              <el-card shadow="never" class="metric-card">
                <div class="metric-value">{{ report.resourceSummary.stats.avgRecvKbS.toFixed(1) }}</div>
                <div class="metric-label">Recv Avg（平均接收 KB/s）</div>
              </el-card>
            </el-col>
          </el-row>

          <el-card shadow="never" class="chart-card">
            <template #header><span>CPU &amp; 内存趋势 CPU / Memory</span></template>
            <div ref="resourceChartRef" class="chart" />
          </el-card>
          <el-card shadow="never" class="chart-card">
            <template #header><span>网络趋势 Network（发送 / 接收 KB/s）</span></template>
            <div ref="networkChartRef" class="chart" />
          </el-card>
        </template>

        <!-- 目标机资源汇总（仅当有数据时显示） -->
        <template v-if="report.targetResourceSummary">
          <el-divider content-position="left">目标机资源汇总 Target Resource Summary</el-divider>

          <div class="target-host-info">
            <el-tag size="small" type="info" effect="plain">SSH {{ report.targetResourceSummary.host }}</el-tag>
            <span class="target-host-hint">目标机资源监控（SSH 连接 {{ report.targetResourceSummary.host }}）</span>
          </div>

          <el-row :gutter="12" class="metrics-row">
            <el-col :span="4">
              <el-card shadow="never" class="metric-card">
                <div class="metric-value" :style="{ color: report.targetResourceSummary.stats.avgCpuPercent > 85 ? '#f56c6c' : '#409eff' }">
                  {{ report.targetResourceSummary.stats.avgCpuPercent.toFixed(1) }}%
                </div>
                <div class="metric-label">CPU Avg（平均 CPU 使用率）</div>
              </el-card>
            </el-col>
            <el-col :span="4">
              <el-card shadow="never" class="metric-card">
                <div class="metric-value" :style="{ color: report.targetResourceSummary.stats.maxCpuPercent > 85 ? '#f56c6c' : '#409eff' }">
                  {{ report.targetResourceSummary.stats.maxCpuPercent.toFixed(1) }}%
                </div>
                <div class="metric-label">CPU Max（最大 CPU 使用率）</div>
              </el-card>
            </el-col>
            <el-col :span="4">
              <el-card shadow="never" class="metric-card">
                <div class="metric-value" :style="{ color: report.targetResourceSummary.stats.avgMemPercent > 85 ? '#f56c6c' : '#409eff' }">
                  {{ report.targetResourceSummary.stats.avgMemPercent.toFixed(1) }}%
                </div>
                <div class="metric-label">Memory Avg（平均内存使用率）</div>
              </el-card>
            </el-col>
            <el-col :span="4">
              <el-card shadow="never" class="metric-card">
                <div class="metric-value" :style="{ color: report.targetResourceSummary.stats.maxMemPercent > 85 ? '#f56c6c' : '#409eff' }">
                  {{ report.targetResourceSummary.stats.maxMemPercent.toFixed(1) }}%
                </div>
                <div class="metric-label">Memory Max（最大内存使用率）</div>
              </el-card>
            </el-col>
            <el-col :span="4">
              <el-card shadow="never" class="metric-card">
                <div class="metric-value">{{ report.targetResourceSummary.stats.avgLoadAvg1.toFixed(2) }}</div>
                <div class="metric-label">Load Avg 1m（平均负载）</div>
              </el-card>
            </el-col>
            <el-col :span="4">
              <el-card shadow="never" class="metric-card">
                <div class="metric-value">{{ report.targetResourceSummary.stats.maxLoadAvg1.toFixed(2) }}</div>
                <div class="metric-label">Load Max 1m（最大负载）</div>
              </el-card>
            </el-col>
          </el-row>

          <el-card shadow="never" class="chart-card">
            <template #header><span>目标机 CPU &amp; 内存趋势 CPU / Memory / Load</span></template>
            <div ref="targetResourceChartRef" class="chart" />
          </el-card>

          <!-- Java 服务进程占用汇总（仅匹配到进程时展示） -->
          <template v-if="report.targetResourceSummary.javaProcessStats && report.targetResourceSummary.javaProcessStats.length">
            <el-card shadow="never" class="chart-card">
              <template #header>
                <span>Java 服务进程占用汇总 Java Process Usage（仅匹配会议相关服务）</span>
              </template>
              <el-table :data="report.targetResourceSummary.javaProcessStats" size="small" stripe border>
                <el-table-column prop="processName" label="服务 Process" min-width="220" show-overflow-tooltip />
                <el-table-column label="CPU 平均 Avg" width="120">
                  <template #default="{ row }">
                    <span :style="{ color: row.avgCpuPercent > 80 ? '#f56c6c' : '#409eff', fontWeight: 600 }">
                      {{ row.avgCpuPercent.toFixed(1) }}%
                    </span>
                  </template>
                </el-table-column>
                <el-table-column label="CPU 最大 Max" width="120">
                  <template #default="{ row }">
                    <span :style="{ color: row.maxCpuPercent > 80 ? '#f56c6c' : '#409eff' }">
                      {{ row.maxCpuPercent.toFixed(1) }}%
                    </span>
                  </template>
                </el-table-column>
                <el-table-column label="内存平均 Avg" width="120">
                  <template #default="{ row }">
                    <span :style="{ color: row.avgMemPercent > 50 ? '#f56c6c' : '#409eff', fontWeight: 600 }">
                      {{ row.avgMemPercent.toFixed(1) }}%
                    </span>
                  </template>
                </el-table-column>
                <el-table-column label="内存最大 Max" width="120">
                  <template #default="{ row }">
                    <span :style="{ color: row.maxMemPercent > 50 ? '#f56c6c' : '#409eff' }">
                      {{ row.maxMemPercent.toFixed(1) }}%
                    </span>
                  </template>
                </el-table-column>
                <el-table-column label="RSS 平均 Avg（MB）" width="150">
                  <template #default="{ row }">{{ row.avgRssMb.toFixed(0) }} MB</template>
                </el-table-column>
                <el-table-column label="RSS 最大 Max（MB）" width="150">
                  <template #default="{ row }">{{ row.maxRssMb.toFixed(0) }} MB</template>
                </el-table-column>
              </el-table>
            </el-card>

            <!-- Java 进程 CPU 趋势图（仅当存在进程序列数据时展示） -->
            <el-card
              v-if="report.targetResourceSummary.javaProcessSeries && report.targetResourceSummary.javaProcessSeries.length"
              shadow="never" class="chart-card"
            >
              <template #header><span>Java 服务 CPU 趋势 Java Process CPU（单核 100%）</span></template>
              <div ref="javaProcessChartRef" class="chart" />
            </el-card>
          </template>
        </template>

        <!-- 事务处理时间明细（仅事务任务） -->
        <template v-if="report.transactionSummary && report.transactionSummary.stepSummaries.length">
          <el-divider content-position="left">事务步骤处理时间 Transaction Waterfall</el-divider>

          <el-row :gutter="12">
            <el-col :span="12">
              <el-card shadow="never" class="chart-card">
                <template #header><span>步骤耗时瀑布图 Step Duration（平均 / 最大 ms）</span></template>
                <div ref="waterfallChartRef" class="chart" />
              </el-card>
            </el-col>
            <el-col :span="12">
              <el-card shadow="never" class="chart-card">
                <template #header><span>事务总览 Transaction Overview</span></template>
                <el-descriptions :column="2" border size="small">
                  <el-descriptions-item label="事务总次数 Total">{{ report.transactionSummary.totalTransactions }}</el-descriptions-item>
                  <el-descriptions-item label="成功 Success">{{ report.transactionSummary.successCount }}</el-descriptions-item>
                  <el-descriptions-item label="失败 Fail">{{ report.transactionSummary.failCount }}</el-descriptions-item>
                  <el-descriptions-item label="失败率 Fail Rate">
                    {{ ((report.transactionSummary.failCount / (report.transactionSummary.totalTransactions || 1)) * 100).toFixed(1) }}%
                  </el-descriptions-item>
                  <el-descriptions-item label="平均耗时 Avg Elapsed">{{ report.transactionSummary.avgElapsedMs.toFixed(1) }} ms</el-descriptions-item>
                  <el-descriptions-item label="最大耗时 Max Elapsed">{{ report.transactionSummary.maxElapsedMs.toFixed(1) }} ms</el-descriptions-item>
                </el-descriptions>
              </el-card>
            </el-col>
          </el-row>

          <!-- 步骤明细表 -->
          <el-card shadow="never" class="chart-card">
            <template #header><span>步骤明细 Step Details</span></template>
            <el-table :data="report.transactionSummary.stepSummaries" size="small" stripe>
              <el-table-column prop="stepName" label="步骤名称 Step" min-width="140" show-overflow-tooltip />
              <el-table-column label="样本数 Samples" width="100">
                <template #default="{ row }">{{ row.sampleCount }}</template>
              </el-table-column>
              <el-table-column label="成功 Success" width="90">
                <template #default="{ row }">
                  <span style="color: #67c23a;">{{ row.successCount }}</span>
                </template>
              </el-table-column>
              <el-table-column label="失败 Fail" width="90">
                <template #default="{ row }">
                  <span :style="{ color: row.failCount > 0 ? '#f56c6c' : '#909399' }">{{ row.failCount }}</span>
                </template>
              </el-table-column>
              <el-table-column label="成功率 Success Rate" width="110">
                <template #default="{ row }">
                  {{ ((row.successCount / (row.sampleCount || 1)) * 100).toFixed(1) }}%
                </template>
              </el-table-column>
              <el-table-column label="平均 Avg ms" width="100">
                <template #default="{ row }">{{ row.avgElapsedMs.toFixed(1) }}</template>
              </el-table-column>
              <el-table-column label="最小 Min ms" width="100">
                <template #default="{ row }">{{ row.minElapsedMs.toFixed(1) }}</template>
              </el-table-column>
              <el-table-column label="最大 Max ms" width="100">
                <template #default="{ row }">{{ row.maxElapsedMs.toFixed(1) }}</template>
              </el-table-column>
            </el-table>
          </el-card>
        </template>
      </template>

      <el-empty v-else description="暂无报告数据（任务尚未执行）" />
    </template>
  </div>
</template>

<script setup lang="ts">
/**
 * 性能测试报告查看面板
 *
 * 功能：加载任务报告，展示摘要、指标、状态码分布和趋势图
 */

import { ref, watch, onMounted, onUnmounted, nextTick, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { Document, Refresh, Download, List, MagicStick } from '@element-plus/icons-vue'
import * as echarts from 'echarts'
import { getReport, listTasks, listExecutions, getExecutionReport, getAiAnalysis } from '@/api/performance'
import type { PerformanceReportResponse, AiAnalysisResponse } from '@/types/performance'
import type { EChartsOption } from 'echarts'
import type { PerformanceTaskListItem, PerformanceExecutionListItem } from '@/types/performance'
import { marked } from 'marked'

const route = useRoute()
const router = useRouter()
/** 从路由 query 读取任务 ID（由任务列表报告按钮跳转携带） */
const taskId = computed(() => (route.query.taskId as string) || '')
/** 从路由 query 读取执行记录 ID */
const executionId = computed(() => (route.query.executionId as string) || '')

/** 执行历史列表状态（空状态展示） */
const recentExecutions = ref<PerformanceExecutionListItem[]>([])
const loadingExecutions = ref(false)
const executionTotal = ref(0)
const executionPage = ref(1)

/** 加载执行历史列表 */
async function loadExecutions(page = 1) {
  loadingExecutions.value = true
  try {
    const params: any = { page, pageSize: 20 }
    if (taskId.value) params.taskId = taskId.value
    const res = await listExecutions(params)
    recentExecutions.value = res.items || []
    executionTotal.value = res.total || 0
    executionPage.value = page
  } catch { /* ignore */ } finally {
    loadingExecutions.value = false
  }
}

/** 状态标签类型 */
function statusTagType(status: string) {
  const map: Record<string, string> = { completed: 'success', running: 'primary', failed: 'danger', cancelled: 'warning' }
  return map[status] || 'info'
}

/** 状态标签文字 */
function statusLabel(status: string) {
  const map: Record<string, string> = { completed: '已完成', running: '运行中', pending: '等待中', failed: '失败', cancelled: '已取消' }
  return map[status] || status
}

/** 格式化时间 */
function formatTime(t: string | null | undefined): string {
  if (!t) return '-'
  try {
    const d = new Date(t)
    return d.toLocaleString('zh-CN', { hour12: false })
  } catch { return t }
}

/** 执行记录切换选项 */
const executionOptions = ref<{ id: string; label: string }[]>([])

/** 加载执行记录选项列表 */
async function loadExecutionOptions() {
  if (!taskId.value) return
  loadingExecutions.value = true
  try {
    const res = await listExecutions({ taskId: taskId.value, pageSize: 100 })
    executionOptions.value = (res.items || []).map((e: PerformanceExecutionListItem) => ({
      id: e.id,
      label: `${formatTime(e.startTime)} #${e.status} TPS:${e.actualTps != null ? e.actualTps.toFixed(1) : '-'} RT:${e.avgResponseTime != null ? e.avgResponseTime.toFixed(0) : '-'}ms`,
    }))
  } catch { /* ignore */ } finally {
    loadingExecutions.value = false
  }
}

/** 切换执行记录 */
function switchExecution(execId: string) {
  if (execId) {
    const query: Record<string, string> = { taskId: taskId.value, executionId: execId }
    router.push({ path: '/performance/report', query })
  }
}

/** 任务选择器状态 */
const selectedTaskId = ref('')
const availableTasks = ref<PerformanceTaskListItem[]>([])
const tasksLoading = ref(false)

/** 加载可选任务列表（已完成/失败的任务才能查看报告） */
async function loadAvailableTasks() {
  tasksLoading.value = true
  try {
    const res = await listTasks({ page: 1, pageSize: 100 })
    availableTasks.value = (res.items || []).filter(
      t => t.status === 'completed' || t.status === 'failed'
    )
  } catch { /* ignore */ } finally {
    tasksLoading.value = false
  }
}

/** 选中任务后跳转 */
function onTaskSelected(id: string) {
  if (id) {
    router.push({ path: '/performance/report', query: { taskId: id } })
  }
}

const loading = ref(false)
const report = ref<PerformanceReportResponse | null>(null)
const selectedExecutionId = ref('')

const tpsChartRef = ref<HTMLElement>()
const rtChartRef = ref<HTMLElement>()
const latencyChartRef = ref<HTMLElement>()
const bandwidthChartRef = ref<HTMLElement>()

// 资源图表引用
const resourceChartRef = ref<HTMLElement>()
const networkChartRef = ref<HTMLElement>()
const targetResourceChartRef = ref<HTMLElement>()
const javaProcessChartRef = ref<HTMLElement>()

// 瀑布图引用
const waterfallChartRef = ref<HTMLElement>()

let tpsChart: echarts.ECharts | null = null
let rtChart: echarts.ECharts | null = null
let latencyChart: echarts.ECharts | null = null
let bandwidthChart: echarts.ECharts | null = null
let resourceChart: echarts.ECharts | null = null
let networkChart: echarts.ECharts | null = null
let targetResourceChart: echarts.ECharts | null = null
let javaProcessChart: echarts.ECharts | null = null
let waterfallChart: echarts.ECharts | null = null

/** 分位数表格行（含 P95） */
const quantileRows = computed(() => {
  if (!report.value) return []
  const m = report.value.metrics
  return [
    { label: 'P50（中位数 Median）', value: m.p50ResponseTime.toFixed(1) + ' ms' },
    { label: 'P90', value: m.p90ResponseTime.toFixed(1) + ' ms' },
    { label: 'P95', value: m.p95ResponseTime.toFixed(1) + ' ms' },
    { label: 'P99', value: m.p99ResponseTime.toFixed(1) + ' ms' },
  ]
})

/** 是否存在错误分类数据 */
const hasErrorTypes = computed(() => {
  if (!report.value) return false
  const m = report.value.metrics
  return (m.errorTypeTimeout || m.errorTypeConnectError || m.errorTypeClientError ||
    m.errorTypeHttp4xx || m.errorTypeHttp5xx || m.errorTypeAssertion) > 0
})

/** 错误分类表格行 */
const errorTypeRows = computed(() => {
  if (!report.value) return []
  const m = report.value.metrics
  const total = (report.value.metrics.failCount || 0) || 1
  const pct = (n: number) => ((n / total) * 100).toFixed(1) + '%'
  return [
    { label: 'Timeout（请求超时）', count: m.errorTypeTimeout, percent: pct(m.errorTypeTimeout) },
    { label: 'Connect Error（连接错误）', count: m.errorTypeConnectError, percent: pct(m.errorTypeConnectError) },
    { label: 'Client Error（客户端错误）', count: m.errorTypeClientError, percent: pct(m.errorTypeClientError) },
    { label: 'HTTP 4xx（客户端错误响应）', count: m.errorTypeHttp4xx, percent: pct(m.errorTypeHttp4xx) },
    { label: 'HTTP 5xx（服务端错误响应）', count: m.errorTypeHttp5xx, percent: pct(m.errorTypeHttp5xx) },
    { label: 'Assertion Fail（断言失败）', count: m.errorTypeAssertion, percent: pct(m.errorTypeAssertion) },
  ]
})

/** 响应时间性能着色：<300ms 绿 / <1000ms 黄 / 其余红（贴合市场 P95 参考线） */
function rtPerfColor(p95: number) {
  if (p95 >= 1000) return '#f56c6c'
  if (p95 >= 300) return '#e6a23c'
  return '#67c23a'
}

/** Apdex 着色：≥0.94 绿 / ≥0.85 黄 / <0.85 红 */
function apdexColor(v: number) {
  if (v >= 0.94) return '#67c23a'
  if (v >= 0.85) return '#e6a23c'
  return '#f56c6c'
}

/** 字节数人性化显示（KB/MB） */
function formatBytes(bytes: number) {
  if (!bytes) return '0 B'
  if (bytes < 1024) return bytes + ' B'
  if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'
  return (bytes / 1024 / 1024).toFixed(2) + ' MB'
}

/** 状态码表格行 */
const statusRows = computed(() => {
  if (!report.value) return []
  const m = report.value.metrics
  const total = m.totalRequests || 1
  const rows = [
    { code: '2xx', count: m.status2xx, percent: ((m.status2xx / total) * 100).toFixed(1) + '%' },
    { code: '3xx', count: m.status3xx, percent: ((m.status3xx / total) * 100).toFixed(1) + '%' },
    { code: '4xx', count: m.status4xx, percent: ((m.status4xx / total) * 100).toFixed(1) + '%' },
    { code: '5xx', count: m.status5xx, percent: ((m.status5xx / total) * 100).toFixed(1) + '%' },
  ]
  return rows
})

/** 加载报告 */
async function loadReport() {
  if (!taskId.value) return
  loading.value = true
  try {
    // 优先按 executionId 加载指定执行记录的报告，否则加载任务最新报告
    const res = executionId.value
      ? await getExecutionReport(executionId.value)
      : await getReport(taskId.value)
    report.value = res
    // 先隐藏骨架屏让图表 div 渲染到 DOM，再初始化图表（v-if/v-else-if 互斥，否则 ref 为 undefined）
    loading.value = false
    await nextTick()
    initCharts()
    updateCharts()
  } catch (e: any) {
    ElMessage.error('加载报告失败: ' + (e.response?.data?.detail || e.message || ''))
    loading.value = false
  }
}

/** 导出报告 JSON */
function exportReport() {
  if (!report.value) return
  const blob = new Blob([JSON.stringify(report.value, null, 2)], { type: 'application/json' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `perf-report-${report.value.summary.taskId}.json`
  a.click()
  URL.revokeObjectURL(url)
}

// ==================== AI 分析 ====================

/** AI 分析结果 */
const aiResult = ref<AiAnalysisResponse | null>(null)
/** AI 分析加载中 */
const aiLoading = ref(false)

/** 渲染 Markdown 文本 */
function renderMarkdown(text: string): string {
  if (!text) return ''
  return marked.parse(text) as string
}

/** 触发 AI 分析（单次执行） */
async function triggerAiAnalysis() {
  if (!executionId.value) {
    ElMessage.warning('请先在顶部选择一条执行记录后再进行 AI 分析')
    return
  }
  aiLoading.value = true
  try {
    aiResult.value = await getAiAnalysis(executionId.value)
  } catch (e: any) {
    ElMessage.error('AI 分析失败: ' + (e.response?.data?.detail || e.message || ''))
  } finally {
    aiLoading.value = false
  }
}

/** 初始化图表 */
function initCharts() {
  if (tpsChartRef.value && !tpsChart) {
    tpsChart = echarts.init(tpsChartRef.value)
  }
  if (rtChartRef.value && !rtChart) {
    rtChart = echarts.init(rtChartRef.value)
  }
  if (latencyChartRef.value && !latencyChart) {
    latencyChart = echarts.init(latencyChartRef.value)
  }
  if (bandwidthChartRef.value && !bandwidthChart) {
    bandwidthChart = echarts.init(bandwidthChartRef.value)
  }
  if (resourceChartRef.value && !resourceChart) {
    resourceChart = echarts.init(resourceChartRef.value)
  }
  if (networkChartRef.value && !networkChart) {
    networkChart = echarts.init(networkChartRef.value)
  }
  if (targetResourceChartRef.value && !targetResourceChart) {
    targetResourceChart = echarts.init(targetResourceChartRef.value)
  }
  if (javaProcessChartRef.value && !javaProcessChart) {
    javaProcessChart = echarts.init(javaProcessChartRef.value)
  }
  if (waterfallChartRef.value && !waterfallChart) {
    waterfallChart = echarts.init(waterfallChartRef.value)
  }
}

/** 更新图表 */
function updateCharts() {
  if (!report.value || !report.value.snapshots.length) return
  const snapshots = report.value.snapshots
  const labels = snapshots.map((s) => `${s.elapsed.toFixed(0)}s`)
  const tps = snapshots.map((s) => s.tps)
  const avg = snapshots.map((s) => s.avgResponseTime)
  const p50 = snapshots.map((s) => s.p50ResponseTime)
  const p90 = snapshots.map((s) => s.p90ResponseTime)
  const p95 = snapshots.map((s) => s.p95ResponseTime)
  const p99 = snapshots.map((s) => s.p99ResponseTime)
  const latencyAvg = snapshots.map((s) => s.latencyAvg)
  const connectTimeAvg = snapshots.map((s) => s.connectTimeAvg)
  const sentBytes = snapshots.map((s) => s.sentBytes)
  const receivedBytes = snapshots.map((s) => s.receivedBytes)

  if (tpsChart) {
    const option: EChartsOption = {
      tooltip: { trigger: 'axis' },
      grid: { left: 50, right: 20, bottom: 30, top: 10 },
      xAxis: { type: 'category', data: labels },
      yAxis: { type: 'value', name: 'TPS' },
      series: [{
        type: 'line',
        data: tps,
        smooth: true,
        showSymbol: false,
        areaStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            { offset: 0, color: 'rgba(64,158,255,0.3)' },
            { offset: 1, color: 'rgba(64,158,255,0.05)' },
          ]),
        },
      }],
    }
    tpsChart.setOption(option, true)
  }

  if (rtChart) {
    const option: EChartsOption = {
      tooltip: { trigger: 'axis' },
      legend: { data: ['平均 Avg', 'P50', 'P90', 'P95', 'P99'], top: 0, itemWidth: 12, itemHeight: 8 },
      grid: { left: 50, right: 20, bottom: 30, top: 30 },
      xAxis: { type: 'category', data: labels },
      yAxis: { type: 'value', name: 'ms' },
      series: [
        { name: '平均 Avg', type: 'line', data: avg, smooth: true, showSymbol: false, lineStyle: { width: 1.5 } },
        { name: 'P50', type: 'line', data: p50, smooth: true, showSymbol: false, lineStyle: { width: 1.2, type: 'dashed' } },
        { name: 'P90', type: 'line', data: p90, smooth: true, showSymbol: false, lineStyle: { width: 1.2, type: 'dashed' } },
        { name: 'P95', type: 'line', data: p95, smooth: true, showSymbol: false, lineStyle: { width: 2, color: '#e6a23c' } },
        { name: 'P99', type: 'line', data: p99, smooth: true, showSymbol: false, lineStyle: { width: 1.2, type: 'dotted' } },
      ],
    }
    rtChart.setOption(option, true)
  }

  if (latencyChart) {
    const option: EChartsOption = {
      tooltip: { trigger: 'axis' },
      legend: { data: ['Latency（首字节延迟）', 'Connect（连接时间）'], top: 0, itemWidth: 12, itemHeight: 8 },
      grid: { left: 50, right: 20, bottom: 30, top: 30 },
      xAxis: { type: 'category', data: labels },
      yAxis: { type: 'value', name: 'ms' },
      series: [
        { name: 'Latency（首字节延迟）', type: 'line', data: latencyAvg, smooth: true, showSymbol: false, areaStyle: { opacity: 0.1 } },
        { name: 'Connect（连接时间）', type: 'line', data: connectTimeAvg, smooth: true, showSymbol: false, lineStyle: { type: 'dashed' } },
      ],
    }
    latencyChart.setOption(option, true)
  }

  if (bandwidthChart) {
    const option: EChartsOption = {
      tooltip: { trigger: 'axis' },
      legend: { data: ['Sent（发送 KB/s）', 'Received（接收 KB/s）'], top: 0, itemWidth: 12, itemHeight: 8 },
      grid: { left: 50, right: 20, bottom: 30, top: 30 },
      xAxis: { type: 'category', data: labels },
      yAxis: { type: 'value', name: 'KB/s' },
      series: [
        { name: 'Sent（发送 KB/s）', type: 'line', data: sentBytes.map(b => +(b / 1024).toFixed(1)), smooth: true, showSymbol: false, lineStyle: { color: '#409eff' } },
        { name: 'Received（接收 KB/s）', type: 'line', data: receivedBytes.map(b => +(b / 1024).toFixed(1)), smooth: true, showSymbol: false, lineStyle: { color: '#67c23a' } },
      ],
    }
    bandwidthChart.setOption(option, true)
  }

  // 资源图表（来自 resourceSummary.series）
  const rs = report.value.resourceSummary
  if (rs && rs.series && rs.series.length > 0) {
    const rLabels = rs.series.map((s: any) => `${s.elapsed.toFixed(0)}s`)
    const cpu = rs.series.map((s: any) => s.cpuPercent)
    const mem = rs.series.map((s: any) => s.memPercent)
    const netSent = rs.series.map((s: any) => s.netSentKbS)
    const netRecv = rs.series.map((s: any) => s.netRecvKbS)

    if (resourceChart) {
      resourceChart.setOption({
        tooltip: { trigger: 'axis' },
        legend: { data: ['CPU %', 'Memory %'], top: 0, itemWidth: 12, itemHeight: 8 },
        grid: { left: 50, right: 20, bottom: 30, top: 30 },
        xAxis: { type: 'category', data: rLabels },
        yAxis: { type: 'value', name: '%', max: 100 },
        series: [
          { name: 'CPU %', type: 'line', data: cpu, smooth: true, showSymbol: false, lineStyle: { width: 1.5, color: '#f56c6c' }, areaStyle: { opacity: 0.08 } },
          { name: 'Memory %', type: 'line', data: mem, smooth: true, showSymbol: false, lineStyle: { width: 1.5, color: '#409eff' }, areaStyle: { opacity: 0.08 } },
        ],
      }, true)
    }

    if (networkChart) {
      networkChart.setOption({
        tooltip: { trigger: 'axis' },
        legend: { data: ['发送 Sent', '接收 Recv'], top: 0, itemWidth: 12, itemHeight: 8 },
        grid: { left: 50, right: 20, bottom: 30, top: 30 },
        xAxis: { type: 'category', data: rLabels },
        yAxis: { type: 'value', name: 'KB/s' },
        series: [
          { name: '发送 Sent', type: 'line', data: netSent, smooth: true, showSymbol: false, lineStyle: { width: 1.5, color: '#67c23a' }, areaStyle: { opacity: 0.08 } },
          { name: '接收 Recv', type: 'line', data: netRecv, smooth: true, showSymbol: false, lineStyle: { width: 1.5, color: '#e6a23c' }, areaStyle: { opacity: 0.08 } },
        ],
      }, true)
    }
  }

  // 目标机资源图表（来自 targetResourceSummary.series）
  const ts = report.value.targetResourceSummary
  if (ts && ts.series && ts.series.length > 0) {
    const tLabels = ts.series.map((s: any) => `${s.elapsed.toFixed(0)}s`)
    const tCpu = ts.series.map((s: any) => s.cpuPercent)
    const tMem = ts.series.map((s: any) => s.memPercent)
    const tLoad = ts.series.map((s: any) => s.loadAvg1)

    if (targetResourceChart) {
      targetResourceChart.setOption({
        tooltip: { trigger: 'axis' },
        legend: { data: ['CPU %', 'Memory %', 'Load 1m'], top: 0, itemWidth: 12, itemHeight: 8 },
        grid: { left: 50, right: 20, bottom: 30, top: 30 },
        xAxis: { type: 'category', data: tLabels },
        yAxis: [
          { type: 'value', name: '%', max: 100 },
          { type: 'value', name: 'Load', splitLine: { show: false } },
        ],
        series: [
          { name: 'CPU %', type: 'line', data: tCpu, smooth: true, showSymbol: false, lineStyle: { width: 1.5, color: '#f56c6c' }, areaStyle: { opacity: 0.08 } },
          { name: 'Memory %', type: 'line', data: tMem, smooth: true, showSymbol: false, lineStyle: { width: 1.5, color: '#409eff' }, areaStyle: { opacity: 0.08 } },
          { name: 'Load 1m', type: 'line', data: tLoad, smooth: true, showSymbol: false, yAxisIndex: 1, lineStyle: { width: 1.5, type: 'dashed', color: '#e6a23c' } },
        ],
      }, true)
    }
  }

  // Java 进程 CPU 趋势图（来自 targetResourceSummary.javaProcessSeries）
  const jps = report.value.targetResourceSummary?.javaProcessSeries
  if (jps && jps.length > 0 && javaProcessChart) {
    const jLabels = jps[0].data.map((s: any) => `${s.elapsed.toFixed(0)}s`)
    const jSeries = jps.map((proc: any) => ({
      name: proc.processName,
      type: 'line',
      data: proc.data.map((s: any) => s.cpuPercent),
      smooth: true,
      showSymbol: false,
      lineStyle: { width: 1.5 },
    }))
    javaProcessChart.setOption({
      tooltip: { trigger: 'axis' },
      legend: { data: jps.map((p: any) => p.processName), top: 0, itemWidth: 12, itemHeight: 8 },
      grid: { left: 50, right: 20, bottom: 30, top: 30 },
      xAxis: { type: 'category', data: jLabels, axisLabel: { fontSize: 11 } },
      yAxis: { type: 'value', name: 'CPU %', max: 100 },
      series: jSeries,
    }, true)
  }

  // 瀑布图（事务步骤耗时）
  if (waterfallChart && report.value.transactionSummary?.stepSummaries?.length) {
    const steps = report.value.transactionSummary.stepSummaries
    const names = steps.map(s => s.stepName)
    const avgData = steps.map(s => s.avgElapsedMs)
    const maxData = steps.map(s => s.maxElapsedMs)
    waterfallChart.setOption({
      tooltip: {
        trigger: 'axis',
        axisPointer: { type: 'shadow' },
      },
      legend: { data: ['平均 Avg ms', '最大 Max ms'], top: 0, itemWidth: 12, itemHeight: 8 },
      grid: { left: 20, right: 80, bottom: 20, top: 30 },
      xAxis: { type: 'value', name: 'ms' },
      yAxis: { type: 'category', data: names.slice().reverse(), axisLabel: { width: 100, overflow: 'truncate' } },
      series: [
        {
          name: '平均 Avg ms',
          type: 'bar',
          data: avgData.slice().reverse(),
          barWidth: 10,
          barGap: '30%',
          itemStyle: { color: '#409eff', borderRadius: [0, 3, 3, 0] },
        },
        {
          name: '最大 Max ms',
          type: 'bar',
          data: maxData.slice().reverse(),
          barWidth: 10,
          itemStyle: { color: '#f56c6c', borderRadius: [0, 3, 3, 0] },
        },
      ],
    }, true)
  }
}

/** 模式标签 */
function modeLabel(mode: string) {
  const map: Record<string, string> = { concurrent: '并发 Concurrent', qps: 'QPS（固定吞吐量）', step: '阶梯 Step' }
  return map[mode] || mode
}

defineExpose({ loadReport })

watch(() => route.query.taskId, (newId) => {
  if (newId) {
    selectedExecutionId.value = executionId.value
    loadReport()
    loadExecutionOptions()
  }
})

onMounted(() => {
  if (taskId.value) {
    selectedExecutionId.value = executionId.value
    loadReport()
    loadExecutionOptions()
  } else {
    loadAvailableTasks()
    loadExecutions()
  }
})

onUnmounted(() => {
  tpsChart?.dispose()
  rtChart?.dispose()
  latencyChart?.dispose()
  bandwidthChart?.dispose()
  resourceChart?.dispose()
  networkChart?.dispose()
  targetResourceChart?.dispose()
  javaProcessChart?.dispose()
  waterfallChart?.dispose()
})
</script>

<style scoped>
.report-panel {
  padding: 0;
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 80px 0;
  color: #909399;
}

.empty-state p {
  margin-top: 12px;
  font-size: 14px;
}

.report-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}

.report-header-left {
  display: flex;
  align-items: center;
}

.report-header-right {
  display: flex;
  gap: 8px;
}

.summary-block {
  margin-bottom: 12px;
}

.metrics-row {
  margin-bottom: 12px;
}

.metric-card {
  text-align: center;
}

.metric-value {
  font-size: 26px;
  font-weight: 700;
  color: #409eff;
  line-height: 1.2;
}

.metric-label {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
}

.chart-card {
  margin-bottom: 12px;
}

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

.ai-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.ai-section {
  margin-bottom: 20px;
}

.ai-section-title {
  margin: 0 0 8px 0;
  font-size: 15px;
  color: #303133;
}

.ai-markdown {
  font-size: 14px;
  line-height: 1.7;
  color: #303133;
}

.ai-markdown p {
  margin: 4px 0;
}

.ai-markdown ul, .ai-markdown ol {
  padding-left: 20px;
}

.ai-markdown code {
  background: #f5f7fa;
  padding: 1px 4px;
  border-radius: 3px;
  font-size: 13px;
}

.ai-markdown pre {
  background: #f5f7fa;
  padding: 12px;
  border-radius: 4px;
  overflow-x: auto;
}

.ai-markdown table {
  border-collapse: collapse;
  width: 100%;
  margin: 8px 0;
}

.ai-markdown th, .ai-markdown td {
  border: 1px solid #ebeef5;
  padding: 6px 10px;
  text-align: left;
}

.ai-markdown th {
  background: #f5f7fa;
  font-weight: 600;
}
</style>