<!--
  组件名称：Projects.vue
  组件描述：性能测试项目管理页面（卡片网格 + 类型筛选 + 一键执行 + 项目CRUD）

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

<template>
  <div class="projects-page">
    <!-- 操作栏 -->
    <div class="page-header">
      <el-tabs v-model="projectType" @tab-change="loadProjects">
        <el-tab-pane label="标准版" name="standard" />
        <el-tab-pane label="项目定制" name="custom" />
      </el-tabs>
      <div class="header-actions">
        <el-button type="primary" @click="openCreateDialog">
          <el-icon><Plus /></el-icon>新建项目
        </el-button>
        <el-button @click="loadProjects">
          <el-icon><Refresh /></el-icon>刷新
        </el-button>
      </div>
    </div>

    <!-- 项目卡片网格 -->
    <el-row :gutter="20" v-loading="loading">
      <el-col :span="6" v-for="project in projects" :key="project.id">
        <el-card class="project-card" shadow="hover" @click="enterProject(project)">
          <div class="project-icon">
            <el-icon :size="32"><component :is="iconOf(project.icon)" /></el-icon>
            <el-tag size="small" :type="project.projectType === 'standard' ? 'info' : 'warning'" class="project-type-tag">
              {{ project.projectType === 'standard' ? '标准版' : '项目定制' }}
            </el-tag>
          </div>
          <div class="project-info">
            <h3 class="project-name">{{ project.name }}</h3>
            <p class="project-desc">{{ project.description || '暂无描述' }}</p>
            <div class="project-stats">
              <span class="stat-item">
                <el-icon><Document /></el-icon>
                {{ project.taskCount || 0 }} 任务
              </span>
              <span class="stat-item">
                <el-icon><TrendCharts /></el-icon>
                <el-tag :type="statusType(project.lastRunStatus)" size="small">
                  {{ project.lastRunStatus ? statusLabel(project.lastRunStatus) : '未执行' }}
                </el-tag>
              </span>
            </div>
            <div class="project-last-run" v-if="project.lastRunTime">
              最近执行：{{ formatTime(project.lastRunTime) }}
            </div>
          </div>
          <div class="project-actions" @click.stop>
            <el-button type="primary" size="small" :loading="runningId === project.id" @click="runProject(project)">
              执行全部
            </el-button>
            <el-button size="small" @click="enterProject(project)">进入项目</el-button>
            <el-button size="small" @click="openEditDialog(project)">编辑</el-button>
            <el-button type="danger" size="small" @click="handleDeleteProject(project)">删除</el-button>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <el-empty v-if="!loading && projects.length === 0" description="暂无项目，点击右上角新建项目" />

    <!-- 创建/编辑项目弹窗 -->
    <el-dialog
      v-model="dialogVisible"
      :title="isEdit ? '编辑项目' : '创建项目'"
      width="500px"
    >
      <el-form :model="formData" label-width="80px">
        <el-form-item label="项目名称" required>
          <el-input v-model="formData.name" placeholder="请输入项目名称" maxlength="100" />
        </el-form-item>
        <el-form-item label="项目类型">
          <el-select v-model="formData.projectType" style="width: 100%">
            <el-option label="标准版" value="standard" />
            <el-option label="项目定制" value="custom" />
          </el-select>
        </el-form-item>
        <el-form-item label="项目图标">
          <el-select v-model="formData.icon" style="width: 100%" placeholder="选择图标">
            <el-option label="文件夹" value="folder" />
            <el-option label="收藏" value="collection" />
            <el-option label="文件" value="files" />
            <el-option label="数据" value="data" />
          </el-select>
        </el-form-item>
        <el-form-item label="排序">
          <el-input-number v-model="formData.sortOrder" :min="0" :max="999" style="width: 100%" />
        </el-form-item>
        <el-form-item label="项目描述">
          <el-input
            v-model="formData.description"
            type="textarea"
            :rows="3"
            placeholder="请输入项目描述"
            maxlength="500"
          />
        </el-form-item>
      </el-form>

      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitForm" :loading="submitting">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
/**
 * 性能测试项目管理页面
 *
 * 功能：
 * 1. 标准版 / 项目定制 Tab 切换
 * 2. 项目卡片网格展示（任务数、最近执行状态/时间）
 * 3. 一键执行整个项目（run-project-all）
 * 4. 进入项目详情（/performance/projects/:id）勾选批量执行
 * 5. 项目增删改
 */

import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Refresh, Folder, Collection, Files, DataAnalysis, Document, TrendCharts } from '@element-plus/icons-vue'
import { listProjects, createProject, updateProject, deleteProject, runProjectAll } from '@/api/performance'
import type { PerformanceProject, PerformanceProjectCreate, PerformanceProjectUpdate, PerfProjectType } from '@/types/performance'

const router = useRouter()

// ==================== 响应式数据 ====================
const loading = ref(false)
const projects = ref<PerformanceProject[]>([])
const projectType = ref('standard')
const dialogVisible = ref(false)
const isEdit = ref(false)
const submitting = ref(false)
const editingId = ref('')
const runningId = ref('')

const formData = ref<PerformanceProjectCreate>({
  name: '',
  description: '',
  projectType: 'standard',
  icon: 'folder',
  sortOrder: 0,
})

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

/** 项目图标组件映射 */
function iconOf(icon: string) {
  const map: Record<string, any> = {
    folder: Folder,
    collection: Collection,
    files: Files,
    data: DataAnalysis,
  }
  return map[icon] || Folder
}

/** 加载项目列表（按类型筛选） */
const loadProjects = async () => {
  loading.value = true
  try {
    const response = await listProjects({ page: 1, pageSize: 200, projectType: projectType.value })
    projects.value = response.items
  } catch (error: any) {
    ElMessage.error('加载项目失败: ' + (error.response?.data?.detail || error.message || ''))
  } finally {
    loading.value = false
  }
}

/** 显示创建弹窗 */
const openCreateDialog = () => {
  isEdit.value = false
  editingId.value = ''
  formData.value = { name: '', description: '', projectType: projectType.value as PerfProjectType, icon: 'folder', sortOrder: 0 }
  dialogVisible.value = true
}

/** 显示编辑弹窗 */
const openEditDialog = (project: PerformanceProject) => {
  isEdit.value = true
  editingId.value = project.id
  formData.value = {
    name: project.name,
    description: project.description || '',
    projectType: project.projectType || 'standard',
    icon: project.icon || 'folder',
    sortOrder: project.sortOrder ?? 0,
  }
  dialogVisible.value = true
}

/** 提交表单 */
const submitForm = async () => {
  if (!formData.value.name.trim()) {
    ElMessage.warning('请输入项目名称')
    return
  }

  submitting.value = true
  try {
    if (isEdit.value) {
      await updateProject(editingId.value, formData.value as PerformanceProjectUpdate)
      ElMessage.success('项目更新成功')
    } else {
      await createProject(formData.value)
      ElMessage.success('项目创建成功')
    }
    dialogVisible.value = false
    await loadProjects()
  } catch (error: any) {
    ElMessage.error('操作失败: ' + (error.response?.data?.detail || error.message || ''))
  } finally {
    submitting.value = false
  }
}

/** 删除项目（不级联删除任务，仅将任务移出归属） */
const handleDeleteProject = async (project: PerformanceProject) => {
  try {
    await ElMessageBox.confirm(
      `确定要删除项目"${project.name}"吗？该项目下的任务不会被删除，只会被移出该项目！`,
      '确认删除',
      { type: 'warning' }
    )

    await deleteProject(project.id)
    ElMessage.success('项目删除成功')
    await loadProjects()
  } catch (error: any) {
    if (error !== 'cancel') {
      ElMessage.error('删除失败: ' + (error.response?.data?.detail || error.message || ''))
    }
  }
}

/** 一键执行整个项目 */
const runProject = async (project: PerformanceProject) => {
  const confirmed = await ElMessageBox.confirm(
    `确定要执行项目"${project.name}"下的全部任务吗？（串行执行 ${project.taskCount || 0} 个任务）`,
    '确认执行',
    { type: 'warning' }
  ).catch(() => null)
  if (confirmed === null) return

  runningId.value = project.id
  try {
    const res = await runProjectAll(project.id)
    // 立即跳转批量执行监控页
    router.push({
      path: '/performance/batch-monitor',
      query: { batchId: res.batchId, projectId: project.id },
    })
  } catch (error: any) {
    ElMessage.error('执行失败: ' + (error.response?.data?.detail || error.message || ''))
    runningId.value = ''
  }
}

/** 进入项目详情 */
const enterProject = (project: PerformanceProject) => {
  router.push(`/performance/projects/${project.id}`)
}

/** 状态标签类型 */
function statusType(status: string | null) {
  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 formatTime(t: string) {
  return t?.replace('T', ' ').substring(0, 19) || ''
}

// ==================== 生命周期 ====================
onMounted(() => {
  loadProjects()
})
</script>

<style lang="scss" scoped>
.projects-page {
  .page-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;

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

  .project-card {
    margin-bottom: 20px;
    cursor: pointer;
    transition: transform 0.2s;

    &:hover {
      transform: translateY(-2px);
    }

    .project-icon {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-bottom: 12px;

      .project-type-tag {
        margin-left: auto;
      }
    }

    .project-info {
      .project-name {
        margin: 0 0 8px;
        font-size: 16px;
        font-weight: 600;
      }

      .project-desc {
        margin: 0 0 12px;
        font-size: 13px;
        color: #909399;
        min-height: 20px;
      }

      .project-stats {
        display: flex;
        gap: 16px;
        font-size: 13px;
        color: #606266;
        margin-bottom: 6px;

        .stat-item {
          display: flex;
          align-items: center;
          gap: 4px;
        }
      }

      .project-last-run {
        font-size: 12px;
        color: #909399;
      }
    }

    .project-actions {
      margin-top: 16px;
      display: flex;
      gap: 8px;
      flex-wrap: wrap;
    }
  }
}
</style>