<!--
  组件名称：ApiPresetList.vue
  组件描述：API 接口预设列表页面，支持搜索、分页、新建、编辑、删除

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

<template>
  <div class="api-preset-list">
    <!-- 工具栏 -->
    <div class="toolbar">
      <el-button type="primary" @click="openCreateDialog">
        <el-icon><Plus /></el-icon>新建预设
      </el-button>
      <el-input
        v-model="keyword"
        placeholder="搜索预设名称…"
        clearable
        style="width: 240px"
        @input="onSearch"
      />
      <el-button @click="fetchData">
        <el-icon><Refresh /></el-icon>刷新
      </el-button>
    </div>

    <!-- 提示 -->
    <el-alert
      title="预设配置用于快速填充任务配置，修改或删除预设不影响已创建的任务。"
      type="info"
      :closable="false"
      show-icon
      style="margin-bottom: 16px"
    />

    <!-- 表格 -->
    <el-table :data="list" v-loading="loading" stripe style="width: 100%">
      <el-table-column prop="name" label="名称" min-width="180" show-overflow-tooltip />
      <el-table-column prop="method" label="方法" width="90" align="center">
        <template #default="{ row }">
          <el-tag :type="methodTagType(row.method)" size="small">{{ row.method }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="credentialName" label="凭据名称" width="150" show-overflow-tooltip>
        <template #default="{ row }">
          <span>{{ row.credentialName || '-' }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="targetUrl" label="目标 URL" min-width="300" show-overflow-tooltip />
      <el-table-column prop="description" label="描述" min-width="160" show-overflow-tooltip>
        <template #default="{ row }">
          <span class="text-muted">{{ row.description || '-' }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="updatedAt" label="更新时间" width="170">
        <template #default="{ row }">
          {{ row.updatedAt ? formatTime(row.updatedAt) : '-' }}
        </template>
      </el-table-column>
      <el-table-column label="操作" width="160" fixed="right">
        <template #default="{ row }">
          <el-button link type="primary" size="small" @click="openEditDialog(row)">编辑</el-button>
          <el-popconfirm
            title="确定删除该预设？"
            confirm-button-text="删除"
            @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-wrap">
      <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"
        @size-change="fetchData"
        @current-change="fetchData"
      />
    </div>

    <!-- 编辑弹窗 -->
    <ApiPresetDialog
      v-model="dialogVisible"
      :preset="editingPreset"
      @saved="onSaved"
    />
  </div>
</template>

<script setup lang="ts">
/**
 * API 接口预设列表页
 *
 * 功能：展示预设列表，支持搜索、分页、新建、编辑、删除
 */

import { ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { Plus, Refresh } from '@element-plus/icons-vue'
import { listPresets, deletePreset } from '@/api/performance'
import type { ApiPreset, ApiPresetListItem } from '@/types/performance'
import ApiPresetDialog from './ApiPresetDialog.vue'

// ==================== 响应式数据 ====================

const loading = ref(false)
const list = ref<ApiPresetListItem[]>([])
const total = ref(0)
const page = ref(1)
const pageSize = ref(20)
const keyword = ref('')
const dialogVisible = ref(false)
const editingPreset = ref<ApiPreset | null>(null)

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

onMounted(() => {
  fetchData()
})

// ==================== 方法 ====================

/** 获取预设列表 */
async function fetchData() {
  loading.value = true
  try {
    const res = await listPresets({
      page: page.value,
      pageSize: pageSize.value,
      keyword: keyword.value || undefined,
    })
    list.value = res.items || []
    total.value = res.total || 0
  } catch (e: any) {
    ElMessage.error('加载预设列表失败: ' + (e.message || ''))
  } finally {
    loading.value = false
  }
}

/** 搜索防抖 */
let searchTimer: ReturnType<typeof setTimeout> | null = null
function onSearch() {
  if (searchTimer) clearTimeout(searchTimer)
  searchTimer = setTimeout(() => {
    page.value = 1
    fetchData()
  }, 300)
}

/** 打开新建弹窗 */
function openCreateDialog() {
  editingPreset.value = null
  dialogVisible.value = true
}

/** 打开编辑弹窗 */
function openEditDialog(row: ApiPresetListItem) {
  // 编辑时需要完整数据，从已有列表项构造
  editingPreset.value = row as unknown as ApiPreset
  dialogVisible.value = true
}

/** 删除 */
async function handleDelete(row: ApiPresetListItem) {
  try {
    await deletePreset(row.id)
    ElMessage.success('预设已删除')
    fetchData()
  } catch (e: any) {
    ElMessage.error('删除失败: ' + (e.response?.data?.detail || e.message || ''))
  }
}

/** 保存成功后刷新 */
function onSaved() {
  page.value = 1
  fetchData()
}

/** 方法标签颜色 */
function methodTagType(method: string) {
  const map: Record<string, string> = {
    GET: 'success',
    POST: 'primary',
    PUT: 'warning',
    DELETE: 'danger',
  }
  return map[method] || 'info'
}

/** 格式化时间 */
function formatTime(ts: string) {
  if (!ts) return '-'
  try {
    const d = new Date(ts)
    const pad = (n: number) => String(n).padStart(2, '0')
    return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`
  } catch {
    return ts
  }
}
</script>

<style scoped>
.api-preset-list {
  padding: 0;
}

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

.pagination-wrap {
  display: flex;
  justify-content: flex-end;
  margin-top: 16px;
}

.text-muted {
  color: #999;
}
</style>