<template>
  <t-card title="" :bordered="false" header-bordered>
    <template #title><h2 style="margin:0;font-size:16px;">⚙️ AI 大模型配置管理</h2></template>

    <!-- F4: 健康状态汇总卡片 -->
    <div v-if="healthSummary" class="health-summary" style="display:flex;gap:12px;margin:12px 0;flex-wrap:wrap;">
      <div style="padding:10px 16px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;min-width:100px;text-align:center;">
        <div style="font-size:22px;font-weight:700;color:#16a34a;">{{ healthSummary.online }}</div>
        <div style="font-size:11px;color:#166534;">🟢 在线</div>
      </div>
      <div style="padding:10px 16px;background:#fef2f2;border:1px solid #fecaca;border-radius:8px;min-width:100px;text-align:center;">
        <div style="font-size:22px;font-weight:700;color:#dc2626;">{{ healthSummary.offline }}</div>
        <div style="font-size:11px;color:#991b1b;">🔴 离线</div>
      </div>
      <div v-if="healthSummary.unknown" style="padding:10px 16px;background:#fffbeb;border:1px solid #fde68a;border-radius:8px;min-width:100px;text-align:center;">
        <div style="font-size:22px;font-weight:700;color:#d97706;">{{ healthSummary.unknown }}</div>
        <div style="font-size:11px;color:#92400e;">🟡 未检测</div>
      </div>
      <div style="padding:10px 16px;background:#f9fafb;border:1px solid #e5e7eb;border-radius:8px;min-width:100px;text-align:center;">
        <div style="font-size:22px;font-weight:700;color:#374151;">{{ healthSummary.total }}</div>
        <div style="font-size:11px;color:#6b7280;">📊 总计</div>
      </div>
    </div>

    <!-- 筛选栏 + 操作按钮 -->
    <div class="toolbar">
      <t-select v-model="filterAppType" :options="appTypeOptions" style="max-width:200px;" size="small" @change="load(1)" />
      <t-button theme="primary" size="small" @click="openAddModal">➕ 新建配置</t-button>
      <t-button variant="outline" size="small" @click="exportConfigs">📤 导出</t-button>
      <t-button variant="outline" size="small" @click="showImportDialog = true">📥 导入</t-button>
      <t-button variant="outline" size="small" @click="load()">🔄 刷新</t-button>
    </div>

    <!-- F6: Fallback 链可视化 -->
    <div v-if="fallbackChains.length > 0" class="fallback-section">
      <div style="display:flex;align-items:center;gap:8px;margin-bottom:8px;">
        <span style="font-size:13px;font-weight:600;color:#1e40af;">🔗 Fallback 链（按优先级排列）</span>
        <t-tag size="small" variant="light" theme="primary" style="cursor:pointer;" @click="showFallbackHelp = !showFallbackHelp">❓ 帮助</t-tag>
      </div>
      <div v-if="showFallbackHelp" class="fallback-help">
        <div style="font-weight:600;color:#1e40af;margin-bottom:8px;">📖 Fallback 链使用说明</div>
        <p>Fallback 链是<span style="color:#059669;font-weight:600;">高可用性机制</span>，主模型故障时自动切换到备用模型。</p>
        <p>✔ 勾选「设为活跃配置」启用 | 📊 调整「优先级」数值（越大越优先）| 🔀 拖拽列表项快速调整</p>
      </div>
      <div v-for="chain in fallbackChains" :key="chain.appType" style="margin-bottom:8px;">
        <div style="font-size:12px;color:#1e40af;font-weight:600;">{{ getAppTypeLabel(chain.appType) }}</div>
        <div v-for="(item, idx) in chain.configs" :key="item.id"
          style="display:flex;align-items:center;gap:6px;padding:4px 8px;margin:2px 0;background:white;border-radius:4px;font-size:12px;cursor:grab;border:1px solid #e5e7eb;"
          draggable="true"
          @dragstart="onDragStart($event, item, chain)"
          @dragover.prevent
          @drop="onDrop($event, item, chain)">
          <span style="color:#6b7280;font-weight:600;">#{{ idx + 1 }}</span>
          <span v-if="idx < chain.configs.length - 1" style="color:#93c5fd;">↓</span>
          <span v-else style="color:#d1d5db;">·</span>
          <strong>{{ item.name }}</strong>
          <code style="font-size:11px;background:#f3f4f6;padding:1px 4px;border-radius:3px;">{{ item.model_name }}</code>
          <span style="color:#6b7280;">P={{ item.priority }}</span>
          <span v-if="healthMap[item.id]" :title="getHealthTooltip(item.id)"
            :style="{ color: healthMap[item.id].status === 'ONLINE' ? '#16a34a' : '#dc2626' }">
            {{ healthMap[item.id].status === 'ONLINE' ? '🟢' : healthMap[item.id].status === 'UNKNOWN' ? '🟡' : '🔴' }}
            <span v-if="healthMap[item.id].latencyMs" style="font-size:10px;">{{ healthMap[item.id].latencyMs }}ms</span>
          </span>
          <span v-else style="color:#d1d5db;" title="未检测">🟡</span>
        </div>
      </div>
    </div>

    <!-- 配置列表表格 -->
    <div style="overflow-x:auto;">
      <t-table :data="configs" :columns="tableColumns" row-key="id" :loading="tableLoading" hover stripe
        :pagination="{ current: currentPage, total: total, pageSize: pageSize, showJumper: true }"
        @page-change="onPageChange">
        <template #app_type="{ row }">
          <t-tag size="small" variant="light" theme="primary">{{ getAppTypeLabel(row.app_type) }}</t-tag>
        </template>
        <template #model_name="{ row }">
          <code style="font-size:12px;background:#f3f4f6;padding:2px 6px;border-radius:4px;">{{ row.model_name }}</code>
        </template>
        <template #base_url="{ row }">
          <span style="font-size:12px;color:#6b7280;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;" :title="row.base_url || getProviderBaseUrl(row.provider)">
            {{ row.base_url || getProviderBaseUrl(row.provider) || '-' }}
          </span>
        </template>
        <template #api_key="{ row }">
          <code style="font-size:12px;background:#f3f4f6;padding:2px 6px;border-radius:4px;">{{ row.api_key || '-' }}</code>
        </template>
        <template #status="{ row }">
          <t-tag size="small" :theme="row.is_active ? 'success' : 'default'" variant="light">
            {{ row.is_active ? '🟢 活跃' : '⚫ 未激活' }}
          </t-tag>
          <span v-if="row.is_active && healthMap[row.id]" :title="getHealthTooltip(row.id)"
            :style="{ cursor: 'help', color: healthMap[row.id].status === 'ONLINE' ? '#16a34a' : healthMap[row.id].status === 'UNKNOWN' ? '#d97706' : '#dc2626', marginLeft: '4px' }">
            {{ healthMap[row.id].status === 'ONLINE' ? '●' : '●' }}
          </span>
        </template>
        <template #op="{ row }">
          <t-space :size="4">
            <t-button size="small" variant="text" @click="openEditModal(row)" title="编辑">✏️</t-button>
            <t-button size="small" variant="text" @click="testConnection(row)" :disabled="testLoading[row.id]" title="测试连接">{{ testLoading[row.id] ? '⏳' : '🔌' }}</t-button>
            <t-button size="small" variant="text" @click="duplicateConfig(row)" title="复制">📋</t-button>
            <t-button v-if="!row.is_active" size="small" variant="text" theme="primary" @click="activate(row.id)" title="激活">▶️</t-button>
            <t-button v-if="row.is_active" size="small" variant="text" @click="deactivateConfig(row.id)" title="停用">⏸️</t-button>
            <t-button v-if="!row.is_active" size="small" variant="text" theme="danger" @click="remove(row.id, row.name)" title="删除">🗑️</t-button>
          </t-space>
        </template>
      </t-table>
    </div>

    <!-- F1: 测试结果提示 -->
    <div v-if="testResult.visible" class="test-result-toast"
      :style="{ position: 'fixed', bottom: '20px', right: '20px', padding: '12px 20px', borderRadius: '8px', zIndex: 9999, color: 'white', maxWidth: '400px', boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
        background: testResult.success ? '#16a34a' : '#dc2626' }">
      <div style="font-weight:600;">{{ testResult.success ? '✅ 连接成功' : '❌ 连接失败' }}</div>
      <div style="font-size:12px;margin-top:4px;">延迟：{{ testResult.latencyMs }}ms<span v-if="testResult.dimensions"> · 维度：{{ testResult.dimensions }}</span></div>
      <div v-if="testResult.errorMessage" style="font-size:11px;margin-top:4px;opacity:0.9;">{{ testResult.errorMessage }}</div>
    </div>

    <!-- ==================== 编辑/新建弹窗 ==================== -->
    <t-dialog
      v-model:visible="editModal.visible"
      :header="editModal.mode === 'add' ? '➕ 新建模型配置' : '✏️ 编辑模型配置'"
      width="720px"
      :footer="false"
      :close-on-overlay-click="false"
    >
      <div style="font-size:12px;color:#6b7280;margin-bottom:16px;">💡 核心三要素：API Key + API 地址 + 模型名称，填入即可使用</div>
      <t-form label-align="top">
        <!-- 应用类型 -->
        <t-form-item label="应用类型">
          <t-radio-group v-model="editModal.form.app_type" :disabled="editModal.mode === 'edit'">
            <t-radio-button v-for="tab in appTypeTabs" :key="tab.value" :value="tab.value">{{ tab.shortLabel }}</t-radio-button>
          </t-radio-group>
        </t-form-item>

        <!-- API Key -->
        <t-form-item label="🔑 API Key（必填）">
          <t-space style="width:100%;">
            <t-input v-model="editModal.form.api_key" :type="showApiKey ? 'text' : 'password'"
              :placeholder="editModal.mode === 'edit' ? '留空则保留原值不变' : '请输入 API Key'" style="flex:1;"
              @blur="onApiKeyFilled" />
            <t-button variant="outline" size="small" @click="showApiKey = !showApiKey">{{ showApiKey ? '🙈 隐藏' : '👁️ 显示' }}</t-button>
          </t-space>
          <template #help>
            <span v-if="editModal.mode === 'edit'" style="font-size:11px;color:#6b7280;">💡 API Key 已脱敏，留空保留原值</span>
          </template>
        </t-form-item>

        <!-- API 地址 -->
        <t-form-item label="🌐 API 地址">
          <t-input v-model="editModal.form.base_url" :placeholder="providerBaseUrlPlaceholder || '输入 API 地址'" @blur="onBaseUrlBlur" />
          <template #help>
            <t-space size="small" style="font-size:12px;margin-top:4px;align-items:center;">
              <span style="color:#6b7280;">快捷选择：</span>
              <t-select v-model="editModal.form.provider" :options="providerOptions" style="max-width:200px;" size="small" @change="onProviderChange" />
              <span v-if="providerTip" style="color:#3b82f6;">💡 {{ providerTip }}</span>
            </t-space>
          </template>
        </t-form-item>

        <!-- 模型名称 -->
        <t-form-item label="🤖 模型名称（必填）">
          <t-space style="width:100%;">
            <t-input v-model="editModal.form.model_name" placeholder="输入模型名称，或点击「获取模型」"
              style="flex:1;" @focus="onModelInputFocus" @input="onModelInputChange"
              @keydown.down.prevent="onDropdownKeyDown('down')" @keydown.up.prevent="onDropdownKeyDown('up')"
              @keydown.enter.prevent="onDropdownKeyDown('enter')" @keydown.escape="modelDropdownOpen = false">
              <template #suffix>
                <t-button v-if="editModal.form.model_name" variant="text" size="small"
                  @click="editModal.form.model_name = ''; modelDropdownOpen = false; updateNameSuggestion()" style="color:#9ca3af;">✕</t-button>
              </template>
            </t-input>
            <t-button variant="outline" size="small" @click="fetchModelsFromApi" :disabled="fetchLoading"
              style="border-color:var(--td-brand-color);color:var(--td-brand-color);white-space:nowrap;">
              {{ fetchLoading ? '⏳ 获取中...' : '🔍 获取模型' }}
            </t-button>
          </t-space>
          <!-- 自定义下拉列表 -->
          <div v-if="modelDropdownOpen && filteredModels.length > 0" class="model-dropdown"
            style="position:relative;top:100%;left:0;right:0;z-index:100;background:white;border:1px solid #d1d5db;border-radius:8px;max-height:240px;overflow-y:auto;margin-top:4px;box-shadow:0 4px 12px rgba(0,0,0,0.12);">
            <div v-for="(m, idx) in filteredModels" :key="m.id"
              @click="selectModel(m)" @mouseenter="modelDropdownHighlight = idx"
              :style="{ padding: '8px 12px', cursor: 'pointer', fontSize: '13px',
                borderBottom: idx < filteredModels.length - 1 ? '1px solid #f3f4f6' : 'none',
                background: idx === modelDropdownHighlight ? '#eff6ff' : 'white' }">
              <div style="font-weight:500;">{{ m.id }}</div>
              <div v-if="m.owned_by" style="font-size:11px;color:#6b7280;margin-top:1px;">{{ m.owned_by }}</div>
            </div>
          </div>
          <template #help>
            <div style="font-size:11px;color:#6b7280;margin-top:4px;">💡 填入 API Key 和地址后点击「获取模型」自动填充</div>
            <div v-if="fetchedModels.length > 0" style="font-size:11px;color:#16a34a;margin-top:2px;">✅ 已获取 {{ fetchedModels.length }} 个模型</div>
          </template>
        </t-form-item>

        <!-- 高级参数（折叠） -->
        <t-form-item>
          <t-collapse v-model="advancedCollapse">
            <t-collapse-panel header="⚡ 高级参数" value="advanced">
              <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;">
                <t-form-item label="温度 (Temperature)">
                  <t-input-number v-model="editModal.form.temperature" :min="0" :max="2" :step="0.1" placeholder="0.7" style="width:100%;" />
                </t-form-item>
                <t-form-item label="最大 Token 数">
                  <t-input-number v-model="editModal.form.max_tokens" :min="1" :max="128000" placeholder="2000" style="width:100%;" />
                </t-form-item>
                <t-form-item label="Top P">
                  <t-input-number v-model="editModal.form.topP" :min="0" :max="1" :step="0.01" placeholder="不设置" style="width:100%;" />
                </t-form-item>
                <t-form-item label="Top K">
                  <t-input-number v-model="editModal.form.topK" :min="1" :max="100" placeholder="不限制" style="width:100%;" />
                </t-form-item>
                <t-form-item label="频率惩罚">
                  <t-input-number v-model="editModal.form.frequencyPenalty" :min="-2" :max="2" :step="0.1" placeholder="0" style="width:100%;" />
                </t-form-item>
                <t-form-item label="存在惩罚">
                  <t-input-number v-model="editModal.form.presencePenalty" :min="-2" :max="2" :step="0.1" placeholder="0" style="width:100%;" />
                </t-form-item>
                <t-form-item label="停止词（逗号分隔）" style="grid-column:1/-1;">
                  <t-input v-model="editModal.form.stopSequences" placeholder="如：END,STOP" />
                </t-form-item>
              </div>
            </t-collapse-panel>
          </t-collapse>
        </t-form-item>

        <!-- 向量维度（仅 EMBEDDING） -->
        <t-form-item v-if="editModal.form.app_type === 'EMBEDDING'" label="📐 向量维度（必填）">
          <t-input-number v-model="editModal.form.embeddingDimensions" :min="1" :max="8192" placeholder="1024" style="max-width:240px;" />
          <template #help>
            <span style="font-size:11px;color:#d97706;">⚠️ 修改维度后需重建向量表</span>
          </template>
        </t-form-item>

        <!-- 配置名称 -->
        <t-form-item label="📝 配置名称（必填）">
          <t-input v-model="editModal.form.name" :placeholder="nameSuggestion || '如：生产环境-DeepSeek对话'" />
          <template #help>
            <span v-if="nameSuggestion && !editModal.form.name" style="font-size:11px;color:#3b82f6;">
              💡 建议：<a @click.prevent="editModal.form.name = nameSuggestion" style="color:var(--td-brand-color);cursor:pointer;text-decoration:underline;">{{ nameSuggestion }}</a>
            </span>
          </template>
        </t-form-item>

        <!-- 优先级 + 激活 -->
        <t-row :gutter="16">
          <t-col :span="6">
            <t-form-item label="优先级">
              <t-input-number v-model="editModal.form.priority" :min="0" placeholder="0（越大越优先）" style="width:100%;" />
            </t-form-item>
          </t-col>
          <t-col :span="6">
            <t-form-item label=" ">
              <t-checkbox v-model="editModal.form.is_active">设为活跃配置（同类型支持多个按优先级 Fallback）</t-checkbox>
            </t-form-item>
          </t-col>
        </t-row>

        <!-- 描述 -->
        <t-form-item label="描述说明">
          <t-textarea v-model="editModal.form.description" :autosize="{ minRows: 2, maxRows: 4 }" placeholder="可选，填写配置用途说明" />
        </t-form-item>
      </t-form>

      <!-- 按钮 -->
      <div class="dialog-footer" style="gap:10px;margin-top:20px;">
        <t-button variant="outline" @click="editModal.visible = false">取消</t-button>
        <t-button v-if="editModal.mode === 'edit'" variant="outline" @click="testConnectionById(editModal.editId!)"
          :disabled="testLoading[editModal.editId!]" style="border-color:var(--td-brand-color);color:var(--td-brand-color);">
          {{ testLoading[editModal.editId!] ? '⏳ 测试中...' : '🔌 测试连接' }}
        </t-button>
        <t-button theme="primary" @click="saveConfig">💾 保存</t-button>
      </div>
    </t-dialog>

    <!-- F7: 导入弹窗 -->
    <t-dialog v-model:visible="showImportDialog" header="📥 导入模型配置" width="600px" :footer="false">
      <t-upload :auto-upload="false" theme="file" accept=".json" @change="onImportFileSelect" />
      <div v-if="importPreview" style="margin:12px 0;padding:12px;background:#f9fafb;border-radius:8px;">
        <div style="font-size:13px;font-weight:600;margin-bottom:8px;">导入预览</div>
        <div style="font-size:12px;">共 {{ importPreview.configs.length }} 条配置</div>
        <div v-for="c in importPreview.configs.slice(0, 5)" :key="c.name" style="font-size:11px;color:#6b7280;margin:2px 0;">
          · {{ c.name }} ({{ c.appType || c.app_type }}) - {{ c.modelName || c.model_name }}
        </div>
      </div>
      <t-form-item label="冲突策略">
        <t-select v-model="importConflict" :options="importConflictOptions" style="max-width:300px;" />
      </t-form-item>
      <div v-if="importResult" style="margin:12px 0;padding:12px;border-radius:8px;"
        :style="{ background: importResult.errors?.length ? '#fef2f2' : '#f0fdf4' }">
        <div style="font-size:13px;font-weight:600;">导入完成</div>
        <div style="font-size:12px;margin-top:4px;">新增 {{ importResult.added }} · 覆盖 {{ importResult.overwritten }} · 跳过 {{ importResult.skipped }}</div>
      </div>
      <div class="dialog-footer" style="gap:10px;margin-top:20px;">
        <t-button variant="outline" @click="closeImportDialog">关闭</t-button>
        <t-button theme="primary" @click="doImport" :disabled="!importPreview">📥 确认导入</t-button>
      </div>
    </t-dialog>
  </t-card>
</template>

<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted, onUnmounted } from 'vue'
import { MessagePlugin } from 'tdesign-vue-next'
import * as api from '@/api/model-config'
import { toast } from '@/utils/toast'
import { useConfirm } from '@/composables/useConfirm'

const { confirm } = useConfirm()

// ==================== 常量 ====================
const appTypeOptions = [
  { label: '全部类型', value: '' },
  { label: '💬 智能客服对话', value: 'CHAT' },
  { label: '📐 文本向量化', value: 'EMBEDDING' },
  { label: '🔄 RAG查询重写', value: 'RAG_REWRITE' },
  { label: '📊 重排序', value: 'RERANK' },
]

const appTypeTabs = [
  { value: 'CHAT', label: '💬 对话', shortLabel: '对话' },
  { value: 'EMBEDDING', label: '📐 向量化', shortLabel: '向量化' },
  { value: 'RAG_REWRITE', label: '🔄 RAG重写', shortLabel: 'RAG重写' },
  { value: 'RERANK', label: '📊 重排序', shortLabel: '重排序' },
]

const providerOptions = [
  { label: '手动填写地址', value: '' },
  { label: '通义千问 (DashScope)', value: 'dashscope' },
  { label: 'DeepSeek (深度求索)', value: 'deepseek' },
  { label: '豆包 (字节跳动)', value: 'volcengine' },
  { label: 'Kimi (月之暗面)', value: 'moonshot' },
  { label: '智谱 AI (GLM)', value: 'zhipu' },
  { label: 'OpenAI', value: 'openai' },
]

const PROVIDER_BASE_URLS: Record<string, string> = {
  dashscope: 'https://dashscope.aliyuncs.com/compatible-mode',
  deepseek: 'https://api.deepseek.com',
  volcengine: 'https://ark.cn-beijing.volces.com/api/v3',
  moonshot: 'https://api.moonshot.cn/v1',
  zhipu: 'https://open.bigmodel.cn/api/paas/v4',
  openai: 'https://api.openai.com',
}

const PROVIDER_TIPS: Record<string, string> = {
  dashscope: '通义千问团队版/私有化部署需填写专属 Base URL，公共版可留空',
  volcengine: '模型名称可在火山引擎 ARK 控制台获取',
}

const importConflictOptions = [
  { label: '跳过同名配置', value: 'skip' },
  { label: '覆盖同名配置', value: 'overwrite' },
]

// ==================== 表格列定义 ====================
const tableColumns = [
  { colKey: 'name', title: '配置名称', width: 160 },
  { colKey: 'app_type', title: '应用类型', width: 100 },
  { colKey: 'model_name', title: '模型名称', width: 160 },
  { colKey: 'base_url', title: 'API 地址', width: 180 },
  { colKey: 'api_key', title: 'API Key', width: 180 },
  { colKey: 'status', title: '状态', width: 120 },
  { colKey: 'op', title: '操作', width: 240 },
]

// ==================== 状态 ====================
const configs = ref<any[]>([])
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)
const tableLoading = ref(false)
const filterAppType = ref('')
const showApiKey = ref(false)

// 模型下拉框
const fetchedModels = ref<any[]>([])
const fetchLoading = ref(false)
const modelDropdownOpen = ref(false)
const modelDropdownHighlight = ref(-1)
const providerTip = ref('')
const providerBaseUrlPlaceholder = ref('')
const nameSuggestion = ref('')
const advancedCollapse = ref<string[]>([])

const filteredModels = computed(() => {
  const query = (editModal.value.form.model_name || '').trim().toLowerCase()
  if (!query) return fetchedModels.value
  return fetchedModels.value.filter((m: any) =>
    m.id.toLowerCase().includes(query) || (m.owned_by && m.owned_by.toLowerCase().includes(query)))
})

// 健康状态
const healthMap = ref<Record<string, any>>({})
const healthSummary = ref<any>(null)
let healthTimer: any = null

// 测试
const testLoading = ref<Record<string, boolean>>({})
const testResult = reactive({ visible: false, success: false, latencyMs: 0, dimensions: null as any, errorMessage: null as any })
let testResultTimer: any = null

// Fallback 链
const fallbackChains = ref<any[]>([])
const showFallbackHelp = ref(false)

// 导入
const showImportDialog = ref(false)
const importPreview = ref<any>(null)
const importConflict = ref('skip')
const importResult = ref<any>(null)

// 编辑弹窗
const editModal = ref<any>({
  visible: false,
  mode: 'add',
  editId: null,
  form: createEmptyForm(),
})

function createEmptyForm() {
  return {
    name: '', app_type: 'CHAT', provider: '', api_key: '', model_name: '',
    temperature: 0.7, max_tokens: 2000, base_url: '', embeddingDimensions: 1024,
    topP: null, topK: null, frequencyPenalty: null, presencePenalty: null, stopSequences: '',
    priority: 0, is_active: false, description: '',
  }
}

// ==================== 提供商切换 ====================
function onProviderChange() {
  const p = editModal.value.form.provider
  if (!p) { editModal.value.form.base_url = ''; providerTip.value = ''; providerBaseUrlPlaceholder.value = '输入自定义 API 地址'; fetchedModels.value = []; updateNameSuggestion(); return }
  editModal.value.form.base_url = PROVIDER_BASE_URLS[p] || ''
  providerBaseUrlPlaceholder.value = PROVIDER_BASE_URLS[p] || ''
  providerTip.value = PROVIDER_TIPS[p] || ''
  fetchedModels.value = []
  updateNameSuggestion()
}

function onBaseUrlBlur() {
  const url = editModal.value.form.base_url
  if (!url || editModal.value.form.provider) return
  for (const [p, du] of Object.entries(PROVIDER_BASE_URLS)) {
    if (url.startsWith(du) || du.startsWith(url)) {
      editModal.value.form.provider = p
      providerTip.value = PROVIDER_TIPS[p] || ''
      break
    }
  }
}

function onApiKeyFilled() { /* UI 提示 */ }

// ==================== 模型下拉框 ====================
function onModelInputFocus() { if (fetchedModels.value.length > 0) { modelDropdownOpen.value = true; modelDropdownHighlight.value = -1 } }
function onModelInputChange() { if (fetchedModels.value.length > 0) { modelDropdownOpen.value = true; modelDropdownHighlight.value = -1 } }

function onDropdownKeyDown(dir: string) {
  if (!modelDropdownOpen.value || filteredModels.value.length === 0) {
    if (fetchedModels.value.length > 0) { modelDropdownOpen.value = true; modelDropdownHighlight.value = 0 }
    return
  }
  if (dir === 'down') modelDropdownHighlight.value = Math.min(modelDropdownHighlight.value + 1, filteredModels.value.length - 1)
  else if (dir === 'up') modelDropdownHighlight.value = Math.max(modelDropdownHighlight.value - 1, 0)
  else if (dir === 'enter') {
    if (modelDropdownHighlight.value >= 0 && modelDropdownHighlight.value < filteredModels.value.length)
      selectModel(filteredModels.value[modelDropdownHighlight.value])
    else modelDropdownOpen.value = false
  }
}

function selectModel(m: any) { editModal.value.form.model_name = m.id; modelDropdownOpen.value = false; modelDropdownHighlight.value = -1; updateNameSuggestion() }

function onDocumentClick(e: Event) {
  const el = e.target as HTMLElement
  if (el.closest?.('.model-dropdown') || el.closest?.('.t-input')) return
  modelDropdownOpen.value = false
}

// ==================== 获取模型列表 ====================
async function fetchModelsFromApi() {
  const form = editModal.value.form
  if (!form.api_key?.trim()) { toast('请先填写 API Key', 'error'); return }
  if (!form.base_url?.trim()) {
    if (form.provider && PROVIDER_BASE_URLS[form.provider]) form.base_url = PROVIDER_BASE_URLS[form.provider]
    else { toast('请填写 API 地址', 'error'); return }
  }
  fetchLoading.value = true
  try {
    const json = await api.fetchModels(form.base_url, form.api_key, form.provider)
    if (json.success && json.data) {
      fetchedModels.value = json.data
      toast('已获取 ' + json.data.length + ' 个模型', 'success')
      modelDropdownOpen.value = true; modelDropdownHighlight.value = 0
    } else { toast(json.message || '获取失败', 'error'); fetchedModels.value = [] }
  } catch (e: any) { toast('获取失败：' + e.message, 'error'); fetchedModels.value = [] }
  finally { fetchLoading.value = false }
}

function updateNameSuggestion() {
  const f = editModal.value.form
  if (f.name) { nameSuggestion.value = ''; return }
  const pl = getProviderLabel(f.provider)
  if (f.model_name?.trim()) nameSuggestion.value = (pl || '自定义') + '-' + f.model_name.trim()
  else nameSuggestion.value = ''
}

watch(() => editModal.value.form.model_name, updateNameSuggestion)
watch(() => editModal.value.form.provider, updateNameSuggestion)

// ==================== 数据加载 ====================
async function load(p = currentPage.value) {
  tableLoading.value = true
  currentPage.value = p
  try {
    const json = await api.listModelConfigs(p, pageSize.value, filterAppType.value || undefined)
    if (json.success) {
      configs.value = json.data || []
      total.value = json.total || 0
      loadHealthStatus(); buildFallbackChains()
    } else toast(json.message || '查询失败', 'error')
  } catch (e: any) { toast('加载失败：' + e.message, 'error') }
  finally { tableLoading.value = false }
}

function onPageChange(pageInfo: { current: number; pageSize: number }) { pageSize.value = pageInfo.pageSize; load(pageInfo.current) }

// ==================== 健康状态 ====================
async function loadHealthStatus() {
  try {
    const json = await api.getHealthStatus()
    if (json.success && json.data) {
      const data = { ...json.data }
      healthSummary.value = data._summary || null
      delete data._summary
      healthMap.value = data
    }
  } catch { /* 静默失败 */ }
}

function getHealthTooltip(cid: string) {
  const h = healthMap.value[cid]
  if (!h) return '未检测'
  let t = h.status === 'ONLINE' ? '在线' : h.status === 'UNKNOWN' ? '未支持自动检测' : '离线'
  if (h.latencyMs) t += ' · ' + h.latencyMs + 'ms'
  return t
}

// ==================== Fallback 链 ====================
function buildFallbackChains() {
  const chains = []
  for (const at of ['CHAT', 'EMBEDDING', 'RAG_REWRITE', 'RERANK']) {
    const ac = configs.value.filter((c: any) => c.app_type === at && c.is_active).sort((a: any, b: any) => (b.priority || 0) - (a.priority || 0))
    if (ac.length > 0) chains.push({ appType: at, configs: ac })
  }
  fallbackChains.value = chains
}

let dragItem: any = null; let dragChain: any = null
function onDragStart(e: DragEvent, item: any, chain: any) { dragItem = item; dragChain = chain; e.dataTransfer!.effectAllowed = 'move' }
async function onDrop(e: DragEvent, target: any) {
  if (!dragItem || dragItem.id === target.id) return
  try {
    await api.updateModelConfigPriority(dragItem.id, target.priority || 0)
    await api.updateModelConfigPriority(target.id, dragItem.priority || 0)
    toast('优先级已调整', 'success')
    load()
  } catch (e: any) { toast('调整失败：' + e.message, 'error') }
  dragItem = null; dragChain = null
}

// ==================== 弹窗 ====================
function openAddModal() {
  editModal.value = { visible: true, mode: 'add', editId: null, form: createEmptyForm() }
  showApiKey.value = false; advancedCollapse.value = []
  fetchedModels.value = []; providerTip.value = ''; providerBaseUrlPlaceholder.value = ''; nameSuggestion.value = ''
  modelDropdownOpen.value = false; modelDropdownHighlight.value = -1
}

function openEditModal(config: any) {
  let extra: any = {}
  const raw = config.extra_config || config.extraConfig
  if (raw) { try { extra = typeof raw === 'string' ? JSON.parse(raw) : raw } catch { } }
  editModal.value = {
    visible: true, mode: 'edit', editId: config.id,
    form: {
      name: config.name || '', app_type: config.app_type || 'CHAT', provider: config.provider || '',
      api_key: '', model_name: config.model_name || '', temperature: config.temperature, max_tokens: config.max_tokens,
      base_url: config.base_url || '', embeddingDimensions: extra.dimensions || 1024,
      topP: extra.topP ?? null, topK: extra.topK ?? null,
      frequencyPenalty: extra.frequencyPenalty ?? null, presencePenalty: extra.presencePenalty ?? null,
      stopSequences: extra.stopSequences || '', priority: config.priority || 0,
      is_active: config.is_active || false, description: config.description || '',
    },
  }
  showApiKey.value = false; advancedCollapse.value = []
  fetchedModels.value = []; nameSuggestion.value = ''
  modelDropdownOpen.value = false; modelDropdownHighlight.value = -1
  if (config.provider && PROVIDER_BASE_URLS[config.provider]) { providerBaseUrlPlaceholder.value = PROVIDER_BASE_URLS[config.provider]; providerTip.value = PROVIDER_TIPS[config.provider] || '' }
  else { providerBaseUrlPlaceholder.value = ''; providerTip.value = '' }
}

// ==================== 保存 ====================
function toCamelCase(form: any) {
  const data: any = { name: form.name, appType: form.app_type, provider: form.provider || 'other', apiKey: form.api_key, modelName: form.model_name, temperature: form.temperature, maxTokens: form.max_tokens, baseUrl: form.base_url, priority: form.priority, isActive: form.is_active, description: form.description }
  const extraConfig: any = {}
  if (form.app_type === 'EMBEDDING') extraConfig.dimensions = form.embeddingDimensions || 1024
  if (form.topP != null) extraConfig.topP = form.topP
  if (form.topK != null) extraConfig.topK = form.topK
  if (form.frequencyPenalty != null) extraConfig.frequencyPenalty = form.frequencyPenalty
  if (form.presencePenalty != null) extraConfig.presencePenalty = form.presencePenalty
  if (form.stopSequences?.trim()) extraConfig.stopSequences = form.stopSequences.trim()
  data.extraConfig = extraConfig
  return data
}

async function saveConfig() {
  const form = editModal.value.form
  if (!form.name?.trim()) { toast('请填写配置名称', 'error'); return }
  if (!form.api_key?.trim() && editModal.value.mode === 'add') { toast('请填写 API Key', 'error'); return }
  if (!form.model_name?.trim()) { toast('请填写模型名称', 'error'); return }
  if (!form.provider) form.provider = 'other'
  try {
    const data = toCamelCase(form)
    let json
    if (editModal.value.mode === 'add') json = await api.createModelConfig(data)
    else { if (!data.apiKey?.trim()) delete data.apiKey; json = await api.updateModelConfig(editModal.value.editId, data) }
    if (json.success) { toast(editModal.value.mode === 'add' ? '配置创建成功' : '配置更新成功', 'success'); editModal.value.visible = false; load() }
    else toast(json.message || '操作失败', 'error')
  } catch (e: any) { toast('保存失败：' + e.message, 'error') }
}

// ==================== 测试连接 ====================
async function testConnection(config: any) {
  testLoading.value = { ...testLoading.value, [config.id]: true }
  try { showTestResult(await api.testModelConfig(config.id)) } catch (e: any) { showTestResult({ success: false, errorMessage: e.message, latencyMs: 0 }) }
  finally { testLoading.value = { ...testLoading.value, [config.id]: false } }
}

async function testConnectionById(id: string) {
  testLoading.value = { ...testLoading.value, [id]: true }
  try { showTestResult(await api.testModelConfig(id)) } catch (e: any) { showTestResult({ success: false, errorMessage: e.message, latencyMs: 0 }) }
  finally { testLoading.value = { ...testLoading.value, [id]: false } }
}

function showTestResult(r: any) {
  if (testResultTimer) clearTimeout(testResultTimer)
  testResult.visible = true; testResult.success = r.success; testResult.latencyMs = r.latencyMs || 0; testResult.dimensions = r.dimensions || null; testResult.errorMessage = r.errorMessage || r.message || null
  testResultTimer = setTimeout(() => { testResult.visible = false }, 5000)
}

// ==================== 复制/激活/停用/删除 ====================
async function duplicateConfig(c: any) {
  if (!await confirm(`确定复制配置「${c.name || c.id}」？`)) return
  try { const j = await api.duplicateModelConfig(c.id); if (j.success) { toast('配置复制成功', 'success'); load() } else toast(j.message || '复制失败', 'error') }
  catch (e: any) { toast('复制失败：' + e.message, 'error') }
}

async function activate(id: string) {
  if (!await confirm('确定激活此配置？')) return
  try { const j = await api.activateModelConfig(id); if (j.success) { toast('配置已激活', 'success'); load() } else toast(j.message || '激活失败', 'error') }
  catch (e: any) { toast('激活失败：' + e.message, 'error') }
}

async function deactivateConfig(id: string) {
  if (!await confirm('确定停用此配置？')) return
  try { const j = await api.deactivateModelConfig(id); if (j.success) { toast('配置已停用', 'success'); load() } else toast(j.message || '停用失败', 'error') }
  catch (e: any) { toast('停用失败：' + e.message, 'error') }
}

async function remove(id: string, name: string) {
  if (!await confirm(`确定删除「${name || id}」？`)) return
  try { const j = await api.deleteModelConfig(id); if (j.success) { toast('已删除', 'success'); load() } else toast(j.message || '删除失败', 'error') }
  catch (e: any) { toast('删除失败：' + e.message, 'error') }
}

// ==================== 导入/导出 ====================
async function exportConfigs() {
  try {
    const j = await api.exportModelConfigs()
    if (j.success) { const blob = new Blob([JSON.stringify(j.data, null, 2)], { type: 'application/json' }); const u = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = u; a.download = 'model-configs-' + new Date().toISOString().slice(0, 10) + '.json'; a.click(); URL.revokeObjectURL(u); toast('导出成功', 'success') }
    else toast(j.message || '导出失败', 'error')
  } catch (e: any) { toast('导出失败：' + e.message, 'error') }
}

function onImportFileSelect(file: any) {
  if (!file?.raw) return
  const reader = new FileReader()
  reader.onload = (ev: any) => {
    try { let d = JSON.parse(ev.target.result); if (!Array.isArray(d) && d.data) d = d.data; if (!Array.isArray(d)) { toast('JSON 格式不正确', 'error'); return }; importPreview.value = { configs: d }; importResult.value = null }
    catch (e: any) { toast('文件解析失败：' + e.message, 'error') }
  }
  reader.readAsText(file.raw)
}

async function doImport() {
  if (!importPreview.value) return
  try { const j = await api.importModelConfigs(importPreview.value.configs, importConflict.value); if (j.success) { importResult.value = j.data; toast('导入完成', 'success'); load() } else toast(j.message || '导入失败', 'error') }
  catch (e: any) { toast('导入失败：' + e.message, 'error') }
}

function closeImportDialog() { showImportDialog.value = false; importPreview.value = null; importResult.value = null }

// ==================== 工具函数 ====================
function getAppTypeLabel(t: string) { const m: Record<string, string> = { CHAT: '💬 对话', EMBEDDING: '📐 向量化', RAG_REWRITE: '🔄 RAG重写', RERANK: '📊 重排序' }; return m[t] || t }
function getProviderLabel(p: string) { const f = providerOptions.find(o => o.value === p); return f ? f.label : p }
function getProviderBaseUrl(p: string) { return PROVIDER_BASE_URLS[p] || '' }

// ==================== 生命周期 ====================
onMounted(() => { load(); healthTimer = setInterval(loadHealthStatus, 30000); document.addEventListener('click', onDocumentClick, true) })
onUnmounted(() => { clearInterval(healthTimer); clearTimeout(testResultTimer); document.removeEventListener('click', onDocumentClick, true) })
</script>

<style scoped>
.fallback-section { margin:12px 0; padding:12px; background:#eff6ff; border:1px solid #bfdbfe; border-radius:8px; }
.fallback-help { margin-bottom:12px; padding:12px; background:white; border:1px solid #93c5fd; border-radius:6px; font-size:12px; line-height:1.6; color:#374151; }
.fallback-help p { margin:4px 0; }
</style>
