<template>
	<div class="assist-input-wrapper flex flex-col" :class="{ agent: isAgentMode }">
		<div class="animate-container flex-1 flex flex-col">
			<div class="scroll-content flex-col">
				<InputImagePreviewList
					:uploaded-images="uploadedImages"
					:quote-list="quoteList"
					@preview="previewImage"
					@remove="removeImage"
				/>
				<InputEditor
					:show-placeholder="showPlaceholder"
					:placeholder="$t('Input.placeholder')"
					:is-agent-mode="isAgentMode"
					@ready="setEditorElement"
					@input="handleEditorInput"
					@paste="handleEditorPaste"
					@keydown="handleKeyDown"
				/>
			</div>

			<InputToolbar
				v-model:type-value="typeValue"
				v-model:area-value="areaValue"
				v-model:style-value="styleValue"
				v-model:setting-options="settingOptions"
				:is-agent-mode="isAgentMode"
				:generating="generating"
				:type-options="typeOptions"
				:area-options="areaOptions"
				:style-options="styleOptions"
				:type-placeholder="$t('Input.typePlaceholder')"
				:area-placeholder="$t('Input.areaPlaceholder')"
				:style-placeholder="$t('Input.stylePlaceholder')"
				:style-title="$t('Input.chooseStyle')"
				:setting-title="$t('Input.styleTitle')"
				:confirm-text="$t('Input.confirm')"
				:create-text="$t('Input.createProject')"
				:parameters-disabled="isReportSelected"
				:translate="translate"
				@file-change="handleFileChange"
				@toggle-report="handleToggleReportTag"
				@create="handleCreateProject"
				@send="handleSendAgent"
			/>
		</div>

		<ReportShortcutButton
			v-if="!isAgentMode"
			:is-cn="isCn"
			:label="$t('Input.trendingReport')"
			@click="handleToggleReportTag"
		/>
		<Preview v-model="showPreview" :url="previewUrl" />
	</div>
</template>

<script setup lang="ts">
	import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
	import { areaList } from '@/utils/area'
	import { useI18n } from 'vue-i18n'
	import { useRouter } from 'vue-router'
	import { useAgentStore, useProjectStore } from '@/stores'
	import { createProject } from '@/api/agent'
	import MyEvent from '@/utils/myEvent'
	import Preview from '@/components/Preview/Preview.vue'
	import InputEditor from './input/InputEditor.vue'
	import InputImagePreviewList from './input/InputImagePreviewList.vue'
	import InputToolbar from './input/InputToolbar.vue'
	import ReportShortcutButton from './input/ReportShortcutButton.vue'
	import {
		createSettingOptions,
		createStyleOptions,
		createTypeOptions,
		optionTagOrder
	} from './input/options'
	import { useInputEditor } from './input/useInputEditor'
	import { useInputImages } from './input/useInputImages'
	import type { OptionItem, OptionTagKind, ParameterTag, SettingOption } from './input/types'

	const router = useRouter()
	const agentStore = useAgentStore()
	const projectStore = useProjectStore()

	const props = withDefaults(
		defineProps<{
			isAgentMode?: boolean
			generating?: boolean
		}>(),
		{
			isAgentMode: false,
			generating: false
		}
	)

	const emits = defineEmits(['send', 'pause'])

	const { t, locale } = useI18n()
	const translate = (key: string) => t(key)

	const isCn = computed(() => {
		return locale.value === 'CHINESE_SIMPLIFIED'
	})
	const isAgentModeRef = computed(() => props.isAgentMode)

	const typeValue = ref<string>('')
	const areaValue = ref<string>('')
	const styleValue = ref<string>('')
	const settingOptions = ref<SettingOption[]>(createSettingOptions())
	const typeOptions = ref<OptionItem[]>(createTypeOptions())
	const areaOptions = ref<OptionItem[]>(areaList)
	const styleOptions = ref<OptionItem[]>(createStyleOptions())

	const {
		inputValue,
		reportTags,
		optionTagKinds,
		showPlaceholder,
		setEditorElement,
		focusEditor,
		stopReportTypewriter,
		addReportTag,
		toggleReportTag,
		handleEditorInput,
		handleEditorPaste,
		handleKeyDown,
		autoResizeEditor,
		syncOptionTag,
		syncAllOptionTags,
		clearEditorText,
		resetOptionTags
	} = useInputEditor({
		isAgentMode: isAgentModeRef,
		t: translate,
		typeValue,
		areaValue,
		styleValue,
		typeOptions,
		areaOptions,
		styleOptions,
		onSubmit: () => {
			if (props.isAgentMode) {
				handleSendAgent()
				return
			}
			handleCreateProject()
		}
	})

	const {
		uploadedImages,
		quoteList,
		showPreview,
		previewUrl,
		handleFileChange,
		removeImage,
		previewImage,
		handleQuote,
		clearImages
	} = useInputImages(focusEditor)

	const isReportSelected = computed(() => {
		return reportTags.value.some((tag) => tag.parentNode)
	})

	const clearParameterValues = () => {
		typeValue.value = ''
		areaValue.value = ''
		styleValue.value = ''
	}

	const handleToggleReportTag = () => {
		const shouldSelectReport = !isReportSelected.value
		toggleReportTag()
		if (shouldSelectReport) {
			clearParameterValues()
		}
	}

	const getTranslatedOptionLabel = (options: OptionItem[], value: string) => {
		const option = options.find((item) => item.value === value)
		return option ? translate(option.label) : value
	}

	const getParameterTagLabel = (kind: OptionTagKind) => {
		if (kind === 'type') {
			return getTranslatedOptionLabel(typeOptions.value, typeValue.value)
		}
		if (kind === 'area') {
			return getTranslatedOptionLabel(areaOptions.value, areaValue.value)
		}

		const option = styleOptions.value.find((item) => item.value === styleValue.value)
		return option?.label || styleValue.value
	}

	const hasParameterValue = (kind: OptionTagKind) => {
		if (kind === 'type') return Boolean(typeValue.value)
		if (kind === 'area') return Boolean(areaValue.value)
		return Boolean(styleValue.value)
	}

	const selectedParameterTags = computed<ParameterTag[]>(() => {
		const currentKinds = optionTagKinds.value.filter(hasParameterValue)
		const missingKinds = optionTagOrder.filter((kind) => {
			return hasParameterValue(kind) && !currentKinds.includes(kind)
		})

		return [...currentKinds, ...missingKinds].map((kind) => ({
			kind,
			label: getParameterTagLabel(kind)
		}))
	})

	watch(inputValue, () => {
		nextTick(() => {
			autoResizeEditor()
		})
	})

	watch(typeValue, () => {
		nextTick(() => {
			syncOptionTag('type')
		})
	})

	watch(areaValue, () => {
		nextTick(() => {
			syncOptionTag('area')
		})
	})

	watch(styleValue, () => {
		nextTick(() => {
			syncOptionTag('style')
		})
	})

	watch(locale, () => {
		nextTick(() => {
			syncAllOptionTags()
		})
	})

	const handleSendAgent = async () => {
		if (props.generating) {
			emits('pause')
			return
		}
		if (!inputValue.value.trim()) return
		const imageUrlList = uploadedImages.value.map((item) => item.path)

		const payload: {
			text: string
			images: any[]
			tempImages: typeof uploadedImages.value
			quoteList: string[]
			parameterTags: ParameterTag[]
			useReport?: boolean
		} = {
			text: inputValue.value.trim(),
			images: imageUrlList,
			tempImages: uploadedImages.value,
			quoteList: quoteList.value,
			parameterTags: selectedParameterTags.value
		}
		if (reportTags.value.length > 0) {
			payload.useReport = true
		}
		emits('send', payload)
		clearImages()
		clearEditorText()
	}

	const handleCreateProject = async () => {
		if (!inputValue.value.trim()) {
			return
		}

		const params = {
			type: typeValue.value || '',
			area: areaValue.value || '',
			style: styleValue.value || '',
			useReport: reportTags.value.length > 0,
			temperature: 0.7
		}
		const projectres = await createProject({
			...params,
			region: params.area
		} as any)
		projectStore.setId(projectres)
		MyEvent.emit('updateProjectList')
		agentStore.setInitialProjectData({
			text: inputValue.value.trim(),
			images: uploadedImages.value.map((item) => item.path),
			tempImages: uploadedImages.value,
			needSuggestion: false,
			quoteList: quoteList.value,
			parameterTags: selectedParameterTags.value,
			...params
		})

		router.push({
			path: `/home/agent/${projectres}`,
			query: {
				type: params.type,
				area: params.area,
				style: params.style,
				useReport: String(params.useReport),
				temperature: String(params.temperature)
			}
		})
		uploadedImages.value = []
	}

	const handleInitInput = () => {
		inputValue.value = ''
		uploadedImages.value = []
		quoteList.value = []
		toggleReportTag(true)
		clearEditorText()
		resetOptionTags()
		nextTick(() => {
			syncAllOptionTags()
		})
	}

	onMounted(() => {
		MyEvent.add('quote', handleQuote)
		MyEvent.add('projectChange', handleInitInput)
		nextTick(() => {
			syncAllOptionTags()
			autoResizeEditor()
		})
	})

	onUnmounted(() => {
		stopReportTypewriter()
		MyEvent.remove('quote', handleQuote)
		MyEvent.remove('projectChange', handleInitInput)
	})

	defineExpose({
		addReportTag
	})
</script>

<style lang="less" scoped>
	.assist-input-wrapper {
		min-height: 23.5rem;
		max-height: 43.5rem;
		width: 106.3rem;
		margin: 0 auto;
		padding: 0;
		position: relative;

		.animate-container {
			overflow-y: hidden;
		}

		&:not(.agent) .animate-container {
			box-shadow: 0px 0.5rem 1.4rem 0px #0000001a;
			transition: all 0.3s ease;
			border-radius: 2.8rem;
			background-color: #fff;
			border: 0.1rem solid #00000005;

			&:hover {
				box-shadow: 0px 0.5rem 3.36rem 2.2rem #f1ede999;
				transform: translateY(-1rem);
			}
		}

		.scroll-content {
			display: flex;
			flex-direction: column;
			flex: 1;
			overflow-y: auto;
			padding: 3.4rem 1.7rem 1.7rem;
		}

		&.agent {
			padding: 1.2rem;
			box-shadow: none;
			border-radius: 1.5rem;
			border: 0.1rem solid #0000001a;

			.scroll-content {
				padding: 0;
				flex: 1;
				overflow: auto;
			}
		}
	}
</style>
