<template>
	<div :style="containerStyle" @submit.prevent class="rounded-lg border shadow-sm bg-card text-card-foreground">
		<aurora-editor
			v-model="localModelValue"
			:extensions="mergedExtensions"
			:hideToolbar="hideToolbar"
			:hideMenubar="hideMenubar"
			:disabled="disabled"
			:maxHeight="maxHeight"
			:minHeight="minHeight"
			:output="output"
			:placeholder="placeholder"
		>
		</aurora-editor>
	</div>
</template>

<script setup lang="ts" name="aiEditorComponent">
import { computed, toRefs } from 'vue';
import { fetchEventSource } from '@microsoft/fetch-event-source';
import request from '/@/utils/request';
import { Session } from '/@/utils/storage';
import {
	Bold,
	BulletList,
	Italic,
	BaseKit,
	Underline,
	Strike,
	LineHeight,
	Image,
	History,
	Heading,
	CodeBlock,
	FontSize,
	Highlight,
	Table,
	Clear,
	Blockquote,
	Link,
	Color,
	Video,
	OrderedList,
	HorizontalRule,
	Fullscreen,
	TaskList,
	MoreMark,
	FormatPainter,
	SlashCommand,
	Indent,
	locale,
	ImportWord,
	Columns,
	TextAlign,
	ImageUpload,
	VideoUpload,
	FontFamily,
	FindAndReplace,
	Code,
	AI,
	Preview,
	Printer,
	AuroraEditor,
} from 'aurora-editor';
import 'aurora-editor/style.css';
import other from '/@/utils/other';
import { useThemeConfig } from '/@/stores/themeConfig';
import { storeToRefs } from 'pinia';

// 获取主题配置
const storesThemeConfig = useThemeConfig();
const { themeConfig } = storeToRefs(storesThemeConfig);

// 获取布局配置信息
const getThemeConfig = computed(() => {
	return themeConfig.value;
});

// 设置编辑器语言为简体中文
locale.setLang('zhHans');

// 定义组件 Props
const props = withDefaults(
	defineProps<{
		modelValue?: string; // 编辑器内容，用于 v-model
		width?: string | number; // 编辑器容器宽度
		maxHeight?: number; // 编辑器最大高度
		minHeight?: number; // 编辑器最小高度
		hideToolbar?: boolean; // 是否隐藏工具栏
		hideMenubar?: boolean; // 是否隐藏菜单栏
		disabled?: boolean; // 是否禁用编辑器
		customExtensions?: any[]; // 自定义扩展
		placeholder?: string; // 编辑器占位符文本
		characterLimit?: number; // 编辑器字符数限制
		enableImage?: boolean; // 是否启用图片功能
		enableVideo?: boolean; // 是否启用视频功能
		output?: string; // 是否启用输出功能
	}>(),
	{
		modelValue: '',
		width: '100%', // 默认宽度
		maxHeight: 800, // 默认最大高度
		minHeight: 800, // 默认最小高度
		hideToolbar: false, // 默认不隐藏工具栏
		hideMenubar: true, // 默认不隐藏菜单栏
		disabled: false, // 默认不禁用
		customExtensions: () => [], // 默认无自定义扩展
		placeholder: '', // 默认无占位符
		characterLimit: 50000, // 默认字符限制
		enableImage: false, // 默认禁用图片功能
		enableVideo: false, // 默认禁用视频功能
		output: 'html', // 默认输出 HTML
	}
);

// 提取props中的属性以直接在模板中使用，避免使用props.xxx语法
const { hideToolbar, hideMenubar, disabled, maxHeight, minHeight, output } = toRefs(props);

// 使用计算属性创建一个双向绑定的本地变量，避免直接修改props
const localModelValue = computed({
	get: () => props.modelValue,
	set: (value) => emit('update:modelValue', value),
});

// 定义emit
const emit = defineEmits<{
	'update:modelValue': [value: string];
}>();

// 计算编辑器容器样式
const containerStyle = computed(() => ({
	width: typeof props.width === 'number' ? `${props.width}px` : props.width, // 处理数字和字符串类型的宽度
}));

// 定义默认的编辑器扩展
const defaultExtensions = computed(() => {
	// Base configurations reused in both modes
	const baseKitConfig = {
		placeholder: {
			showOnlyCurrent: true,
			placeholder: props.placeholder,
		},
		characterCount: {
			limit: props.characterLimit,
		},
	};
	const aiConfig = {
		completions: AICompletions,
		shortcuts: [
			{
				label: '自定义选项',
				children: [
					{
						label: '重写文案',
						prompt:
							'Rewrite this content with no spelling mistakes, proper grammar, and with more descriptive language, using best writing practices without losing the original meaning.',
					},
				],
			},
		],
	};

	// Core extensions used in both modes (except Fullscreen which is conditional)
	const coreExtensions = [BaseKit.configure(baseKitConfig), AI.configure(aiConfig)];
	// Base list for the full editor experience
	let fullExtensions: any[] = [
		...coreExtensions,
		History,
		Columns,
		FormatPainter,
		Clear,
		Heading.configure({ spacer: true }),
		FontSize,
		FontFamily,
		Bold,
		Italic,
		Underline,
		Strike,
		MoreMark,
		Color.configure({ spacer: true }),
		Highlight,
		BulletList,
		OrderedList,
		TextAlign.configure({ types: ['heading', 'paragraph', 'image'], spacer: true }),
		Indent,
		LineHeight,
		TaskList.configure({
			spacer: true,
			taskItem: {
				nested: true,
			},
		}),
		Link,
		Blockquote,
		SlashCommand,
		HorizontalRule,
		CodeBlock,
		Table,
		Code,
		ImportWord.configure({
			upload: handleFileUpload,
		}),
		FindAndReplace.configure({ spacer: true }),
		Printer.configure({ pageTitle: getThemeConfig.value.globalTitle }),
		Preview,
		Fullscreen, // Fullscreen is also part of the full set
	];

	// Conditionally add image extensions
	if (props.enableImage) {
		fullExtensions.push(
			Image, // 图片
			ImageUpload.configure({
				// 图片上传配置
				upload: (file: File) => {
					return new Promise<string>((resolve) => {
						setTimeout(() => {
							const fileUrl = URL.createObjectURL(file);
							resolve(fileUrl);
						}, 1000);
					});
				},
			})
		);
	}

	// Conditionally add video extensions
	if (props.enableVideo) {
		fullExtensions.push(
			Video, // 视频
			VideoUpload.configure({
				// 视频上传配置
				upload: handleFileUpload,
			})
		);
	}

	return fullExtensions;
});

// 合并默认扩展和自定义扩展
const mergedExtensions = computed(() => {
	return [...defaultExtensions.value, ...props.customExtensions];
});

// 统一文件上传处理 (视频、Word导入等)
async function handleFileUpload(files: File[]) {
	// 生成预览 URL
	const uploads = files.map((file) => ({
		src: URL.createObjectURL(file),
		alt: file.name,
	}));
	// 模拟上传延迟
	await new Promise((resolve) => setTimeout(resolve, 1000));
	// 返回上传结果 (实际应返回服务器 URL)
	return Promise.resolve(uploads);
}

// AI 补全处理函数 (使用 Server-Sent Events)
async function AICompletions(history: Array<{ role: string; content: string }> = [], signal?: AbortSignal): Promise<ReadableStream> {
	try {
		// 构建后端 API 地址
		const backendApiUrl = `${request.defaults.baseURL}${other.adaptationUrl('/knowledge/completions/text')}`;
		// 获取认证信息
		const token = Session.getToken();
		const tenantId = Session.getTenant();

		// 准备发送到后端的消息 (假设后端处理系统提示)
		const messagesToSend = history;

		// 创建 ReadableStream 用于流式传输
		let streamController: ReadableStreamDefaultController<any>;
		const stream = new ReadableStream({
			start(controller) {
				streamController = controller; // 保存控制器以推送数据
			},
			cancel() {
				// 处理流取消的逻辑 (例如，清理资源)
			},
		});

		// 使用 fetchEventSource 发起 SSE 请求
		fetchEventSource(backendApiUrl, {
			method: 'POST', // 请求方法
			headers: {
				// 请求头
				'Content-Type': 'application/json',
				Authorization: `Bearer ${token}`, // 认证 Token
				'TENANT-ID': tenantId, // 租户 ID
			},
			body: JSON.stringify(messagesToSend), // 请求体 (发送的消息)
			signal, // 用于中止请求的 AbortSignal
			openWhenHidden: true, // 保持连接即使页面不可见
			onmessage(event) {
				const { message } = JSON.parse(event.data);
				// 接收到消息时的回调
				// 检查是否是结束标记
				if (message === '[DONE]') {
					streamController.close(); // 关闭流
					return;
				}

				try {
					// 获取消息内容
					if (message) {
						streamController.enqueue({
							choices: [{ delta: { content: message } }], // 模拟 OpenAI 流格式
						});
					}
				} catch (error) {
					// 移除 console.error 以修复 linter 错误
					streamController.error(error); // 将错误推送到流中
				}
			},
			onclose() {
				// 连接关闭时的回调
				streamController.close(); // 关闭流
			},
			onerror(error) {
				// 发生错误时的回调
				streamController.error(error); // 将错误推送到流中
			},
		});

		// 返回创建的 ReadableStream
		return stream;
	} catch (error) {
		// 创建一个包含错误信息的流
		return new ReadableStream({
			start(controller) {
				controller.error(error);
			},
		});
	}
}
</script>
