<template>
	<el-dialog v-model="drawerVisible" :title="editingId ? '编辑知识库' : '新建知识库'" @open="handleOpen" class="knowledge-modal"
		fullscreen>
		<div class="modal-wrap">
			<el-form ref="formRef" :model="form" :rules="rules" label-position="left" label-width="120px"
				class="knowledge-form">
				<el-tabs v-model="activeTab" tab-position="left" class="settings-tabs">
					<el-tab-pane label="基础信息" name="basic">
						<div class="tab-intro">设置知识库的名称、类型和描述信息</div>
						<div class="collapse-body">
							<el-form-item label="知识库类型" prop="type">
								<div class="switch-wrap">
									<el-segmented v-model="form.type" class="selection-segmented" :options="knowledgeTypeOptions"
										@change="handleKnowledgeBaseTypeChange" />
									<div class="field-tip">
										FAQ 类型适合结构化问答数据；文档型支持文件解析与分块。
									</div>
								</div>
							</el-form-item>

							<div v-if="isDocumentType" class="subsection ml-120px mb-16px">
								<div class="subsection-title">索引策略</div>
								<div class="subsection-tip">
									配置文档上传后的处理管道。关键词和向量检索为 RAG 必需项，系统会保持开启。
								</div>
								<div class="index-strategy-list">
									<el-form-item label="知识图谱启用">
										<div class="switch-wrap">
											<el-segmented v-model="form.graph_enabled" class="selection-segmented"
												:options="booleanSegmentedOptions" />
											<div class="field-tip">开启后可使用图谱关系辅助检索。</div>
										</div>
									</el-form-item>
									<el-form-item label="关键字启用">
										<div class="switch-wrap">
											<el-segmented v-model="form.keyword_enabled" class="selection-segmented"
												:options="booleanSegmentedOptions" disabled />
											<div class="field-tip">RAG 检索必须开启，系统会自动保持为开启状态。</div>
										</div>
									</el-form-item>
									<el-form-item label="向量启用">
										<div class="switch-wrap">
											<el-segmented v-model="form.vector_enabled" class="selection-segmented"
												:options="booleanSegmentedOptions" disabled />
											<div class="field-tip">RAG 检索必须开启，系统会自动保持为开启状态。</div>
										</div>
									</el-form-item>
									<el-form-item label="维基启用">
										<div class="switch-wrap">
											<el-segmented v-model="form.wiki_enabled" class="selection-segmented"
												:options="booleanSegmentedOptions" />
											<div class="field-tip">开启后可从 Wiki 内容中补充知识来源。</div>
										</div>
									</el-form-item>
								</div>
							</div>

							<el-form-item label="知识库名称" prop="name">
								<el-input v-model="form.name" placeholder="请输入知识库名称" />
							</el-form-item>

							<el-form-item label="知识库描述">
								<el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入知识库描述" />
							</el-form-item>
						</div>
					</el-tab-pane>

					<el-tab-pane label="模型配置" name="model">
						<div class="tab-intro">为知识库选择合适的 AI 模型</div>
						<div class="collapse-body">
							<el-form-item label="LLM大语言模型" prop="summary_model_id">
								<el-select v-model="form.summary_model_id" placeholder="请选择">
									<el-option v-for="item in summaryModels" :key="item.id" :label="buildModelLabel(item)"
										:value="item.id" />
								</el-select>
								<div class="field-tip">用于总结和摘要的大语言模型。</div>
							</el-form-item>
							<el-form-item label="Embedding 嵌入模型" prop="embedding_model_id">
								<el-select v-model="form.embedding_model_id" placeholder="请选择">
									<el-option v-for="item in embeddingModels" :key="item.id" :label="buildModelLabel(item)"
										:value="item.id" />
								</el-select>
								<div class="field-tip">用于文本向量化的嵌入模型。</div>
							</el-form-item>
						</div>
					</el-tab-pane>

					<el-tab-pane v-if="isDocumentType" label="解析引擎" name="parser">
						<div class="tab-intro">为不同文件类型选择文档解析引擎</div>
						<div class="collapse-body">
							<div class="field-tip compact-tip">
								未配置的文件类型将使用内置解析引擎。
							</div>
							<div class="parser-rule-list">
								<div v-for="rule in form.parser_engine_rules" :key="rule.file_types.join(',')" class="parser-rule-item">
									<div class="parser-rule-item__types">{{ rule.file_types.join(', ') }}</div>
									<el-select v-model="rule.engine" placeholder="请选择">
										<el-option v-for="item in parserEngineOptions" :key="item" :label="item" :value="item" />
									</el-select>
								</div>
							</div>
						</div>
					</el-tab-pane>

					<el-tab-pane v-if="isDocumentType" label="图像处理" name="image">
						<div class="tab-intro">配置图像内容理解能力</div>
						<div class="collapse-body">
							<el-form-item label="多模态功能">
								<div class="switch-wrap">
									<el-segmented v-model="form.vlm_enabled" class="selection-segmented"
										:options="booleanSegmentedOptions" />
									<div class="field-tip">启用图片等多模态内容的理解能力。</div>
								</div>
							</el-form-item>
							<el-form-item v-if="form.vlm_enabled" label="VLLM视觉模型">
								<el-select v-model="form.vlm_model_id" placeholder="请选择">
									<el-option v-for="item in vlmModels" :key="item.id" :label="buildModelLabel(item)" :value="item.id" />
								</el-select>
								<div class="field-tip">用于多模态理解的视觉语言模型（必选）。</div>
							</el-form-item>
						</div>
					</el-tab-pane>

					<el-tab-pane v-if="isDocumentType" label="音频处理" name="audio">
						<div class="tab-intro">配置语音识别（ASR）</div>
						<div class="collapse-body">
							<div class="field-tip compact-tip">
								启用后可上传音频文件并整段转写为文本（常见格式：mp3、wav、m4a、flac、ogg 等）。暂不支持视频上传。
							</div>
							<el-form-item label="启用音频语音识别">
								<div class="switch-wrap">
									<el-segmented v-model="form.asr_enabled" class="selection-segmented"
										:options="booleanSegmentedOptions" />
									<div class="field-tip">
										启用后可上传音频到知识库，系统自动将语音转写为文本并参与解析与检索。
									</div>
								</div>
							</el-form-item>
							<el-form-item v-if="form.asr_enabled" label="ASR模型">
								<el-select v-model="form.asr_model_id" placeholder="请选择">
									<el-option v-for="item in asrModels" :key="item.id" :label="buildModelLabel(item)" :value="item.id" />
								</el-select>
								<div class="field-tip">用于音频中语音转文本的识别模型（如 OpenAI Whisper）。</div>
							</el-form-item>
						</div>
					</el-tab-pane>

					<el-tab-pane v-if="isDocumentType" label="存储引擎" name="storage">
						<div class="tab-intro">选择文档上传使用的文件存储引擎</div>
						<div class="collapse-body">
							<el-form-item label="存储引擎">
								<el-select v-model="form.storage_provider" placeholder="请选择">
									<el-option v-for="item in storageProviderOptions" :key="item.value" :label="item.label"
										:value="item.value" />
								</el-select>
								<div class="field-tip">
									选择该知识库使用的存储引擎，需在全局设置中已配置对应引擎。
								</div>
							</el-form-item>
						</div>
					</el-tab-pane>

					<el-tab-pane v-if="isDocumentType" label="分块设置" name="chunk">
						<div class="tab-intro">配置文档分块参数，优化检索效果</div>
						<div class="collapse-body">
							<el-form-item label="分块大小">
								<div class="slider-wrap">
									<el-slider v-model="form.chunk_size" :min="100" :max="4000" :step="50" show-input />
									<div class="field-tip">控制每个文档分块的字符数（100-4000）。</div>
								</div>
							</el-form-item>
							<el-form-item label="分块重叠">
								<div class="slider-wrap">
									<el-slider v-model="form.chunk_overlap" :min="0" :max="500" :step="10" show-input />
									<div class="field-tip">相邻文档块之间的重叠字符数（0-500）。</div>
								</div>
							</el-form-item>
							<el-form-item label="分隔符">
								<el-select v-model="form.separators" multiple allow-create filterable default-first-option
									placeholder="请输入或选择分隔符">
									<el-option v-for="item in separatorOptions" :key="item" :label="`${item.label}(${item.displayValue})`"
										:value="item.value" />
								</el-select>
								<div class="field-tip">文档分块时使用的分隔符。</div>
							</el-form-item>

							<el-form-item label="父子分块">
								<div class="switch-wrap">
									<el-segmented v-model="form.enable_parent_child" class="selection-segmented"
										:options="booleanSegmentedOptions" />
									<div class="field-tip">
										启用两级父子分块策略。大的父块提供上下文，小的子块用于向量匹配检索。
									</div>
								</div>
							</el-form-item>

							<div v-if="form.enable_parent_child" class="subsection ml-120px">
								<div class="subsection-title">父子分块参数</div>

								<el-form-item label="父块大小">
									<div class="slider-wrap">
										<el-slider v-model="form.parent_chunk_size" :min="512" :max="8192" :step="128" show-input />
										<div class="field-tip">提供上下文的父块字符数（512-8192）。</div>
									</div>
								</el-form-item>
								<el-form-item label="子块大小">
									<div class="slider-wrap">
										<el-slider v-model="form.child_chunk_size" :min="64" :max="2048" :step="64" show-input />
										<div class="field-tip">用于向量匹配的子块字符数（64-2048）。</div>
									</div>
								</el-form-item>
							</div>
						</div>
					</el-tab-pane>

					<el-tab-pane v-if="isDocumentType" label="高级设置" name="advanced">
						<div class="tab-intro">配置问题生成等高级功能</div>
						<div class="collapse-body">
							<el-form-item label="AI 问题生成">
								<div class="switch-wrap">
									<el-segmented v-model="form.question_generation_enabled" class="selection-segmented"
										:options="booleanSegmentedOptions" />
									<div class="field-tip">
										解析文档时调用大模型为每个分块生成相关问题，提高检索召回率。启用后会增加文档解析耗时。
									</div>
								</div>
							</el-form-item>
							<el-form-item v-if="form.question_generation_enabled" label="生成问题数量">
								<el-input-number v-model="form.question_count" :min="1" :max="10" style="width: 100%" />
								<div class="field-tip">每个文档分块生成的问题数量（1-10）。</div>
							</el-form-item>
						</div>
					</el-tab-pane>

					<el-tab-pane v-if="!isDocumentType" label="FAQ设置" name="faq">
						<div class="tab-intro">设置 FAQ 知识库的索引策略和问答组织方式</div>
						<div class="collapse-body">
							<el-form-item label="索引方式">
								<div class="switch-wrap">
									<el-segmented v-model="form.faq_index_mode" class="selection-segmented"
										:options="faqIndexModeOptions" />
									<div class="field-tip">仅索引问题可提升精度，索引问答可提高召回率。</div>
								</div>
							</el-form-item>
							<el-form-item label="问题索引方式">
								<div class="switch-wrap">
									<el-segmented v-model="form.faq_question_index_mode" class="selection-segmented"
										:options="faqQuestionIndexModeOptions" />
									<div class="field-tip">
										合并索引：标准问和相似问合并索引；分别索引：标准问和每个相似问独立索引，检索更精确但需要更多存储。
									</div>
								</div>
							</el-form-item>
						</div>
					</el-tab-pane>
				</el-tabs>
			</el-form>
		</div>

		<template #footer>
			<div class="drawer-footer">
				<el-button @click="drawerVisible = false">取消</el-button>
				<el-button type="primary" :loading="submitLoading" @click="submitForm">保存</el-button>
			</div>
		</template>
	</el-dialog>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { aiModel, knowledge, storageProvider } from '@repo/api-service'
import type { KnowledgeBaseForm, KnowledgeModelOption, ParserEngineRule } from '../types'

const emit = defineEmits<{ (e: 'refresh'): void }>()

const submitLoading = ref(false)
const drawerVisible = ref(false)
const editingId = ref('')
const activeTab = ref('basic')
const modelList = ref<KnowledgeModelOption[]>([])
const formRef = ref()

const DEFAULT_PARSER_RULES: ParserEngineRule[] = [
	{ engine: 'builtin', file_types: ['pdf'] },
	{ engine: 'builtin', file_types: ['docx', 'doc'] },
	{ engine: 'markitdown', file_types: ['pptx', 'ppt'] },
	{ engine: 'builtin', file_types: ['xlsx', 'xls'] },
	{ engine: 'simple', file_types: ['csv'] },
	{ engine: 'builtin', file_types: ['md', 'markdown'] },
	{ engine: 'simple', file_types: ['txt'] },
	{ engine: 'simple', file_types: ['json'] },
	{ engine: 'builtin', file_types: ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff', 'webp'] },
	{ engine: 'simple', file_types: ['mp3', 'wav', 'm4a', 'flac', 'ogg'] }
]

const separatorOptions = [
	{ label: '双换行', value: '\n\n', displayValue: '\\n\\n' },
	{ label: '单换行', value: '\n', displayValue: '\\n' },
	{ label: '中文句号', value: '。', displayValue: '。' },
	{ label: '感叹号', value: '！', displayValue: '！' },
	{ label: '问号', value: '？', displayValue: '？' },
	{ label: '英文分号', value: ';', displayValue: ';' },
	{ label: '中文分号', value: '；', displayValue: '；' }
]
const DEFAULT_SEPARATORS = separatorOptions.map((item) => item.value)
const parserEngineOptions = ['builtin', 'markitdown', 'simple']
const storageProviderOptions = ref<{ label: string; value: string }[]>([])
const knowledgeTypeOptions = [
	{ label: '文档', value: 'document' },
	{ label: '问答', value: 'faq' }
]
const booleanSegmentedOptions = [
	{ label: '开启', value: true },
	{ label: '关闭', value: false }
]
const faqIndexModeOptions = [
	{ label: '仅索引问题', value: 'question_only' },
	{ label: '索引问答', value: 'question_answer' }
]
const faqQuestionIndexModeOptions = [
	{ label: '合并索引', value: 'combined' },
	{ label: '分别索引', value: 'separate' }
]

function cloneParserRules(rules?: ParserEngineRule[]) {
	return (rules || DEFAULT_PARSER_RULES).map((rule) => ({
		engine: rule.engine,
		file_types: [...rule.file_types]
	}))
}

const createDefaultForm = (): KnowledgeBaseForm => ({
	name: '',
	description: '',
	type: 'document',
	embedding_model_id: '',
	summary_model_id: '',
	faq_index_mode: 'question_only',
	faq_question_index_mode: 'separate',
	vlm_enabled: true,
	vlm_model_id: '',
	asr_enabled: false,
	asr_model_id: '',
	asr_language: '',
	graph_enabled: false,
	keyword_enabled: true,
	vector_enabled: true,
	wiki_enabled: false,
	question_generation_enabled: true,
	question_count: 3,
	chunk_size: 512,
	chunk_overlap: 100,
	separators: [...DEFAULT_SEPARATORS],
	parser_engine_rules: cloneParserRules(),
	enable_parent_child: true,
	parent_chunk_size: 4096,
	child_chunk_size: 384,
	storage_provider: 'local',
	wiki_extraction_granularity: 'standard',
	wiki_max_pages_per_ingest: 0,
	wiki_synthesis_model_id: ''
})

const form = reactive<KnowledgeBaseForm>(createDefaultForm())

const embeddingModels = computed(() => modelList.value.filter((item) => item.type === 'Embedding'))
const summaryModels = computed(() => modelList.value.filter((item) => item.type === 'KnowledgeQA'))
const vlmModels = computed(() => modelList.value.filter((item) => item.type === 'VLLM'))
const asrModels = computed(() =>
	modelList.value.filter((item) => ['ASR', 'Asr', 'asr'].includes(item.type))
)
const isDocumentType = computed(() => form.type === 'document')

async function fetchModels() {
	const res = await aiModel.postModelPageList({
		keyword: '',
		type: '',
		source: '',
		pageIndex: 1,
		pageSize: 200
	})
	if (res?.isSuccess) {
		modelList.value = (res.result?.model || []) as KnowledgeModelOption[]
		applyModelDefaults()
	}
}

async function fetchStorageProviders() {
	const res = await storageProvider.postStorageProviderEngines({})
	if (res?.isSuccess) {
		storageProviderOptions.value = (res.result || [])
			.filter((item) => {
				return item.allowed && item.available
			})
			.map((item) => ({ label: item.name, value: item.name }))
		applyModelDefaults()
	}
}

function applyModelDefaults() {
	if (!form.embedding_model_id && embeddingModels.value.length) {
		form.embedding_model_id = embeddingModels.value[0]!.id
	}
	if (!form.summary_model_id && summaryModels.value.length) {
		form.summary_model_id = summaryModels.value[0]!.id
	}
	if (!form.wiki_synthesis_model_id && summaryModels.value.length) {
		form.wiki_synthesis_model_id = summaryModels.value[0]!.id
	}
	if (vlmModels.value.length) {
		if (!form.vlm_model_id) form.vlm_model_id = vlmModels.value[0]!.id
	} else {
		form.vlm_enabled = false
		form.vlm_model_id = ''
	}
	if (asrModels.value.length) {
		if (!form.asr_model_id) form.asr_model_id = asrModels.value[0]!.id
	} else {
		form.asr_enabled = false
		form.asr_model_id = ''
		form.asr_language = ''
	}
}

async function hydrateSelectedModels() {
	const selectedIds = [
		form.embedding_model_id,
		form.summary_model_id,
		form.vlm_model_id,
		form.asr_model_id,
		form.wiki_synthesis_model_id
	].filter(Boolean)
	const missingIds = Array.from(new Set(selectedIds)).filter(
		(id) => !modelList.value.some((item) => item.id === id)
	)
	if (!missingIds.length) return
	const results = await Promise.all(
		missingIds.map((id) =>
			aiModel.postModelInfo({ id }).catch(() => null)
		)
	)
	const hydratedModels = results
		.filter((res): res is NonNullable<typeof res> => !!res?.isSuccess && !!res.result)
		.map((res) => res.result as KnowledgeModelOption)
	if (hydratedModels.length) {
		modelList.value = [...modelList.value, ...hydratedModels].filter(
			(item, index, list) => list.findIndex((candidate) => candidate.id === item.id) === index
		)
	}
}

const rules = {
	name: [{ required: true, message: '请输入知识库名称', trigger: 'blur' }],
	type: [{ required: true, message: '请选择知识库类型', trigger: 'change' }],
	embedding_model_id: [{ required: true, message: '请选择 Embedding 模型', trigger: 'change' }],
	summary_model_id: [{ required: true, message: '请选择摘要模型', trigger: 'change' }]
}

function buildModelLabel(item: KnowledgeModelOption) {
	const title = item.title?.trim()
	return title ? `${title} (${item.name})` : item.name
}

function formatSeparatorLabel(value: string) {
	if (value === '\n\n') return '\\n\\n'
	if (value === '\n') return '\\n'
	if (value === ' ') return '[space]'
	return value
}

function toggleSeparator(value: string) {
	if (form.separators.includes(value)) {
		form.separators = form.separators.filter((item) => item !== value)
		return
	}
	form.separators = [...form.separators, value]
}

function handleKnowledgeBaseTypeChange(type: KnowledgeBaseForm['type']) {
	activeTab.value = 'basic'
	if (type === 'faq') {
		form.graph_enabled = false
		form.keyword_enabled = true
		form.vector_enabled = true
		form.wiki_enabled = false
		form.vlm_enabled = false
		form.asr_enabled = false
		form.question_generation_enabled = false
		form.faq_index_mode = 'question_only'
		form.faq_question_index_mode = 'separate'
		return
	}

	form.graph_enabled = false
	form.keyword_enabled = true
	form.vector_enabled = true
	form.wiki_enabled = false
	form.question_generation_enabled = true
	form.question_count = 3
	form.chunk_size = 512
	form.chunk_overlap = 100
	form.separators = [...DEFAULT_SEPARATORS]
	form.parser_engine_rules = cloneParserRules()
	form.enable_parent_child = true
	form.parent_chunk_size = 4096
	form.child_chunk_size = 384
	form.storage_provider = 'local'
	form.wiki_extraction_granularity = 'standard'
	form.wiki_max_pages_per_ingest = 0
	applyModelDefaults()
}

function resetForm() {
	Object.assign(form, createDefaultForm())
	activeTab.value = 'basic'
	applyModelDefaults()
}

function handleOpen() {
	activeTab.value = 'basic'
}

function openCreateDrawer() {
	editingId.value = ''
	resetForm()
	drawerVisible.value = true
}

async function openEditDrawer(id: string) {
	editingId.value = id
	resetForm()
	const res = await knowledge.postKnowledgeBaseInfo({ id })
	if (!res?.isSuccess) return

	const detail = res.result
	Object.assign(form, {
		name: detail.name,
		description: detail.description || '',
		type: (detail.type || 'document') as KnowledgeBaseForm['type'],
		embedding_model_id: detail.embedding_model_id || '',
		summary_model_id: detail.summary_model_id || '',
		faq_index_mode: detail.faq_config?.index_mode || 'question_only',
		faq_question_index_mode: detail.faq_config?.question_index_mode || 'separate',
		vlm_enabled: detail.vlm_config?.enabled ?? false,
		vlm_model_id: detail.vlm_config?.model_id || '',
		asr_enabled: detail.asr_config?.enabled ?? false,
		asr_model_id: detail.asr_config?.model_id || '',
		asr_language: detail.asr_config?.language || '',
		graph_enabled: detail.indexing_strategy?.graph_enabled ?? false,
		keyword_enabled: true,
		vector_enabled: true,
		wiki_enabled: detail.indexing_strategy?.wiki_enabled ?? false,
		question_generation_enabled: detail.question_generation_config?.enabled ?? true,
		question_count: detail.question_generation_config?.question_count ?? 3,
		chunk_size: detail.chunking_config?.chunk_size ?? 512,
		chunk_overlap: detail.chunking_config?.chunk_overlap ?? 100,
		separators: detail.chunking_config?.separators?.length
			? [...detail.chunking_config.separators]
			: [...DEFAULT_SEPARATORS],
		parser_engine_rules: cloneParserRules(detail.chunking_config?.parser_engine_rules),
		enable_parent_child: detail.chunking_config?.enable_parent_child ?? true,
		parent_chunk_size: detail.chunking_config?.parent_chunk_size ?? 4096,
		child_chunk_size: detail.chunking_config?.child_chunk_size ?? 384,
		storage_provider:
			detail.storage_provider_config?.provider || detail.storage_config?.provider || 'local',
		wiki_extraction_granularity: detail.wiki_config?.extraction_granularity || 'standard',
		wiki_max_pages_per_ingest: detail.wiki_config?.max_pages_per_ingest ?? 0,
		wiki_synthesis_model_id: detail.wiki_config?.synthesis_model_id || ''
	})
	await hydrateSelectedModels()
	applyModelDefaults()
	drawerVisible.value = true
}

function buildCommonPayload() {
	const keywordEnabled = true
	const vectorEnabled = true
	const wikiEnabled = form.wiki_enabled
	const vlmEnabled = vectorEnabled && form.vlm_enabled
	const asrEnabled = vectorEnabled && form.asr_enabled
	const questionGenerationEnabled = vectorEnabled && form.question_generation_enabled

	return {
		name: form.name,
		description: form.description,
		indexing_strategy: {
			graph_enabled: form.graph_enabled,
			keyword_enabled: keywordEnabled,
			vector_enabled: vectorEnabled,
			wiki_enabled: wikiEnabled
		},
		embedding_model_id: form.embedding_model_id,
		summary_model_id: form.summary_model_id,
		wiki_config: {
			extraction_granularity: form.wiki_extraction_granularity,
			max_pages_per_ingest: form.wiki_max_pages_per_ingest,
			synthesis_model_id: wikiEnabled
				? form.wiki_synthesis_model_id || form.summary_model_id
				: form.summary_model_id
		},
		chunking_config: {
			chunk_size: form.chunk_size,
			chunk_overlap: form.chunk_overlap,
			separators: form.separators.length ? form.separators : [...DEFAULT_SEPARATORS],
			parser_engine_rules: cloneParserRules(form.parser_engine_rules),
			enable_parent_child: form.enable_parent_child,
			parent_chunk_size: form.parent_chunk_size,
			child_chunk_size: form.child_chunk_size
		},
		vlm_config: {
			model_id: vlmEnabled ? form.vlm_model_id : '',
			enabled: vlmEnabled
		},
		asr_config: {
			model_id: asrEnabled ? form.asr_model_id : '',
			language: asrEnabled ? form.asr_language : '',
			enabled: asrEnabled
		},
		storage_provider_config: {
			provider: form.storage_provider
		},
		storage_config: {
			provider: form.storage_provider
		},
		question_generation_config: {
			enabled: questionGenerationEnabled,
			question_count: form.question_count
		}
	}
}

function buildPayload() {
	const commonPayload = buildCommonPayload()

	if (form.type === 'faq') {
		return {
			...commonPayload,
			type: form.type,
			faq_config: {
				index_mode: form.faq_index_mode,
				question_index_mode: form.faq_question_index_mode
			}
		}
	}

	return {
		...commonPayload,
		type: form.type
	}
}

async function formValidate(formInstance: any) {
	return formInstance
		?.validate()
		.then(() => true)
		.catch(() => false)
}

async function submitForm() {
	const valid = await formValidate(formRef.value)
	if (!valid) return

	submitLoading.value = true
	try {
		const payload = buildPayload()
		if (editingId.value) {
			await knowledge.postKnowledgeBaseUpdate({
				id: editingId.value,
				...(payload as any)
			} as any)
			ElMessage.success('知识库已更新')
		} else {
			await knowledge.postKnowledgeBaseCreate(payload as any)
			ElMessage.success('知识库已创建')
		}
		drawerVisible.value = false
		emit('refresh')
	} catch {
		ElMessage.error('保存失败')
	} finally {
		submitLoading.value = false
	}
}

defineExpose({
	openCreateDrawer,
	openEditDrawer,
	resetForm,
	close: () => {
		resetForm()
		drawerVisible.value = false
	}
})

onMounted(async () => {
	await fetchModels()
	await fetchStorageProviders()
	resetForm()
})
</script>

<style lang="less">
.knowledge-modal {
	--agent-surface: #ffffff;
	--agent-surface-soft: #f7f8fc;
	--agent-border: rgba(148, 163, 184, 0.22);
	--agent-border-strong: rgba(148, 163, 184, 0.38);
	--agent-text: #0f172a;
	--agent-text-soft: #475569;
	--agent-accent: #14532d;
	--agent-shadow: 0 20px 45px rgba(15, 23, 42, 0.08);
	height: 100vh;
	display: flex;
	flex-direction: column;
	background:
		radial-gradient(circle at top left, rgba(20, 83, 45, 0.08), transparent 30%),
		radial-gradient(circle at top right, rgba(15, 23, 42, 0.05), transparent 24%), #eff3f8;

	.el-dialog__body {
		flex: 1;
		overflow: auto;
		padding: 24px;
	}

	.el-dialog__header {
		padding: 20px 24px 0;
	}

	.el-dialog__title {
		font-size: 22px;
		font-weight: 700;
		color: var(--agent-text);
		letter-spacing: -0.02em;
	}

	.el-dialog__footer {
		padding: 0 24px 24px;
	}

	.modal-wrap {
		margin: 0 auto;
		width: min(1360px, 100%);
	}

	.knowledge-form {
		max-width: 100%;
	}

	:deep(.settings-tabs > .el-tabs__header) {
		margin-right: 20px;
	}

	:deep(.settings-tabs > .el-tabs__content) {
		overflow: visible;
	}

	:deep(.settings-tabs .el-tabs__item) {
		height: auto;
		padding: 14px 18px;
		line-height: 1.4;
		border-radius: 12px;
	}

	:deep(.settings-tabs .el-tabs__item.is-active) {
		background: rgba(20, 83, 45, 0.1);
		color: var(--agent-accent);
	}

	:deep(.settings-tabs .el-tab-pane) {
		min-height: calc(100vh - 220px);
		border-radius: 20px;
		border: 1px solid rgba(255, 255, 255, 0.65);
		background:
			linear-gradient(180deg, rgba(255, 255, 255, 0.96), rgba(248, 250, 252, 0.92)),
			var(--agent-surface);
		box-shadow: var(--agent-shadow);
	}

	.tab-intro {
		padding: 0 20px;
		font-size: 16px;
		color: rgba(0, 0, 0, 0.9);
	}

	.collapse-body {
		padding: 20px;
	}

	.switch-wrap,
	.slider-wrap {
		width: 100%;
	}

	.switch-wrap {
		.field-tip {
			margin-top: 0;
		}
	}

	.selection-segmented {
		align-self: flex-start;
		width: fit-content;
		max-width: 100%;
		margin-bottom: 8px;
	}

	.selection-segmented :deep(.el-segmented) {
		width: fit-content;
		max-width: 100%;
	}

	.selection-segmented :deep(.el-segmented__group) {
		width: auto;
	}

	.field-tip {
		margin-top: 8px;
		font-size: 13px;
		line-height: 1.7;
		color: var(--agent-text-soft);
	}

	.compact-tip {
		margin-bottom: 16px;
	}

	.index-strategy-list {
		display: grid;
		gap: 10px;
		margin-top: 16px;
	}

	.form-grid {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 0 12px;
	}

	.subsection {
		margin-top: 12px;
		padding: 16px;
		border: 1px solid var(--agent-border);
		border-radius: 14px;
		background: rgba(247, 248, 252, 0.8);
	}

	.subsection-title {
		margin-bottom: 14px;
		font-size: 14px;
		font-weight: 600;
		color: var(--agent-text);
	}

	.subsection-tip {
		margin: -4px 0 0;
		font-size: 13px;
		line-height: 1.7;
		color: var(--agent-text-soft);
	}

	.parser-rule-list {
		display: grid;
		gap: 12px;
	}

	.parser-rule-item {
		display: grid;
		grid-template-columns: minmax(0, 1fr) 220px;
		gap: 12px;
		align-items: center;
	}

	.parser-rule-item__types {
		padding: 10px 14px;
		border: 1px solid var(--agent-border);
		border-radius: 12px;
		background: rgba(247, 248, 252, 0.8);
		color: var(--agent-text);
		line-height: 1.5;
	}

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

	.separator-chip {
		display: inline-flex;
		align-items: center;
		justify-content: space-between;
		gap: 8px;
		width: 100%;
		padding: 10px 12px;
		border: 1px solid var(--agent-border);
		border-radius: 10px;
		background: rgba(247, 248, 252, 0.9);
		color: var(--agent-text);
		font-size: 13px;
		text-align: left;
		cursor: pointer;
		transition: all 0.2s ease;
	}

	.separator-chip:hover {
		border-color: var(--agent-border-strong);
		background: rgba(240, 245, 250, 0.95);
	}

	.separator-chip--active {
		border-color: rgba(20, 83, 45, 0.35);
		background: rgba(20, 83, 45, 0.08);
		color: var(--agent-accent);
	}

	.separator-chip__value {
		font-size: 12px;
		color: var(--agent-text-soft);
	}

	.separator-chip__close {
		flex-shrink: 0;
		font-size: 16px;
		line-height: 1;
		opacity: 0.6;
	}

	.drawer-footer {
		display: flex;
		justify-content: flex-end;
		gap: 10px;
		padding-top: 6px;
	}

	@media (max-width: 768px) {
		.el-dialog__body {
			padding: 16px;
		}

		:deep(.settings-tabs) {
			display: block;
		}

		:deep(.settings-tabs > .el-tabs__header) {
			margin-right: 0;
			margin-bottom: 16px;
		}

		.form-grid,
		.parser-rule-item,
		.separator-grid {
			grid-template-columns: 1fr;
		}
	}
}
</style>
