<template>
	<div class="model-manage">
		<el-card class="list-card">
			<div class="action-bar mb-12px">
				<div class="action-bar__left">
					<el-button type="primary" @click="openCreateModel">
						<el-icon>
							<Plus />
						</el-icon> 新建模型
					</el-button>
					<el-button @click="getAllModelList()">
						<el-icon>
							<Refresh />
						</el-icon> 刷新
					</el-button>
				</div>
				<div class="action-bar__right">
					<el-input v-model="searchForm.keyword" clearable placeholder="关键词搜索模型名称/标识" class="search-input"
						@keyup.enter="handleSearch" />
					<el-select v-model="searchForm.type" clearable placeholder="模型类型" style="width: 160px" @change="handleSearch">
						<el-option label="对话模型" value="KnowledgeQA" />
						<el-option label="Embedding模型" value="Embedding" />
						<el-option label="Rerank模型" value="Rerank" />
						<el-option label="视觉模型" value="VLLM" />
					</el-select>
					<el-select v-model="searchForm.source" clearable placeholder="来源" style="width: 140px" @change="handleSearch">
						<el-option label="本地" value="local" />
						<el-option label="服务商" value="remote" />
					</el-select>
					<el-button type="primary" @click="handleSearch">查询</el-button>
					<el-button @click="handleResetSearch">重置</el-button>
				</div>
			</div>

			<div v-loading="modelLoading" class="grid" :class="{ 'grid--empty': !allModels.length && !modelLoading }">
				<el-empty v-if="!allModels.length && !modelLoading" description="暂无配置的模型" class="empty" />

				<div v-for="row in allModels" :key="row.id" class="card" @click="openDetailModel(row.id)">
					<div class="card-head">
						<div class="card-head__content">
							<div class="card-head__top">
								<div class="title-block">
									<div class="title">{{ row.title || row.name || '未命名模型' }}</div>
									<div class="subtitle">{{ row.name || '未设置模型标识' }}</div>
								</div>
								<div class="actions" @click.stop>
									<el-dropdown>
										<span class="actions-trigger">
											<el-icon>
												<MoreFilled />
											</el-icon>
										</span>
										<template #dropdown>
											<el-dropdown-menu>
												<el-dropdown-item @click="openDetailModel(row.id)">详情</el-dropdown-item>
												<el-dropdown-item @click="openEditModel(row.id)">编辑</el-dropdown-item>
												<el-dropdown-item @click="deleteModelConfirm(row.id)" divided>
													<span class="danger-text">删除</span>
												</el-dropdown-item>
											</el-dropdown-menu>
										</template>
									</el-dropdown>
								</div>
							</div>

							<div class="badge-row">
								<span class="badge">{{ getModelTypeName(row.type) }}</span>
								<span class="badge subtle">{{ formatModelSource(row.source) }}</span>
							</div>
						</div>
					</div>

					<div class="desc">{{ row.description || '暂无描述' }}</div>

					<div class="tags">
						<el-tag v-if="row.is_default" type="success" effect="light">默认</el-tag>
						<el-tag :type="getModelStatusType(row.status)" effect="light">
							{{ formatModelStatus(row.status) }}
						</el-tag>
						<el-tag v-if="row.provider" type="info" effect="light">
							{{ row.provider }}
						</el-tag>
					</div>
				</div>
			</div>

			<div v-if="pagination.total > 0" class="pagination-wrap">
				<el-pagination v-model:current-page="pagination.pageIndex" v-model:page-size="pagination.pageSize" background
					layout="total, sizes, prev, pager, next, jumper" :total="pagination.total" :page-sizes="[10, 20, 50, 100]"
					@current-change="handlePageChange" @size-change="handleSizeChange" />
			</div>
		</el-card>

		<el-dialog v-model="showDetailDialog" title="模型详情" width="700px">
			<el-descriptions :column="1" border v-if="currentDetailModel">
				<el-descriptions-item label="模型标识">{{ currentDetailModel.name }}</el-descriptions-item>
				<el-descriptions-item label="显示名称">{{ currentDetailModel.title }}</el-descriptions-item>
				<el-descriptions-item label="模型类型">{{
					getModelTypeName(currentDetailModel.type)
				}}</el-descriptions-item>
				<el-descriptions-item label="模型来源">{{
					currentDetailModel.source === 'local' ? '本地Ollama' : '远程API'
				}}</el-descriptions-item>
				<el-descriptions-item label="服务商">{{
					currentDetailModel.provider
				}}</el-descriptions-item>
				<el-descriptions-item label="描述">{{
					currentDetailModel.description || '无'
				}}</el-descriptions-item>
				<el-descriptions-item v-if="currentDetailModel.source === 'remote'" label="API地址">
					{{ currentDetailModel.parameters.base_url || '无' }}
				</el-descriptions-item>
				<el-descriptions-item v-if="currentDetailModel.source === 'remote'" label="API Key">
					{{ maskApiKey(currentDetailModel.parameters.api_key) }}
				</el-descriptions-item>
				<el-descriptions-item v-if="currentDetailModel.source === 'remote'" label="连接测试">
					<div class="model-check-box">
						<el-button type="primary" plain :loading="detailCheckLoading" @click="checkCurrentDetailModel">
							测试连接
						</el-button>
						<el-alert v-if="detailCheckResult.message" :type="detailCheckResult.success ? 'success' : 'error'"
							:title="detailCheckResult.message" :closable="false" show-icon />
					</div>
				</el-descriptions-item>
				<el-descriptions-item label="创建时间">{{
					currentDetailModel.creationTime
				}}</el-descriptions-item>
				<el-descriptions-item label="更新时间">{{
					currentDetailModel.updateTime
				}}</el-descriptions-item>
			</el-descriptions>
			<template #footer>
				<el-button @click="showDetailDialog = false">关闭</el-button>
			</template>
		</el-dialog>

		<el-drawer v-model="showModelDialog" direction="rtl" :title="currentModelId ? '编辑模型' : '新建模型'" width="700px">
			<el-form ref="modelFormRef" :model="modelForm" :rules="modelRules" label-width="120px" label-position="top">
				<el-form-item label="模型来源" prop="source">
					<el-radio-group v-model="modelForm.source" @change="handleSourceChange">
						<el-radio label="local">本地Ollama</el-radio>
						<el-radio label="remote">服务商</el-radio>
					</el-radio-group>
				</el-form-item>

				<el-form-item v-if="modelForm.source === 'remote'" label="模型类型" prop="type">
					<el-select v-model="modelForm.type" placeholder="请选择模型类型" @change="handleTypeChange">
						<el-option label="对话模型" value="KnowledgeQA" />
						<el-option label="Embedding模型" value="Embedding" />
						<el-option label="Rerank模型" value="Rerank" />
						<el-option label="视觉模型" value="VLLM" />
					</el-select>
				</el-form-item>

				<el-form-item v-if="modelForm.source === 'local'" label="本地模型" prop="name">
					<el-select v-model="modelForm.name" placeholder="请选择" style="width: 100%">
						<el-option v-for="model in availableLocalModels" :key="model.name" :label="model.name"
							:value="model.name" />
					</el-select>
				</el-form-item>

				<el-form-item v-if="modelForm.source === 'remote'" label="服务商" prop="provider">
					<el-select v-model="modelForm.provider" placeholder="请选择服务商" @change="handleProviderChange"
						style="width: 100%">
						<el-option v-for="p in providers" :key="p.value" :label="p.label" :value="p.value" />
					</el-select>
				</el-form-item>

				<el-form-item label="模型名称" prop="name">
					<el-input v-model="modelForm.name" :readonly="modelForm.source === 'local'" placeholder="如：llama3.1" />
				</el-form-item>

				<el-form-item label="显示名称" prop="title">
					<el-input v-model="modelForm.title" placeholder="请输入显示名称" />
				</el-form-item>

				<el-form-item label="描述" prop="description">
					<el-input v-model="modelForm.description" type="textarea" rows="2" placeholder="模型描述..." />
				</el-form-item>

				<el-form-item v-if="modelForm.source === 'remote'" label="API地址" prop="base_url">
					<el-autocomplete v-model="modelForm.base_url" :fetch-suggestions="queryBaseUrlSuggestions" clearable
						placeholder="可从默认地址选择，或手动输入" style="width: 100%" />
				</el-form-item>

				<el-form-item v-if="modelForm.source === 'remote'" label="API Key" prop="api_key">
					<el-input v-model="modelForm.api_key" type="password" placeholder="输入你的API密钥" />
				</el-form-item>
				<el-form-item v-if="modelForm.source === 'remote' && modelForm.type === 'Embedding'" label="维度"
					prop="dimension">
					<el-input-number v-model="modelForm.dimension" :min="1" :step="1" controls-position="right"
						style="width: 100%" placeholder="请输入向量维度" />
				</el-form-item>

				<el-form-item v-if="modelForm.source === 'remote' && modelForm.type === 'Embedding'" label="截断Tokens"
					prop="truncate_prompt_tokens">
					<el-input-number v-model="modelForm.truncate_prompt_tokens" :min="0" :step="1" controls-position="right"
						style="width: 100%" placeholder="请输入截断 token 数" />
				</el-form-item>

				<el-form-item v-if="modelForm.source === 'remote' && modelForm.type === 'KnowledgeQA'" label="支持视觉"
					prop="supports_vision">
					<el-switch v-model="modelForm.supports_vision" />
				</el-form-item>

				<el-form-item prop="custom_headers">
					<div class="header-config">
						<div class="header-config__top">
							<span>自定义请求头(可选)</span>
							<el-button type="primary" link @click="addCustomHeader">
								<el-icon>
									<Plus />
								</el-icon>添加请求头
							</el-button>
						</div>
						<div class="header-config__desc">
							调用远程模型API时附加的HTTP请求头，常用于鉴权、链路追踪等场景
						</div>
						<div class="header-config__rows">
							<div v-for="(item, index) in customHeaderList" :key="index" class="header-config__row">
								<el-input v-model="item.key" placeholder="Header名称" />
								<el-input v-model="item.value" placeholder="Header值" />
								<el-button link type="danger" :disabled="customHeaderList.length === 1"
									@click="removeCustomHeader(index)">
									删除
								</el-button>
							</div>
						</div>
					</div>
				</el-form-item>
				<el-form-item>
					<div v-if="modelForm.source === 'remote'" class="model-check-box">
						<el-button type="primary" plain :loading="formCheckLoading" @click="checkModelFormConnection">
							测试连接
						</el-button>
						<el-alert v-if="formCheckResult.message" :type="formCheckResult.success ? 'success' : 'error'"
							:title="formCheckResult.message" :closable="false" show-icon />
					</div>
				</el-form-item>
			</el-form>
			<template #footer>
				<el-button @click="showModelDialog = false">取消</el-button>
				<el-button type="primary" @click="submitModelForm" :loading="submitLoading">提交</el-button>
			</template>
		</el-drawer>
	</div>
</template>

<script setup lang="ts">
import { computed, ref, reactive, onMounted, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Refresh, MoreFilled } from '@element-plus/icons-vue'
import { aiModel, ollama } from '@repo/api-service'
import type {
	ModelItem,
	ModelProvider,
	ModelCreateForm,
	ModelDetail,
	OllamaModel,
	modelType
} from './types'

const props = withDefaults(
	defineProps<{
		localOllamaModels?: OllamaModel[]
	}>(),
	{
		localOllamaModels: () => []
	}
)

const modelLoading = ref(false)
const submitLoading = ref(false)
const allModels = ref<ModelItem[]>([])
const providers = ref<ModelProvider[]>([])
const showModelDialog = ref(false)
const showDetailDialog = ref(false)
const currentModelId = ref<string | null>(null)
const currentDetailModel = ref<ModelDetail | null>(null)
const modelFormRef = ref()
const customHeaderList = ref<Array<{ key: string; value: string }>>([{ key: '', value: '' }])
const localModelOptions = ref<OllamaModel[]>([])
const detailCheckLoading = ref(false)
const detailCheckResult = reactive<{ success: boolean; message: string }>({
	success: false,
	message: ''
})
const formCheckLoading = ref(false)
const formCheckResult = reactive<{ success: boolean; message: string }>({
	success: false,
	message: ''
})
const searchForm = reactive({
	keyword: '',
	type: '',
	source: ''
})
const pagination = reactive({
	pageIndex: 1,
	pageSize: 20,
	total: 0
})

const availableLocalModels = computed(() =>
	props.localOllamaModels.length ? props.localOllamaModels : localModelOptions.value
)

const modelForm = reactive<ModelCreateForm>({
	source: 'local',
	type: 'KnowledgeQA',
	name: '',
	title: '',
	description: '',
	provider: '',
	base_url: '',
	api_key: '',
	custom_headers: {},
	dimension: undefined,
	truncate_prompt_tokens: undefined,
	supports_vision: false
})

const modelRules = {
	name: [{ required: true, message: '请输入模型名称', trigger: 'change' }],
	title: [{ required: true, message: '请输入显示名称', trigger: 'blur' }],
	type: [{ required: true, message: '请选择模型类型', trigger: 'change' }],
	source: [{ required: true, message: '请选择模型来源', trigger: 'change' }],
	dimension: [
		{
			validator: (_: any, value: number, callback: (error?: Error) => void) => {
				if (
					modelForm.source === 'remote' &&
					modelForm.type === 'Embedding' &&
					(!value || value <= 0)
				) {
					callback(new Error('Embedding 模型请填写有效的 dimension'))
					return
				}
				callback()
			},
			trigger: 'blur'
		}
	],
}

const typeLabelMap: Record<string, string> = {
	KnowledgeQA: '对话模型',
	Embedding: 'Embedding模型',
	Rerank: 'Rerank模型',
	VLLM: '视觉模型'
}

// const filteredProviders = computed(() => {
// 	if (!modelForm.type) return providers.value
// 	return providers.value.filter((p) => getProviderModelTypes(p).includes(modelForm.type))
// })

// function getProviderModelTypes(provider: ModelProvider) {
// 	const typeMap: Record<string, ModelCreateForm['type']> = {
// 		chat: 'KnowledgeQA',
// 		embedding: 'Embedding',
// 		rerank: 'Rerank',
// 		vllm: 'VLLM',
// 		knowledgeqa: 'KnowledgeQA'
// 	}
// 	return (provider.modelTypes || [])
// 		.map((t) => typeMap[String(t).toLowerCase()] || (t as ModelCreateForm['type']))
// 		.filter((t) => ['KnowledgeQA', 'Embedding', 'Rerank', 'VLLM'].includes(t))
// }

// function getModelTypeLabel(type: ModelCreateForm['type']) {
// 	const map: Record<ModelCreateForm['type'], string> = {
// 		KnowledgeQA: 'LLM',
// 		Embedding: 'TEXT EMBEDDING',
// 		Rerank: 'RERANK',
// 		VLLM: 'VLLM'
// 	}
// 	return map[type]
// }

function maskApiKey(key: string) {
	if (!key) return '无'
	if (key.length <= 8) return '****'
	return `${key.slice(0, 4)}${'*'.repeat(key.length - 8)}${key.slice(-4)}`
}
function getModelTypeName(type?: string) {
	if (!type) return '-'
	return typeLabelMap[type] || type
}

function formatModelSource(source?: string) {
	return source === 'local' ? '本地模型' : '服务商'
}

function formatModelStatus(status?: string) {
	if (!status) return '未知状态'
	if (status === 'active') return '可用'
	return status
}

function getModelStatusType(status?: string) {
	if (status === 'active') return 'success'
	if (!status) return 'info'
	return 'warning'
}

function resetDetailCheckResult() {
	detailCheckResult.success = false
	detailCheckResult.message = ''
}

function resetFormCheckResult() {
	formCheckResult.success = false
	formCheckResult.message = ''
}

async function runModelCheck(
	payload: Record<string, any>,
	resultState: { success: boolean; message: string }
) {
	resultState.message = ''
	try {
		const res = await aiModel.postModelCheck(payload as any)
		if (res?.isSuccess) {
			resultState.success = true
			resultState.message = res?.result?.message ?? '连接测试成功'
			return true
		}
		resultState.success = false
		resultState.message = res?.result?.message || '连接测试失败，请检查配置'
		return false
	} catch {
		resultState.success = false
		resultState.message = '连接测试失败，请检查配置'
		return false
	}
}

async function openDetailModel(id: string) {
	const res = await aiModel.postModelInfo({ id })
	if (res.isSuccess) {
		currentDetailModel.value = res.result
		resetDetailCheckResult()
		showDetailDialog.value = true
	}
}

/**根据模型类型获取模型提供者 */
async function getProviders(type?: modelType) {
	const res = await aiModel.postModelProviders({ model_type: type! })
	if (res.isSuccess) providers.value = (res.result || []) as ModelProvider[]
}

async function getAllModelList() {
	modelLoading.value = true
	try {
		const res = await aiModel.postModelPageList({
			keyword: searchForm.keyword,
			type: searchForm.type,
			source: searchForm.source,
			pageIndex: pagination.pageIndex,
			pageSize: pagination.pageSize
		})
		if (res.isSuccess) {
			allModels.value = (res.result.model || []) as ModelItem[]
			pagination.total = res.result.totalCount || 0
			pagination.pageIndex = res.result.currentPage || pagination.pageIndex
			pagination.pageSize = res.result.pageSize || pagination.pageSize
		}
	} finally {
		modelLoading.value = false
	}
}

async function loadLocalModels() {
	if (props.localOllamaModels.length) return
	try {
		const res = await ollama.postOllamaModels({})
		if (res?.isSuccess) {
			localModelOptions.value = (res.result || []) as OllamaModel[]
		}
	} catch {
		localModelOptions.value = []
	}
}

function handleSearch() {
	pagination.pageIndex = 1
	getAllModelList()
}

function handleResetSearch() {
	searchForm.keyword = ''
	searchForm.type = ''
	searchForm.source = ''
	pagination.pageIndex = 1
	pagination.pageSize = 20
	getAllModelList()
}

function handlePageChange(page: number) {
	pagination.pageIndex = page
	getAllModelList()
}

function handleSizeChange(size: number) {
	pagination.pageSize = size
	pagination.pageIndex = 1
	getAllModelList()
}

function openCreateModel() {
	resetModelForm()
	showModelDialog.value = true
}

// function openCreateModelByProvider(provider: ModelProvider) {
// 	resetModelForm()
// 	modelForm.source = 'remote'
// 	modelForm.provider = provider.value
// 	modelForm.type = getProviderModelTypes(provider)[0] || 'KnowledgeQA'
// 	modelForm.base_url = getDefaultUrlByType(provider)
// 	if (modelForm.type === 'VLLM') modelForm.supports_vision = true
// 	showModelDialog.value = true
// }

async function openEditModel(id: string) {
	resetModelForm()
	currentModelId.value = id
	const res = await aiModel.postModelInfo({ id })
	if (res.isSuccess) {
		const data = res.result
		const currentHeaders = ((data as any)?.parameters?.custom_headers || {}) as Record<
			string,
			string
		>
		const headerRows = Object.entries(currentHeaders).map(([key, value]) => ({
			key,
			value: String(value ?? '')
		}))
		customHeaderList.value = headerRows.length ? headerRows : [{ key: '', value: '' }]
		Object.assign(modelForm, {
			source: data.source,
			type: data.type,
			name: data.name,
			title: data.title,
			description: data.description,
			provider: data.provider,
			base_url: data.parameters.base_url,
			api_key: data.parameters.api_key,
			custom_headers: currentHeaders,
			dimension: data.parameters?.embedding_parameters?.dimension,
			truncate_prompt_tokens: data.parameters?.embedding_parameters?.truncate_prompt_tokens,
			supports_vision: Boolean((data as any)?.parameters?.supports_vision),
			is_default: data.is_default
		})
	}
	showModelDialog.value = true
}

function resetModelForm() {
	currentModelId.value = null
	customHeaderList.value = [{ key: '', value: '' }]
	resetFormCheckResult()
	Object.assign(modelForm, {
		source: 'local',
		type: 'KnowledgeQA',
		name: '',
		title: '',
		description: '',
		provider: '',
		base_url: '',
		api_key: '',
		custom_headers: {},
		dimension: undefined,
		truncate_prompt_tokens: undefined,
		supports_vision: false,
		is_default: false
	})
}
function addCustomHeader() {
	customHeaderList.value.push({ key: '', value: '' })
}
function removeCustomHeader(index: number) {
	if (customHeaderList.value.length === 1) {
		customHeaderList.value[0] = { key: '', value: '' }
		return
	}
	customHeaderList.value.splice(index, 1)
}

function handleSourceChange() {
	modelForm.name = ''
	modelForm.provider = ''
	modelForm.base_url = ''
	resetFormCheckResult()
}

async function handleTypeChange() {
	modelForm.provider = ''
	modelForm.base_url = ''
	resetFormCheckResult()
	if (modelForm.type === 'VLLM') {
		modelForm.supports_vision = true
		return
	}
	if (modelForm.type === 'KnowledgeQA') {
		modelForm.supports_vision = modelForm.supports_vision ?? false
		return
	}
	modelForm.supports_vision = false
	modelForm.dimension = undefined
	modelForm.truncate_prompt_tokens = undefined
	// getProviders(modelForm.type)
}

function handleProviderChange() {
	const provider = providers.value.find((p) => p.value === modelForm.provider)
	if (provider) modelForm.base_url = getDefaultUrlByType(provider) || ''
	resetFormCheckResult()
}

function getDefaultUrlByType(provider: ModelProvider) {
	const typeToDefaultUrlKey: Record<string, keyof ModelProvider['defaultUrls']> = {
		KnowledgeQA: 'chat',
		Embedding: 'embedding',
		Rerank: 'rerank',
		VLLM: 'vllm'
	}
	const defaultUrlKey = typeToDefaultUrlKey[modelForm.type] || 'chat'
	return provider.defaultUrls?.[defaultUrlKey] || ''
}

function queryBaseUrlSuggestions(
	queryString: string,
	cb: (results: Array<{ value: string }>) => void
) {
	const provider = providers.value.find((p) => p.value === modelForm.provider)
	if (!provider) return cb([])
	const defaultUrl = getDefaultUrlByType(provider)
	if (!defaultUrl) return cb([])
	const list = [{ value: defaultUrl }]
	const keyword = (queryString || '').trim().toLowerCase()
	cb(keyword ? list.filter((item) => item.value.toLowerCase().includes(keyword)) : list)
}

function buildCheckParams() {
	const payload: Record<string, any> = {
		name: modelForm.name,
		type: modelForm.type,
		source: modelForm.source,
		provider: modelForm.provider,
		api_key: modelForm.api_key
	}
	if (modelForm.type === 'Embedding') {
		payload.truncate_prompt_tokens = modelForm.truncate_prompt_tokens ?? 0
	}
	return payload
}

async function checkCurrentDetailModel() {
	if (!currentDetailModel.value || currentDetailModel.value.source !== 'remote') return
	detailCheckLoading.value = true
	try {
		const detail = currentDetailModel.value
		const payload: Record<string, any> = {
			name: detail.name,
			type: detail.type,
			source: detail.source,
			provider: detail.provider,
			api_key: detail.parameters?.api_key
		}
		if (detail.type === 'Embedding') {
			payload.truncate_prompt_tokens =
				detail.parameters?.embedding_parameters?.truncate_prompt_tokens ?? 0
		}
		await runModelCheck(payload, detailCheckResult)
	} finally {
		detailCheckLoading.value = false
	}
}

async function checkModelFormConnection() {
	if (modelForm.source !== 'remote') return
	const valid = await modelFormRef.value
		?.validateField?.(['type', 'name', 'source'])
		.then(() => true)
		.catch(() => false)
	if (!valid) return
	if (!modelForm.provider || !modelForm.api_key) {
		formCheckResult.success = false
		formCheckResult.message = '请先完善服务商和 API Key'
		return
	}
	formCheckLoading.value = true
	try {
		await runModelCheck(buildCheckParams(), formCheckResult)
	} finally {
		formCheckLoading.value = false
	}
}

async function submitModelForm() {
	await modelFormRef.value?.validate(async (valid: boolean) => {
		if (!valid) return
		submitLoading.value = true
		try {
			const customHeaders: Record<string, string> = {}
			for (const item of customHeaderList.value) {
				const key = item.key.trim()
				if (!key) continue
				customHeaders[key] = item.value
			}
			// try {
			// 	if (
			// 		typeof modelForm.custom_headers === 'string' &&
			// 		modelForm.custom_headers.trim().startsWith('{')
			// 	) {
			// 		Object.assign(customHeaders, JSON.parse(modelForm.custom_headers))
			// 	}
			// } catch {
			// 	ElMessage.error('自定义请求头 JSON 格式错误')
			// 	return
			// }
			if (modelForm.source === 'remote') {
				const checkSuccess = await runModelCheck(buildCheckParams(), formCheckResult)
				if (!checkSuccess) {
					ElMessage.error(formCheckResult.message || '模型不可用，请检查数据')
					return
				}
			}

			const params = {
				name: modelForm.name,
				title: modelForm.title,
				description: modelForm.description,
				type: modelForm.type,
				source: modelForm.source,
				provider: modelForm.source === 'local' ? 'ollama' : modelForm.provider!,
				base_url: modelForm.base_url,
				api_key: modelForm.api_key,
				custom_headers: customHeaders,
				supports_vision:
					modelForm.type === 'VLLM'
						? true
						: modelForm.type === 'KnowledgeQA'
							? !!modelForm.supports_vision
							: false,
				dimension: modelForm.type === 'Embedding' ? modelForm.dimension : undefined,
				truncate_prompt_tokens:
					modelForm.type === 'Embedding' ? modelForm.truncate_prompt_tokens : undefined
			}
			if (currentModelId.value) {
				await aiModel.postModelUpdate({ id: currentModelId.value, ...params })
				ElMessage.success('更新成功')
			} else {
				await aiModel.postModelCreate(params)
				ElMessage.success('创建成功')
			}
			showModelDialog.value = false
			getAllModelList()
		} catch {
			ElMessage.error('提交失败')
		} finally {
			submitLoading.value = false
		}
	})
}

async function deleteModelConfirm(id: string) {
	ElMessageBox.confirm('确定要删除该模型吗？删除后不可恢复').then(async () => {
		await aiModel.postModelOpenApiDelete({ id })
		ElMessage.success('删除成功')
		getAllModelList()
	})
}

watch(
	() => modelForm.type,
	() => {
		if (modelForm.type) {
			getProviders(modelForm.type)
		}
	},
	{ immediate: true }
)

onMounted(() => {
	// getProviders()
	loadLocalModels()
	getAllModelList()
	window.addEventListener('open-import-ollama-model', (e: any) => {
		resetModelForm()
		modelForm.source = 'local'
		modelForm.name = e.detail
		modelForm.title = e.detail
		showModelDialog.value = true
	})
})
</script>

<style lang="less" scoped>
.model-manage {
	width: 100%;
}

.action-bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: 12px;
}

.action-bar__left,
.action-bar__right {
	display: flex;
	align-items: center;
	gap: 12px;
	flex-wrap: wrap;
}

.list-card {
	border-radius: 18px;
	margin-bottom: 16px;
}

.search-input {
	width: 240px;
}

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

.pill {
	padding: 8px 12px;
	border-radius: 999px;
	border: 1px solid #e5e7eb;
	background: #f8fafc;
	font-size: 12px;
	color: #64748b;
}

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

.grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
	gap: 16px;
	min-height: 240px;
}

.grid--empty {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 360px;
}

.card {
	overflow: hidden;
	border-radius: 20px;
	border: 1px solid #e5e7eb;
	background: #fff;
	box-shadow: 0 12px 28px rgba(15, 23, 42, 0.06);
	cursor: pointer;
	padding: 16px;
	display: flex;
	flex-direction: column;
	gap: 14px;
	transition:
		transform 0.22s ease,
		box-shadow 0.22s ease,
		border-color 0.22s ease;
}

.card:hover {
	transform: translateY(-3px);
	border-color: #d8dee9;
	box-shadow: 0 18px 36px rgba(15, 23, 42, 0.1);
}

.card-head {
	padding: 14px 16px;
	border-radius: 18px;
	background:
		radial-gradient(circle at top left, rgba(15, 23, 42, 0.06), transparent 38%),
		linear-gradient(135deg, #f8fafc, #eef2ff 58%, #fff7ed);
}

.card-head__content {
	min-width: 0;
}

.card-head__top {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 12px;
}

.title-block {
	min-width: 0;
}

.title {
	font-size: 18px;
	font-weight: 700;
	line-height: 1.25;
	color: #0f172a;
	word-break: break-word;
}

.subtitle {
	margin-top: 6px;
	font-size: 13px;
	color: #64748b;
	word-break: break-all;
}

.badge-row {
	margin-top: 10px;
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.badge {
	padding: 5px 10px;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.92);
	font-size: 12px;
	color: #334155;
	border: 1px solid rgba(203, 213, 225, 0.9);
}

.badge.subtle {
	background: rgba(15, 23, 42, 0.82);
	color: #f8fafc;
	border-color: transparent;
}

.desc {
	min-height: 44px;
	color: #64748b;
	font-size: 14px;
	line-height: 1.65;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.tags {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.meta-list {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 10px;
}

.meta-item {
	padding: 10px 12px;
	border-radius: 14px;
	background: #f8fafc;
	border: 1px solid #e2e8f0;
	display: flex;
	flex-direction: column;
	gap: 4px;
	min-width: 0;
}

.meta-label {
	font-size: 12px;
	color: #94a3b8;
}

.meta-value {
	font-size: 13px;
	color: #334155;
	word-break: break-word;
}

.card-footer {
	display: flex;
	justify-content: flex-end;
	gap: 6px;
	margin-top: auto;
}

.actions {
	display: flex;
	justify-content: flex-end;
}

.actions-trigger {
	width: 30px;
	height: 30px;
	border-radius: 999px;
	display: grid;
	place-items: center;
	color: #475569;
	background: rgba(255, 255, 255, 0.8);
	transition:
		background 0.2s ease,
		color 0.2s ease;
}

.actions-trigger:hover {
	background: rgba(15, 23, 42, 0.08);
	color: #0f172a;
}

.danger-text {
	color: var(--el-color-danger);
}

.empty {
	width: 100%;
	min-height: 360px;
	display: flex;
	align-items: center;
	justify-content: center;
	grid-column: span 4;
}

.card-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	font-weight: 600;
}

pre {
	margin: 0;
	padding: 8px;
	background: #f5f7fa;
	border-radius: 4px;
	font-size: 12px;
}

.provider-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
	gap: 12px;
}

.provider-card {
	position: relative;
	padding: 16px;
	border-radius: 16px;
	border: 1px solid #d9dbe1;
	transition: all 0.2s ease;
}

.provider-card:hover {
	transform: translateY(-2px);
	box-shadow: 0 10px 24px rgba(18, 28, 45, 0.12);
}

.provider-card__top {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	margin-bottom: 8px;
}

.provider-card__label {
	font-size: 18px;
	font-weight: 700;
	line-height: 1.15;
	color: #1f2937;
}

.provider-card__desc {
	font-size: 18px;
	line-height: 1.5;
	color: #2f384a;
	min-height: 72px;
	margin-bottom: 12px;
}

.provider-card__tags {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.provider-card__action {
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.2s ease;
}

.provider-card:hover .provider-card__action {
	opacity: 1;
	pointer-events: auto;
}

.provider-card--tone-1 {
	background: #f2f4f8;
}

.provider-card--tone-2 {
	background: #eef2f7;
}

.provider-card--tone-3 {
	background: #f4f6fb;
}

.provider-card--tone-4 {
	background: #edf3f8;
}

.provider-card--tone-5 {
	background: #f3f5f9;
}

.header-config {
	width: 100%;
}

.header-config__top {
	display: flex;
	align-items: center;
	justify-content: space-between;
}

.header-config__desc {
	color: #909399;
	font-size: 12px;
	margin: 4px 0 10px;
}

.header-config__rows {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.header-config__row {
	display: grid;
	grid-template-columns: 1fr 1fr auto;
	gap: 8px;
	align-items: center;
}

.model-check-box {
	width: 100%;
	display: flex;
	flex-direction: column;
	gap: 8px;
}

@media (max-width: 768px) {
	.search-input {
		width: 100%;
	}

	.meta-list,
	.header-config__row {
		grid-template-columns: 1fr;
	}
}
</style>
