<template>
	<el-scrollbar class="w-full box-border p-12px">
		<div class="qc-setter">
			<section class="section-block">
				<div class="w-full flex items-center justify-between beautify">
					<label class="text-14px font-bold text-gray-700">{{ texts.input }}</label>
				</div>
				<VarInput v-model="formData.query" class="w-full" placeholder="输入/选择变量" />
			</section>

			<!-- 分类 -->
			<section class="section-block">
				<div class="section-header">
					<label class="section-title">{{ texts.classes }}</label>
					<el-button type="primary" link @click="handleAddClass">
						{{ texts.addClass }}
					</el-button>
				</div>

				<div v-if="!formData.classes?.length" class="empty-state">
					<div class="empty-desc">{{ texts.empty }}</div>
				</div>

				<VueDraggable v-else v-model="formData.classes" :animation="150" handle=".handle" @end="handleSortEnd"
					class="class-list">
					<div v-for="(item, index) in formData.classes" :key="item.id" class="class-card">
						<div class="class-card__header">
							<div class="class-card__title">
								<Icon icon="lucide:grip-vertical" :size="16" class="handle drag-icon" />
								<span class="class-index">{{ item.name }}</span>
							</div>
							<div class="class-card__actions">
								<IconButton link icon="lucide:copy" class="text-#667085" @click="handleDuplicateClass(index)" />
								<IconButton link icon="lucide:trash-2" class="text-#f04438 ml-0!" @click="handleRemoveClass(index)" />
							</div>
						</div>

						<div class="class-card__body">
							<VarInput v-model="item.instruction" class="w-full" :rows="3"
								:placeholder="texts.classInstructionPlaceholder" />
						</div>
					</div>
				</VueDraggable>
			</section>

			<!-- 模型设置 -->
			<section class="section-block">
				<div class="section-header">
					<label class="section-title">{{ texts.modelSettings }}</label>
				</div>
				<div class="advanced-item">
					<el-select v-model="formData.model_id" filterable remote reserve-keyword clearable class="w-full"
						:remote-method="searchChatModels" :loading="modelsLoading" :placeholder="texts.modelPlaceholder">
						<el-option v-for="model in chatModels" :key="model.id" :label="modelLabel(model)" :value="model.id" />
					</el-select>
					<div class="advanced-tip">{{ texts.modelTip }}</div>
				</div>
			</section>

			<section class="section-block">
				<el-collapse>
					<el-collapse-item name="1">
						<template #title>
							<div class="flex items-center justify-between beautify">
								<label class="text-14px font-bold text-gray-700">{{
									texts.advancedSettings
								}}</label>
							</div>
						</template>
						<div class="advanced-item">
							<div class="advanced-label">{{ texts.instruction }}</div>
							<VarInput v-model="formData.instruction" class="w-full" :rows="3" placeholder="输入/选择变量" />
						</div>
					</el-collapse-item>

					<el-collapse-item name="2">
						<template #title>
							<div class="flex items-center justify-between beautify">
								<label class="text-14px font-bold text-gray-700">输出变量</label>
							</div>
						</template>
						<ul>
							<li v-for="output in formData.outputs" :key="output.name">
								<div>
									<span class="text-#333">{{ output.name }}</span>
									<span class="text-#999 ml-8px">{{ output.type }}</span>
								</div>
								<div class="text-#666">{{ output.describe }}</div>
							</li>
						</ul>
					</el-collapse-item>
				</el-collapse>
			</section>
			<NodeRuntimeConfig v-model="formData" />
		</div>
	</el-scrollbar>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { VueDraggable } from 'vue-draggable-plus'
import { Icon, IconButton } from '@repo/ui'

import NodeRuntimeConfig from '@/nodes/_base/NodeRuntimeConfig.vue'
import VarInput from '@/nodes/_base/VarInput.vue'
import { useI18n } from '@/composables/useI18n'
import { useSetterModel } from '../_shared/useSetterModel'
import { aiModel } from "@repo/api-service"

import type { QuestionClassifierData, ClassItem } from './index'

type QuestionClassifierModelItem = NonNullable<
	Awaited<ReturnType<typeof aiModel.postModelPageList>>['result']
>['model'][number]

interface Emits {
	(e: 'update', value: QuestionClassifierData): void
}

const props = defineProps<{
	data: QuestionClassifierData
	id: string
}>()

const emit = defineEmits<Emits>()
const { t } = useI18n()

const texts = computed(() => ({
	input: t('pages.iterationSetter.input'),
	classes: t('pages.questionClassifierSetter.classes'),
	addClass: t('pages.questionClassifierSetter.addClass'),
	empty: t('pages.questionClassifierSetter.empty'),
	classPrefix: t('pages.questionClassifierSetter.classPrefix'),
	classNamePlaceholder: t('pages.questionClassifierSetter.classNamePlaceholder'),
	classInstructionPlaceholder: t('pages.questionClassifierSetter.classInstructionPlaceholder'),
	advancedSettings: t('pages.questionClassifierSetter.advancedSettings'),
	instruction: t('pages.questionClassifierSetter.instruction'),
	instructionPlaceholder: t('pages.questionClassifierSetter.instructionPlaceholder'),
	modelSettings: t('pages.questionClassifierSetter.modelSettings'),
	model: t('pages.questionClassifierSetter.model'),
	modelPlaceholder: t('pages.questionClassifierSetter.modelPlaceholder'),
	modelTip: t('pages.questionClassifierSetter.modelTip')
}))

const formData = useSetterModel<QuestionClassifierData>(props, emit)
const chatModels = ref<QuestionClassifierModelItem[]>([])
const modelsLoading = ref(false)

const modelLabel = (item: QuestionClassifierModelItem) => {
	const title = item.title?.trim()
	return title ? `${title} (${item.name})` : item.name
}

const mergeModels = (items: QuestionClassifierModelItem[]) => {
	const modelMap = new Map<string, QuestionClassifierModelItem>()
	chatModels.value.forEach((item) => {
		if (item.id) modelMap.set(item.id, item)
	})
	items.forEach((item) => {
		if (item.id) modelMap.set(item.id, item)
	})
	chatModels.value = Array.from(modelMap.values())
}

const hydrateSelectedModel = async () => {
	const modelId = formData.value?.model_id
	if (!modelId || chatModels.value.some((item) => item.id === modelId)) return
	const res = await aiModel.postModelInfo({ id: modelId })
	if (res?.isSuccess && res.result) {
		mergeModels([res.result as QuestionClassifierModelItem])
	}
}

const fetchChatModels = async (keyword = '') => {
	const res = await aiModel.postModelPageList({
		keyword: keyword.trim(),
		type: 'KnowledgeQA',
		source: '',
		pageIndex: 1,
		pageSize: 50
	})
	if (res?.isSuccess) {
		mergeModels((res.result?.model || []) as QuestionClassifierModelItem[])
	}
}

const searchChatModels = async (keyword: string) => {
	modelsLoading.value = true
	try {
		await fetchChatModels(keyword)
		await hydrateSelectedModel()
	} finally {
		modelsLoading.value = false
	}
}

const getId = () => {
	const ids = formData.value.classes.map((c) => c.id.split('_')[1]).map(Number)
	const maxId = Math.max(...ids, 0)
	return props.id + '_' + (maxId + 1)
}

const getClassName = (index: number) => `${texts.value.classPrefix}${index}`

const createClassItem = (index?: number): ClassItem => ({
	id: index ? `${props.id}_${index}` : getId(),
	name: index ? getClassName(index) : '',
	instruction: ''
})

const reorderClasses = () => {
	formData.value.classes = (formData.value.classes || []).map((item, index) => ({
		...item,
		id: `${props.id}_${index + 1}`,
		name: getClassName(index + 1)
	}))
}

const ensureDefaults = () => {
	formData.value.type ||= 'question-classifier'
	formData.value.classes ||= [createClassItem(1), createClassItem(2), createClassItem(3)]
	formData.value.instruction ||= ''
	if (typeof formData.value.model_id !== 'string') {
		formData.value.model_id = ''
	}
	reorderClasses()
}

ensureDefaults()

onMounted(async () => {
	await searchChatModels('')
})

const handleAddClass = () => {
	if (!formData.value.classes) {
		formData.value.classes = []
	}
	formData.value.classes.push(createClassItem())
	reorderClasses()
}

const handleRemoveClass = (index: number) => {
	formData.value.classes.splice(index, 1)
	reorderClasses()
}

const handleDuplicateClass = (index: number) => {
	const source = formData.value.classes[index]
	if (!source) return
	const copy: ClassItem = {
		...source,
		id: `class-${Date.now()}-${index}`
	}
	formData.value.classes.splice(index + 1, 0, copy)
	reorderClasses()
}

const handleSortEnd = () => {
	reorderClasses()
}
</script>

<style scoped lang="less">
.qc-setter {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.section-block {
	padding-bottom: 16px;
}

.section-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: 12px;
}

.section-title {
	font-size: 14px;
	font-weight: 700;
	color: #374151;
}

.advanced-item {
	display: flex;
	flex-direction: column;
	gap: 8px;
	margin-bottom: 14px;
}

.advanced-label {
	font-size: 13px;
	font-weight: 600;
	color: #374151;
}

.advanced-tip {
	font-size: 12px;
	color: #667085;
	line-height: 1.6;
}

.empty-state {
	padding: 18px 16px;
	border-radius: 12px;
	border: 1px dashed #d0d5dd;
	background: #f8fafc;
}

.empty-desc {
	font-size: 12px;
	color: #667085;
}

.class-list {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.class-card {
	padding: 14px 16px;
	border-radius: 14px;
	border: 1px solid #eaecf0;
	background: #fff;
	box-shadow: 0 6px 18px rgba(16, 24, 40, 0.06);
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.class-card__header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
}

.class-card__title {
	display: flex;
	align-items: center;
	gap: 8px;
	flex: 1;
	min-width: 0;
}

.drag-icon {
	color: #98a2b3;
	cursor: move;
	flex-shrink: 0;
}

.class-index {
	font-size: 13px;
	color: #667085;
}

.class-name-input {
	flex: 1;
}

.class-card__actions {
	display: flex;
	align-items: center;
	gap: 4px;
}

.class-card__body {
	:deep(.el-textarea__inner) {
		min-height: 60px;
	}
}

.advanced-item {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.advanced-label {
	font-size: 13px;
	font-weight: 600;
	color: #374151;
}
</style>
