<!--
  组件名称：ProjectDetail.vue
  组件描述：性能测试项目详情页（任务列表 + 复选框批量执行 + WebSocket 进度）

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

<template>
  <div class="project-detail-page">
    <!-- 返回按钮 + 项目信息头部 -->
    <div class="page-header">
      <div class="header-left">
        <el-button @click="goBack" text>
          <el-icon><ArrowLeft /></el-icon>返回
        </el-button>
        <h2 class="project-title">{{ project?.name || '项目加载中...' }}</h2>
        <el-tag v-if="project" size="small" :type="project.projectType === 'standard' ? 'info' : 'warning'">
          {{ project.projectType === 'standard' ? '标准版' : '项目定制' }}
        </el-tag>
      </div>
      <div class="header-right">
        <el-button type="primary" :loading="runningAll" @click="handleRunAll">
          <el-icon><VideoPlay /></el-icon>执行全部
        </el-button>
        <el-button v-if="selectedIds.length > 0" type="warning" :loading="runningBatch" @click="handleBatchRun">
          <el-icon><VideoPlay /></el-icon>批量执行（{{ selectedIds.length }}）
        </el-button>
        <el-button v-if="lastReportId" type="success" @click="viewMergedReport(lastReportId)">
          <el-icon><Document /></el-icon>查看合并报告
        </el-button>
        <el-button @click="viewHistoryReports">
          <el-icon><List /></el-icon>历史报告
        </el-button>
        <el-button @click="loadTasks">
          <el-icon><Refresh /></el-icon>刷新
        </el-button>
      </div>
    </div>

    <!-- 项目描述 -->
    <div v-if="project?.description" class="project-desc-bar">
      {{ project.description }}
    </div>

    <!-- 批量执行实时进度卡片 -->
    <el-card v-if="batchProgress" shadow="never" class="batch-progress-card">
      <div class="batch-progress-header">
        <span>
          <el-icon style="vertical-align: -2px; margin-right: 4px"><Loading v-if="isBatchRunning" /></el-icon>
          Batch Progress（批量执行进度）
        </span>
        <el-tag :type="batchStatusType(batchProgress.currentStatus)" size="small">
          {{ batchStatusLabel(batchProgress.currentStatus) }}
        </el-tag>
      </div>
      <div class="batch-progress-body">
        <el-progress
          :percentage="batchPercent"
          :status="batchProgress.currentStatus === 'running' ? undefined : (batchProgress.failCount > 0 ? 'exception' : 'success')"
          :stroke-width="14"
          :text-inside="true"
        />
        <div class="batch-progress-info">
          <span class="batch-progress-count">
            {{ batchProgress.successCount }} Success（成功） / {{ batchProgress.failCount }} Failed（失败）
          </span>
          <span>
            {{ batchProgress.currentIndex }} / {{ batchProgress.totalCount }}（{{ batchPercent }}%）
          </span>
        </div>
        <div v-if="batchProgress.currentTaskName" class="batch-progress-text">
          Current Task（当前任务）: {{ batchProgress.currentTaskName }}
          <el-button link type="primary" size="small" style="margin-left: 12px" @click="disconnectBatchWs">
            关闭进度
          </el-button>
        </div>
        <div v-else class="batch-progress-text">
          <el-button v-if="!isBatchRunning && batchProgress.totalCount > 0" link type="primary" size="small" @click="viewBatchMonitor">
            查看批次明细
          </el-button>
          <el-button link type="primary" size="small" style="margin-left: 12px" @click="disconnectBatchWs">
            关闭进度
          </el-button>
        </div>
      </div>
    </el-card>

    <!-- 任务列表 -->
    <el-card shadow="never">
      <div class="toolbar">
        <el-select v-model="statusFilter" placeholder="全部状态" clearable style="width: 140px" @change="loadTasks">
          <el-option label="全部" value="" />
          <el-option label="等待中" value="pending" />
          <el-option label="运行中" value="running" />
          <el-option label="已完成" value="completed" />
          <el-option label="失败" value="failed" />
          <el-option label="已取消" value="cancelled" />
        </el-select>
      </div>

      <el-table
        ref="tableRef"
        :data="tasks"
        v-loading="loading"
        stripe
        style="width: 100%"
        @selection-change="onSelectionChange"
      >
        <el-table-column type="selection" width="50" />
        <el-table-column prop="name" label="任务名称" min-width="160" show-overflow-tooltip />
        <el-table-column prop="targetUrl" label="目标 URL" min-width="200" show-overflow-tooltip />
        <el-table-column prop="method" label="方法" width="80" />
        <el-table-column label="模式" width="90">
          <template #default="{ row }">
            <el-tag size="small">{{ modeLabel(row.mode) }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="Concurrency（并发）" width="70" prop="concurrency" />
        <el-table-column label="时长" width="80">
          <template #default="{ row }">{{ row.duration }}s</template>
        </el-table-column>
        <el-table-column label="状态" width="110">
          <template #default="{ row }">
            <el-tag :type="statusType(row.status)" size="small">
              {{ statusLabel(row.status) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="TPS（吞吐量）" width="90">
          <template #default="{ row }">
            {{ row.actualTps != null ? row.actualTps.toFixed(1) : '-' }}
          </template>
        </el-table-column>
        <el-table-column label="Error Rate（错误率）" width="90">
          <template #default="{ row }">
            <span :style="{ color: (row.errorRate || 0) > 5 ? '#f56c6c' : '#67c23a' }">
              {{ row.errorRate != null ? (row.errorRate * 100).toFixed(1) + '%' : '-' }}
            </span>
          </template>
        </el-table-column>
        <el-table-column label="创建时间" width="170">
          <template #default="{ row }">{{ formatTime(row.createdAt) }}</template>
        </el-table-column>
        <el-table-column label="操作" width="250" fixed="right">
          <template #default="{ row }">
            <el-button
              v-if="row.status === 'pending' || row.status === 'completed' || row.status === 'failed' || row.status === 'cancelled'"
              link type="primary" size="small" :loading="runningId === row.id" @click="handleRun(row)"
            >
              执行
            </el-button>
            <el-button v-if="row.status === 'running'" link type="warning" size="small" @click="handleStop(row)">
              停止
            </el-button>
            <el-button
              v-if="row.status === 'running' || row.status === 'completed'"
              link type="primary" size="small" @click="router.push('/performance/monitor?taskId=' + row.id)"
            >
              监控
            </el-button>
            <el-button
              v-if="row.status === 'completed' || row.status === 'failed'"
              link type="primary" size="small" @click="router.push('/performance/report?taskId=' + row.id)"
            >
              报告
            </el-button>
            <el-popconfirm title="确定删除此任务？" @confirm="handleDelete(row)">
              <template #reference>
                <el-button link type="danger" size="small">删除</el-button>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>

      <div class="pagination">
        <el-pagination
          v-model:current-page="page"
          v-model:page-size="pageSize"
          :total="total"
          :page-sizes="[10, 20, 50]"
          layout="total, sizes, prev, pager, next"
          @change="loadTasks"
        />
      </div>
    </el-card>
  </div>
</template>

<script setup lang="ts">
/**
 * 性能测试项目详情页
 *
 * 功能：
 * 1. 项目信息展示 + 返回按钮
 * 2. 任务列表（带复选框，按项目过滤）
 * 3. 执行全部（runProjectAll）
 * 4. 批量执行选中任务（batchRunTasks）
 * 5. WebSocket 批量执行进度条
 * 6. 单任务执行/停止/删除/跳转监控报告
 */

import { ref, onMounted, computed, onUnmounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ArrowLeft, VideoPlay, Refresh, Document, List, Loading } from '@element-plus/icons-vue'
import { getProject, listTasks, runTask, stopTask, deleteTask, runProjectAll, batchRunTasks, createPerfBatchStream } from '@/api/performance'
import type { PerformanceProject, PerformanceTaskListItem, PerfBatchProgress } from '@/types/performance'

const router = useRouter()
const route = useRoute()

// ==================== 响应式数据 ====================
const projectId = computed(() => route.params.id as string)

const loading = ref(false)
const project = ref<PerformanceProject | null>(null)
const tasks = ref<PerformanceTaskListItem[]>([])
const total = ref(0)
const page = ref(1)
const pageSize = ref(20)
const statusFilter = ref('')
const runningId = ref('')
const runningAll = ref(false)
const runningBatch = ref(false)

// 复选框选中
const selectedIds = ref<string[]>([])
const tableRef = ref()

const lastReportId = ref<string | null>(null) // 最近一次批量执行生成的合并报告 ID

// 批量执行进度
const batchProgress = ref<PerfBatchProgress | null>(null)
const batchWs = ref<WebSocket | null>(null)
const isBatchRunning = computed(() => batchProgress.value?.currentStatus === 'running')
const batchPercent = computed(() => {
  if (!batchProgress.value || batchProgress.value.totalCount === 0) return 0
  return Math.round((batchProgress.value.currentIndex / batchProgress.value.totalCount) * 100)
})

// ==================== 方法定义 ====================

/** 返回项目管理页 */
function goBack() {
  router.push('/performance/projects')
}

/** 加载项目信息 */
async function loadProject() {
  if (!projectId.value) return
  try {
    project.value = await getProject(projectId.value)
  } catch (e: any) {
    ElMessage.error('加载项目信息失败: ' + (e.response?.data?.detail || e.message || ''))
  }
}

/** 加载任务列表（按项目过滤） */
async function loadTasks() {
  if (!projectId.value) return
  loading.value = true
  try {
    const params: any = { page: page.value, pageSize: pageSize.value, projectId: projectId.value }
    if (statusFilter.value) params.status = statusFilter.value
    const res = await listTasks(params)
    tasks.value = res.items
    total.value = res.total
  } catch (e: any) {
    ElMessage.error('加载任务列表失败: ' + (e.message || ''))
  } finally {
    loading.value = false
  }
}

/** 复选框选中变化 */
function onSelectionChange(selection: PerformanceTaskListItem[]) {
  selectedIds.value = selection.map(t => t.id)
}

/** 执行单个任务 */
async function handleRun(task: PerformanceTaskListItem) {
  runningId.value = task.id
  try {
    const res = await runTask(task.id)
    ElMessage.success(res.message || '任务已开始执行')
    await loadTasks()
  } catch (e: any) {
    ElMessage.error('执行失败: ' + (e.response?.data?.detail || e.message || ''))
  } finally {
    runningId.value = ''
  }
}

/** 停止单个任务 */
async function handleStop(task: PerformanceTaskListItem) {
  try {
    const res = await stopTask(task.id)
    ElMessage.success(res.message || '已发送停止信号')
    await loadTasks()
  } catch (e: any) {
    ElMessage.error('停止失败: ' + (e.response?.data?.detail || e.message || ''))
  }
}

/** 删除单个任务 */
async function handleDelete(task: PerformanceTaskListItem) {
  try {
    await deleteTask(task.id)
    ElMessage.success('任务已删除')
    await loadTasks()
  } catch (e: any) {
    ElMessage.error('删除失败: ' + (e.response?.data?.detail || e.message || ''))
  }
}

/** 执行全部 */
async function handleRunAll() {
  const confirmed = await ElMessageBox.confirm(
    `确定要执行项目"${project.value?.name}"下的全部任务吗？`,
    '确认执行',
    { type: 'warning' }
  ).catch(() => null)
  if (confirmed === null) return

  runningAll.value = true
  try {
    const res = await runProjectAll(projectId.value)
    // 连接批次专属 WebSocket 订阅进度
    connectBatchWs(res.batchId)
    // 初始化进度
    batchProgress.value = {
      type: 'perf_batch_progress',
      batchId: res.batchId,
      projectId: projectId.value,
      currentIndex: 0,
      totalCount: res.taskCount || res.taskIds?.length || 0,
      currentTaskId: '',
      currentTaskName: '',
      currentStatus: 'running',
      successCount: 0,
      failCount: 0,
    }
  } catch (e: any) {
    ElMessage.error('执行失败: ' + (e.response?.data?.detail || e.message || ''))
    runningAll.value = false
  }
}

/** 批量执行选中任务 */
async function handleBatchRun() {
  if (selectedIds.value.length === 0) {
    ElMessage.warning('请至少选择一个任务')
    return
  }

  const confirmed = await ElMessageBox.confirm(
    `确定要批量执行选中的 ${selectedIds.value.length} 个任务吗？`,
    '确认执行',
    { type: 'warning' }
  ).catch(() => null)
  if (confirmed === null) return

  runningBatch.value = true
  try {
    const res = await batchRunTasks({ taskIds: selectedIds.value, projectId: projectId.value })
    // 连接批次专属 WebSocket 订阅进度
    connectBatchWs(res.batchId)
    // 初始化进度
    batchProgress.value = {
      type: 'perf_batch_progress',
      batchId: res.batchId,
      projectId: projectId.value,
      currentIndex: 0,
      totalCount: res.taskCount || selectedIds.value.length,
      currentTaskId: '',
      currentTaskName: '',
      currentStatus: 'running',
      successCount: 0,
      failCount: 0,
    }
  } catch (e: any) {
    ElMessage.error('批量执行失败: ' + (e.response?.data?.detail || e.message || ''))
    runningBatch.value = false
  }
}

/** 状态标签类型 */
function statusType(status: string) {
  const map: Record<string, string> = { completed: 'success', running: 'primary', pending: 'info', 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 modeLabel(mode: string) {
  const map: Record<string, string> = { concurrent: '并发', qps: 'QPS', step: '阶梯' }
  return map[mode] || mode
}

/** 跳转合并报告 */
function viewMergedReport(reportId: string) {
  router.push(`/performance/project-report?reportId=${reportId}&projectId=${projectId.value}`)
}

/** 跳转历史报告列表 */
function viewHistoryReports() {
  router.push(`/performance/project-report?projectId=${projectId.value}`)
}

/** 跳转批量监控页 */
function viewBatchMonitor() {
  if (batchProgress.value?.batchId) {
    router.push({
      path: '/performance/batch-monitor',
      query: { batchId: batchProgress.value.batchId, projectId: projectId.value },
    })
  }
}

// ==================== 批量进度 WebSocket ====================

/** 连接批次专属 WebSocket 订阅批量执行进度 */
function connectBatchWs(batchId: string) {
  disconnectBatchWs()
  batchWs.value = createPerfBatchStream(
    batchId,
    handleBatchProgress,
    () => { /* 连接错误，进度条停在上次状态 */ },
    () => { batchWs.value = null },
  )
}

/** 断开批量进度 WebSocket */
function disconnectBatchWs() {
  if (batchWs.value) {
    batchWs.value.close()
    batchWs.value = null
  }
}

/** 处理批量进度消息 */
function handleBatchProgress(msg: PerfBatchProgress) {
  batchProgress.value = msg
  // 批量执行完成时刷新任务列表（状态可能有变化）
  if (msg.currentStatus === 'completed' || msg.currentStatus === 'partially_failed') {
    loadTasks()
    loadProject()
  }
  // 开始执行后可以停止按钮 loading
  if (msg.currentIndex > 0) {
    runningAll.value = false
    runningBatch.value = false
  }
}

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

/** 批量状态标签文字 */
function batchStatusLabel(status: string) {
  const map: Record<string, string> = {
    running: 'Running（执行中）',
    completed: 'Completed（已完成）',
    partially_failed: 'Partially Failed（部分失败）',
    failed: 'Failed（失败）',
    cancelled: 'Cancelled（已取消）',
  }
  return map[status] || status || 'Running（执行中）'
}

/** 格式化时间 */
function formatTime(t: string) {
  return t?.replace('T', ' ').substring(0, 19) || ''
}

// ==================== 生命周期 ====================
onMounted(() => {
  loadProject()
  loadTasks()
})

onUnmounted(() => {
  disconnectBatchWs()
})
</script>

<style scoped>
.project-detail-page {
  padding: 0;
}

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

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

    .project-title {
      font-size: 20px;
      font-weight: 600;
      color: #303133;
      margin: 0;
    }
  }

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

.project-desc-bar {
  background: #f0f5ff;
  border: 1px solid #d6e4ff;
  border-radius: 4px;
  padding: 10px 16px;
  margin-bottom: 16px;
  font-size: 13px;
  color: #606266;
  line-height: 1.6;
}

.batch-progress-card {
  margin-bottom: 16px;
  background: #fafafa;

  .batch-progress-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-weight: 600;
    font-size: 14px;
  }

  .batch-progress-body {
    .batch-progress-info {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 10px;
      font-size: 13px;
      color: #606266;

      .batch-progress-count {
        color: #909399;
      }
    }

    .batch-progress-text {
      margin-top: 6px;
      font-size: 12px;
      color: #909399;
      text-align: right;
    }
  }
}

.toolbar {
  display: flex;
  gap: 12px;
  margin-bottom: 16px;
  align-items: center;
}

.pagination {
  display: flex;
  justify-content: flex-end;
  margin-top: 16px;
}
</style>