<!--
  页面名称：Modules.vue
  页面描述：模块管理页面，展示模块卡片列表

  @author czj
  @date 2026-07-09
-->

<template>
  <div class="modules-page">
    <!-- 操作栏 -->
    <div class="page-header">
      <el-button type="primary" @click="showCreateDialog">
        <el-icon><Plus /></el-icon>
        新建模块
      </el-button>
      <el-button @click="loadModules">
        <el-icon><Refresh /></el-icon>
        刷新
      </el-button>
    </div>

    <!-- 模块卡片网格 -->
    <el-row :gutter="20" v-loading="loading">
      <el-col :span="6" v-for="module in modules" :key="module.id">
        <el-card class="module-card" shadow="hover">
          <div class="module-icon">
            <el-icon :size="32"><Folder /></el-icon>
          </div>
          <div class="module-info">
            <h3 class="module-name">{{ module.name }}</h3>
            <p class="module-desc">{{ module.description || '暂无描述' }}</p>
            <div class="module-stats">
              <span class="stat-item">
                <el-icon><Document /></el-icon>
                {{ module.caseCount || 0 }} 用例
              </span>
              <span class="stat-item">
                <el-icon><TrendCharts /></el-icon>
                {{ module.passRate || 0 }}% 通过
              </span>
            </div>
          </div>
          <div class="module-actions">
            <el-button type="primary" size="small" @click="executeModule(module.id)">
              执行
            </el-button>
            <el-button size="small" @click="showEditDialog(module)">
              编辑
            </el-button>
            <el-button size="small" @click="viewCases(module.id)">
              查看
            </el-button>
            <el-button type="danger" size="small" @click="deleteModule(module)">
              删除
            </el-button>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 创建/编辑弹窗 -->
    <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.module_type" style="width: 100%">
            <el-option label="标准模块" value="standard" />
            <el-option label="项目定制模块" value="custom" />
          </el-select>
        </el-form-item>
        <el-form-item label="父模块">
          <el-tree-select
            v-model="formData.parent_id"
            :data="parentModuleTreeData"
            :props="{ label: 'name', value: 'id', children: 'children' }"
            placeholder="选择父模块（可选）"
            clearable
            check-strictly
            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-item label="模块图标">
          <el-input v-model="formData.icon" placeholder="默认为 folder" />
        </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">
/**
 * 模块管理页面
 */

import { ref, computed, watch, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Refresh, Folder, Document, TrendCharts } from '@element-plus/icons-vue'
import type { Module, CreateModuleRequest, UpdateModuleRequest } from '@/types/module'
import { moduleApi, buildModuleTree } from '@/api/modules'

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

// ==================== 响应式数据 ====================
const loading = ref(false)
const modules = ref<Module[]>([])
const dialogVisible = ref(false)
const isEdit = ref(false)
const submitting = ref(false)
const editingId = ref('')

/** 当前模块类型（来自路由参数，默认 standard） */
const currentType = computed(() => (route.params.type as string) || 'standard')

/** 父模块树形数据（编辑时排除当前模块及其子模块，防循环引用） */
const parentModuleTreeData = computed(() => {
  if (!isEdit.value || !editingId.value) {
    return buildModuleTree(modules.value)
  }

  // 递归获取所有子模块ID
  const getChildIds = (parentId: string): string[] => {
    const children = modules.value.filter(m => m.parentId === parentId)
    return children.flatMap(c => [c.id, ...getChildIds(c.id)])
  }

  const excludeIds = new Set([editingId.value, ...getChildIds(editingId.value)])
  const filteredModules = modules.value.filter(m => !excludeIds.has(m.id))

  return buildModuleTree(filteredModules)
})

const formData = ref<CreateModuleRequest>({
  name: '',
  description: '',
  icon: 'folder',
  module_type: 'standard',
  parent_id: null
})

// ==================== 方法定义 ====================
/** 加载模块列表（按当前类型筛选） */
const loadModules = async () => {
  loading.value = true
  try {
    const response = await moduleApi.list(0, 100, currentType.value)
    modules.value = response.items
  } catch (error: any) {
    ElMessage.error('加载模块失败: ' + error.message)
  } finally {
    loading.value = false
  }
}

/** 显示创建弹窗 */
const showCreateDialog = () => {
  isEdit.value = false
  editingId.value = ''
  formData.value = { name: '', description: '', icon: 'folder', module_type: currentType.value, parent_id: null }
  dialogVisible.value = true
}

/** 显示编辑弹窗 */
const showEditDialog = (module: Module) => {
  isEdit.value = true
  editingId.value = module.id
  formData.value = {
    name: module.name,
    description: module.description,
    icon: module.icon,
    module_type: module.moduleType || 'standard',
    parent_id: module.parentId || null
  }
  dialogVisible.value = true
}

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

  submitting.value = true
  try {
    if (isEdit.value) {
      await moduleApi.update(editingId.value, formData.value as UpdateModuleRequest)
      ElMessage.success('模块更新成功')
    } else {
      await moduleApi.create(formData.value)
      ElMessage.success('模块创建成功')
    }
    dialogVisible.value = false
    await loadModules()
  } catch (error: any) {
    ElMessage.error('操作失败: ' + error.message)
  } finally {
    submitting.value = false
  }
}

/** 删除模块 */
const deleteModule = async (module: Module) => {
  try {
    await ElMessageBox.confirm(
      `确定要删除模块"${module.name}"吗？该操作将删除该模块下所有用例！`,
      '确认删除',
      { type: 'warning' }
    )

    await moduleApi.delete(module.id)
    ElMessage.success('模块删除成功')
    await loadModules()
  } catch (error: any) {
    if (error !== 'cancel') {
      ElMessage.error('删除失败: ' + error.message)
    }
  }
}

/** 执行模块测试 */
const executeModule = (moduleId: string) => {
  router.push(`/execution?moduleId=${moduleId}`)
}

/** 查看模块下的用例 */
const viewCases = (moduleId: string) => {
  router.push(`/cases?moduleId=${moduleId}`)
}

// ==================== 生命周期 ====================

// 路由类型变化时重新加载（切换标准/定制子菜单）
watch(currentType, () => {
  loadModules()
})

onMounted(() => {
  loadModules()
})
</script>

<style lang="scss" scoped>
.modules-page {
  .page-header {
    margin-bottom: 20px;
    display: flex;
    gap: 12px;
  }

  .module-card {
    margin-bottom: 20px;

    .module-icon {
      width: 56px;
      height: 56px;
      display: flex;
      align-items: center;
      justify-content: center;
      background: #f5f7fa;
      border-radius: 8px;
      margin-bottom: 12px;
    }

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

      .module-desc {
        margin: 0 0 12px;
        font-size: 13px;
        color: #909399;
      }

      .module-stats {
        display: flex;
        gap: 16px;
        font-size: 13px;
        color: #606266;

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

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