<script setup>
import { ref, reactive, onMounted } from 'vue'
import {
  NIcon, NDataTable, NForm, NFormItem, NInput,
  NInputNumber, NSwitch, NSpace, NTag, NSelect, NButton, NTooltip,
  useMessage
} from 'naive-ui'
import { h } from 'vue'
import { AddOutline, ReloadOutline, SettingsOutline, FlashOutline, TrashOutline, StarOutline, Star, CloseOutline, ArrowUpOutline, ArrowDownOutline, CreateOutline, CopyOutline } from '@vicons/ionicons5'
import {
  getModelList, createModel, updateModel, deleteModel, setDefaultModel, duplicateModel,
  testModelConnection, testConnection, fetchAvailableModels, updateModelPriorities
} from '../api/model'
import { useConfirmDelete } from '../composables/useConfirmDelete'

const message = useMessage()
const confirmDelete = useConfirmDelete()

const loading = ref(false)
const models = ref([])
const showModal = ref(false)
const editingId = ref(null)
const saving = ref(false)
const testingId = ref(null)
const testingInModal = ref(false)
const testResult = ref(null)
const fetchingModels = ref(false)
const availableModels = ref([])

const form = reactive({
  name: '',
  baseUrl: '',
  completionsPath: '/chat/completions',
  apiKey: '',
  modelName: '',
  temperature: 0.3,
  isDefault: false
})

// 表格列定义
const columns = [
  { title: '名称', key: 'name', width: 130 },
  {
    title: '模型标识', key: 'modelName', width: 130,
    render: (row) => h('span', { style: 'font-family: monospace; font-size: 13px' }, row.modelName)
  },
  { title: '接口地址', key: 'baseUrl', ellipsis: { tooltip: true } },
  { title: 'API Key', key: 'apiKey', width: 150 },
  { title: '温度', key: 'temperature', width: 70, render: (row) => row.temperature?.toFixed(1) },
  {
    title: '状态', key: 'isDefault', width: 90,
    render: (row) => row.isDefault
      ? h(NTag, { type: 'success', size: 'small' }, { default: () => '默认' })
      : h(NTag, { size: 'small' }, { default: () => '-' })
  },
  {
    title: '调用顺序', key: 'priority', width: 100,
    render: (row, index) => {
      const isFirst = index === 0
      const isLast = index === models.value.length - 1
      return h(NSpace, { size: 4, align: 'center' }, {
        default: () => [
          h('span', { style: 'font-size: 12px; color: var(--text-secondary); min-width: 16px; text-align: center' }, `${index + 1}`),
          h('button', {
            class: 'order-btn',
            disabled: isFirst,
            onClick: () => handleMoveUp(index)
          }, [h(NIcon, { size: 14 }, { default: () => h(ArrowUpOutline) })]),
          h('button', {
            class: 'order-btn',
            disabled: isLast,
            onClick: () => handleMoveDown(index)
          }, [h(NIcon, { size: 14 }, { default: () => h(ArrowDownOutline) })])
        ]
      })
    }
  },
  {
    title: '操作', key: 'actions', width: 180,
    render: (row) => h(NSpace, { size: 2, align: 'center', wrap: false }, {
      default: () => [
        h(NTooltip, null, {
          trigger: () => h(NButton, {
            size: 'tiny', quaternary: true, circle: true, type: 'info',
            loading: testingId.value === row.id,
            onClick: () => handleTestRow(row)
          }, { icon: () => h(NIcon, { size: 16 }, { default: () => h(FlashOutline) }) }),
          default: () => '测试连接'
        }),
        !row.isDefault && h(NTooltip, null, {
          trigger: () => h(NButton, {
            size: 'tiny', quaternary: true, circle: true, type: 'warning',
            onClick: () => handleSetDefault(row)
          }, { icon: () => h(NIcon, { size: 16 }, { default: () => h(StarOutline) }) }),
          default: () => '设为默认'
        }),
        h(NTooltip, null, {
          trigger: () => h(NButton, {
            size: 'tiny', quaternary: true, circle: true,
            onClick: () => handleEdit(row)
          }, { icon: () => h(NIcon, { size: 16 }, { default: () => h(CreateOutline) }) }),
          default: () => '编辑'
        }),
        h(NTooltip, null, {
          trigger: () => h(NButton, {
            size: 'tiny', quaternary: true, circle: true,
            onClick: () => handleDuplicate(row)
          }, { icon: () => h(NIcon, { size: 16 }, { default: () => h(CopyOutline) }) }),
          default: () => '复制'
        }),
        h(NTooltip, null, {
          trigger: () => h(NButton, {
            size: 'tiny', quaternary: true, circle: true, type: 'error',
            onClick: () => confirmDelete({
              name: row.name,
              itemType: '模型',
              onConfirm: async () => {
                try {
                  await deleteModel(row.id)
                  message.success('删除成功')
                  fetchModels()
                } catch (e) {
                  message.error('删除失败')
                }
              },
            })
          }, { icon: () => h(NIcon, { size: 16 }, { default: () => h(TrashOutline) }) }),
          default: () => '删除'
        })
      ]
    })
  }
]

onMounted(fetchModels)

async function fetchModels() {
  loading.value = true
  try {
    const res = await getModelList()
    models.value = res.data || []
  } catch (e) {
    message.error('加载模型列表失败')
  } finally {
    loading.value = false
  }
}

function openCreate() {
  editingId.value = null
  Object.assign(form, { name: '', baseUrl: '', completionsPath: '/chat/completions', apiKey: '', modelName: '', temperature: 0.3, isDefault: false })
  testResult.value = null
  availableModels.value = []
  showModal.value = true
}

function handleEdit(row) {
  editingId.value = row.id
  Object.assign(form, {
    name: row.name,
    baseUrl: row.baseUrl,
    completionsPath: row.completionsPath || '/chat/completions',
    apiKey: '',
    modelName: row.modelName,
    temperature: row.temperature,
    isDefault: row.isDefault
  })
  testResult.value = null
  availableModels.value = []
  showModal.value = true
}

async function handleSave() {
  if (!form.name || !form.baseUrl || !form.modelName) {
    message.warning('请填写必填字段')
    return
  }
  if (!editingId.value && !form.apiKey) {
    message.warning('请填写 API Key')
    return
  }

  saving.value = true
  try {
    if (editingId.value) {
      await updateModel(editingId.value, form)
      message.success('更新成功')
    } else {
      await createModel(form)
      message.success('创建成功')
    }
    showModal.value = false
    await fetchModels()
  } catch (e) {
    message.error(e.response?.data?.message || '操作失败')
  } finally {
    saving.value = false
  }
}

async function handleSetDefault(row) {
  try {
    await setDefaultModel(row.id)
    message.success(`已将「${row.name}」设为默认模型`)
    await fetchModels()
  } catch (e) {
    message.error('设置失败')
  }
}

async function handleDuplicate(row) {
  try {
    await duplicateModel(row.id)
    message.success(`已复制「${row.name}」`)
    await fetchModels()
  } catch (e) {
    message.error(e.response?.data?.message || '复制失败')
  }
}

// 测试表格中已保存模型的连接
async function handleTestRow(row) {
  testingId.value = row.id
  try {
    const res = await testModelConnection(row.id)
    const data = res.data
    if (data.success) {
      message.success(`连接成功 · ${data.latencyMs}ms`, { duration: 5000 })
    } else {
      message.error(`连接失败 · ${data.error}`, { duration: 8000 })
    }
  } catch (e) {
    message.error('测试请求失败')
  } finally {
    testingId.value = null
  }
}

// 在弹窗中测试连接（支持未保存的配置）
async function handleTestInModal() {
  if (!form.baseUrl || !form.modelName) {
    message.warning('请先填写接口地址和模型标识')
    return
  }
  if (!editingId.value && !form.apiKey) {
    message.warning('请先填写 API Key')
    return
  }

  testingInModal.value = true
  testResult.value = null
  try {
    let res
    if (editingId.value && !form.apiKey) {
      res = await testModelConnection(editingId.value)
    } else {
      res = await testConnection({
        baseUrl: form.baseUrl,
        completionsPath: form.completionsPath,
        apiKey: form.apiKey,
        modelName: form.modelName,
        temperature: form.temperature
      })
    }
    testResult.value = res.data
    if (res.data.success) {
      message.success(`连接成功 · ${res.data.latencyMs}ms`)
    } else {
      message.warning(`连接失败 · ${res.data.error}`)
    }
  } catch (e) {
    testResult.value = { success: false, error: '请求失败' }
    message.error('测试请求失败')
  } finally {
    testingInModal.value = false
  }
}

// 获取可用模型列表
async function handleFetchModels() {
  if (!form.baseUrl || !form.apiKey) {
    message.warning('请先填写接口地址和 API Key')
    return
  }

  fetchingModels.value = true
  try {
    const res = await fetchAvailableModels({ baseUrl: form.baseUrl, apiKey: form.apiKey })
    availableModels.value = (res.data || []).map(id => ({ label: id, value: id }))
    if (availableModels.value.length > 0) {
      message.success(`获取到 ${availableModels.value.length} 个可用模型`)
    } else {
      message.info('未获取到可用模型')
    }
  } catch (e) {
    message.error(e.response?.data?.message || '获取模型列表失败')
  } finally {
    fetchingModels.value = false
  }
}

// 选择模型
function handleModelSelect(val) {
  form.modelName = val
}

// 调整模型调用顺序
async function handleMoveUp(index) {
  if (index <= 0) return
  const list = [...models.value]
  ;[list[index - 1], list[index]] = [list[index], list[index - 1]]
  await savePriorities(list)
}

async function handleMoveDown(index) {
  if (index >= models.value.length - 1) return
  const list = [...models.value]
  ;[list[index], list[index + 1]] = [list[index + 1], list[index]]
  await savePriorities(list)
}

async function savePriorities(reordered) {
  const priorities = reordered.map((m, i) => ({ id: m.id, priority: i }))
  try {
    await updateModelPriorities(priorities)
    models.value = reordered
  } catch (e) {
    message.error('更新顺序失败')
    await fetchModels()
  }
}
</script>

<template>
  <div class="model-management">
    <div class="toolbar">
      <div class="toolbar-left">
        <span class="model-count">
          共 <span class="count-num">{{ models.length }}</span> 个模型
        </span>
      </div>
      <div class="toolbar-right">
        <n-button size="small" @click="fetchModels" :disabled="loading">
          <template #icon><n-icon><ReloadOutline /></n-icon></template>
          刷新
        </n-button>
        <n-button size="small" type="primary" @click="openCreate">
          <template #icon><n-icon><AddOutline /></n-icon></template>
          新增模型
        </n-button>
      </div>
    </div>

    <n-data-table
      :columns="columns"
      :data="models"
      :loading="loading"
      :bordered="false"
      :single-line="false"
      striped
      class="model-table"
    />

    <!-- 新增/编辑弹窗 -->
    <div class="dialog-overlay" v-if="showModal" @click.self="showModal = false">
      <div class="model-dialog">
        <div class="dialog-header">
          <span class="dialog-title">{{ editingId ? '编辑模型' : '新增模型' }}</span>
          <button class="icon-btn" @click="showModal = false"><n-icon size="16"><CloseOutline /></n-icon></button>
        </div>
        <div class="dialog-body">
          <n-form label-placement="left" label-width="90">
            <n-form-item label="名称" required>
              <n-input v-model:value="form.name" placeholder="如：智谱 GLM-4" />
            </n-form-item>
            <n-form-item label="接口地址" required>
              <n-input v-model:value="form.baseUrl" placeholder="如：https://open.bigmodel.cn/api/paas/v4" />
            </n-form-item>
            <n-form-item label="补全路径">
              <n-input v-model:value="form.completionsPath" placeholder="/chat/completions" />
            </n-form-item>
            <n-form-item label="API Key" :required="!editingId">
              <n-input v-model:value="form.apiKey" type="password" show-password-on="click"
                :placeholder="editingId ? '留空则不修改' : '输入 API Key'" />
            </n-form-item>
            <n-form-item label="模型标识" required>
              <n-space vertical style="width: 100%">
                <n-input v-model:value="form.modelName" placeholder="如：glm-4-flash"
                  :disabled="availableModels.length > 0" />
                <n-select v-if="availableModels.length > 0" :value="form.modelName" :options="availableModels"
                  placeholder="从列表中选择模型" @update:value="handleModelSelect" filterable clearable />
                <button class="ghost-btn small" :disabled="fetchingModels" @click="handleFetchModels">
                  <n-icon size="14"><FlashOutline /></n-icon>
                  <span>{{ fetchingModels ? '获取中...' : '获取可用模型' }}</span>
                </button>
              </n-space>
            </n-form-item>
            <n-form-item label="温度">
              <n-input-number v-model:value="form.temperature" :min="0" :max="2" :step="0.1" style="width: 160px" />
            </n-form-item>
            <n-form-item label="设为默认">
              <n-switch v-model:value="form.isDefault" />
            </n-form-item>

            <!-- 测试连接 -->
            <n-form-item label="连接测试">
              <n-space vertical style="width: 100%">
                <button class="ghost-btn small" :disabled="testingInModal" @click="handleTestInModal">
                  <n-icon size="14"><FlashOutline /></n-icon>
                  <span>{{ testingInModal ? '测试中...' : '测试连接' }}</span>
                </button>
                <div v-if="testResult" class="test-result" :class="testResult.success ? 'success' : 'fail'">
                  <template v-if="testResult.success">
                    <span class="test-status">✓ 连接成功</span>
                    <span class="test-latency">{{ testResult.latencyMs }}ms</span>
                    <div v-if="testResult.response" class="test-response">{{ testResult.response }}</div>
                  </template>
                  <template v-else>
                    <span class="test-status">✗ 连接失败</span>
                    <span class="test-error">{{ testResult.error }}</span>
                  </template>
                </div>
              </n-space>
            </n-form-item>
          </n-form>
        </div>
        <div class="dialog-footer">
          <button class="cancel-btn" @click="showModal = false">取消</button>
          <button class="primary-btn" :disabled="saving" @click="handleSave">
            {{ saving ? '保存中...' : '保存' }}
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.model-management {
  height: 100%;
}

.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--bg-primary);
  padding-bottom: 12px;
}

.model-count {
  font-size: 14px;
  color: var(--text-secondary);
}

.count-num {
  color: var(--color-accent);
  font-weight: 600;
}

.toolbar-right {
  display: flex;
  gap: 8px;
}

/* ========== 按钮 ========== */
.primary-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  background: var(--gradient-accent);
  color: #fff;
  border: none;
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all var(--transition-fast);
}
.primary-btn:hover { box-shadow: var(--glow-blue); }
.primary-btn:disabled { opacity: 0.5; cursor: not-allowed; }

.ghost-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  background: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  font-size: 13px;
  cursor: pointer;
  transition: all var(--transition-fast);
}
.ghost-btn:hover { color: var(--text-primary); border-color: var(--border-color-hover); }
.ghost-btn.small { padding: 5px 12px; font-size: 12px; }
.ghost-btn:disabled { opacity: 0.5; cursor: not-allowed; }

.cancel-btn {
  padding: 8px 20px;
  background: rgba(255,255,255,0.05);
  color: var(--text-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  font-size: 13px;
  cursor: pointer;
}
.cancel-btn:hover { background: rgba(255,255,255,0.08); }

.icon-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  background: none;
  border: none;
  color: var(--text-secondary);
  cursor: pointer;
  border-radius: 6px;
}
.icon-btn:hover { background: rgba(255,255,255,0.06); color: var(--text-primary); }

.order-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 4px;
  color: var(--text-secondary);
  cursor: pointer;
  padding: 0;
}
.order-btn:hover:not(:disabled) { background: rgba(255,255,255,0.08); color: var(--text-primary); }
.order-btn:disabled { opacity: 0.3; cursor: not-allowed; }

/* ========== NDataTable 颜色覆盖 ========== */
.model-table :deep(.n-data-table) {
  --n-td-color: #0f1e3c;
  --n-td-color-hover: rgba(37, 99, 235, 0.22);
  --n-th-color: rgba(37, 99, 235, 0.28);
  --n-th-text-color: var(--text-primary);
  --n-td-text-color: var(--text-primary);
  --n-border-color: rgba(56, 189, 248, 0.18);
  --n-td-color-striped: #0a1628;
}
.model-table :deep(.n-data-table-th) {
  background: rgba(37, 99, 235, 0.28) !important;
  color: var(--text-primary) !important;
  border-bottom: 1px solid rgba(56, 189, 248, 0.35) !important;
  font-size: 13px;
  font-weight: 600;
}
.model-table :deep(.n-data-table-td) {
  background: #0f1e3c !important;
  color: var(--text-primary) !important;
  border-bottom: 1px solid rgba(56, 189, 248, 0.1) !important;
}
.model-table :deep(.n-data-table-tr--striped .n-data-table-td) {
  background: #0a1628 !important;
}
.model-table :deep(.n-data-table-tr:hover .n-data-table-td) {
  background: rgba(37, 99, 235, 0.18) !important;
}

/* ========== 弹窗 ========== */
.dialog-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}
.model-dialog {
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  width: 560px;
  max-height: 90vh;
  overflow-y: auto;
}
.dialog-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid rgba(37, 99, 235, 0.12);
}
.dialog-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
}
.dialog-body {
  padding: 20px;
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 16px 20px;
  border-top: 1px solid rgba(37, 99, 235, 0.12);
}

/* ========== 测试连接结果 ========== */
.test-result {
  padding: 8px 12px;
  border-radius: 6px;
  font-size: 13px;
  width: 100%;
}
.test-result.success {
  background: rgba(34, 197, 94, 0.08);
  border: 1px solid rgba(34, 197, 94, 0.2);
}
.test-result.fail {
  background: rgba(239, 68, 68, 0.08);
  border: 1px solid rgba(239, 68, 68, 0.2);
}
.test-status { font-weight: 600; }
.test-latency { margin-left: 12px; color: var(--text-secondary); }
.test-error { margin-left: 8px; color: #ef4444; }
.test-response {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  color: var(--text-secondary);
  font-size: 12px;
  max-height: 60px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
</style>
