<script setup lang="ts">
import { ref } from 'vue';

import { QuillEditor } from '@vueup/vue-quill';
// eslint-disable-next-line n/no-extraneous-import
import '@vueup/vue-quill/dist/vue-quill.snow.css';
import { useVModel } from '@vueuse/core';
import { message } from 'ant-design-vue';

// 导入上传相关API和工具函数
import { uploadFile } from '#/api/core/upload';
import { uploadToOss } from '#/utils/oss-upload';
import { prepareImageForUpload } from '#/utils/prepare-image-upload';
import { preferences } from '@vben/preferences';

const props = defineProps({
  value: {
    type: String,
    default: '',
  },
});
const emits = defineEmits(['update:value']);
// 创建对QuillEditor的引用，用于后续获取Quill实例
const quillEditorRef = ref(null);
const isUpload = ref(false);
const mValue = useVModel(props, 'value', emits, {
  defaultValue: props.value,
  passive: true,
});
// 富文本编辑器配置选项
const editorOptions = {
  theme: 'snow',
  modules: {
    toolbar: [
      ['bold', 'italic', 'underline', 'strike'],
      ['blockquote', 'code-block'],
      [{ header: 1 }, { header: 2 }],
      [{ list: 'ordered' }, { list: 'bullet' }],
      [{ script: 'sub' }, { script: 'super' }],
      [{ indent: '-1' }, { indent: '+1' }],
      [{ direction: 'rtl' }],
      [{ size: ['small', false, 'large', 'huge'] }],
      [{ header: [1, 2, 3, 4, 5, 6, false] }],
      [{ color: [] }, { background: [] }],
      [{ font: [] }],
      [{ align: [] }],
      ['clean'],
      ['link', 'image', 'video'],
    ],
  },
  placeholder: '请输入消息内容',
};

/**
 * 直接处理编辑器的粘贴事件
 * 这是一个备用方法，通过Quill的clipboard模块直接处理粘贴事件
 */
const setupQuillPasteHandler = () => {
  // 确保编辑器已经挂载
  if (!quillEditorRef.value) return;

  const quill = quillEditorRef.value.getQuill();
  if (!quill) return;

  // 获取Quill的clipboard模块
  const clipboard = quill.getModule('clipboard');

  // 保存原始的粘贴处理函数
  const originalMatchers = clipboard.matchers;

  // 重写粘贴处理函数
  clipboard.addMatcher('img', (node: any, delta: any) => {
    // 这里可以处理HTML中的img标签
    // 但对于直接粘贴的图片文件，这个方法不会被触发
    return delta;
  });

  // 监听编辑器的paste事件
  quill.root.addEventListener('paste', async (e: ClipboardEvent) => {
    const imageFile = getImageFromClipboard(e);

    if (imageFile) {
      e.preventDefault();

      if (isUpload.value === true) {
        return;
      }
      isUpload.value = true;
      const imageUrl = await uploadImage(imageFile);

      if (imageUrl) {
        insertImageToEditor(quill, imageUrl);
      }
    }
  });
};
/**
 * 从剪贴板数据中提取图片文件
 * @param {ClipboardEvent} event - 剪贴板事件
 * @returns {File|null} - 返回图片文件或null
 */
const getImageFromClipboard = (event: ClipboardEvent): File | null => {
  const clipboardData = event.clipboardData;
  if (!clipboardData) return null;

  // 遍历剪贴板中的所有项目
  const items = clipboardData.items;
  for (const item of items) {
    // 检查是否是图片类型
    if (item.type.includes('image')) {
      return item.getAsFile();
    }
  }

  return null;
};

/**
 * 在编辑器中插入图片
 * @param {any} quill - Quill编辑器实例
 * @param {string} imageUrl - 图片URL
 */
const insertImageToEditor = (quill: any, imageUrl: string): void => {
  if (!quill) return;

  // 获取当前光标位置
  const range = quill.getSelection();

  if (range) {
    // 在光标位置插入图片
    quill.insertEmbed(range.index, 'image', imageUrl);
    // 将光标移动到图片后面
    quill.setSelection(range.index + 1);
  } else {
    // 如果没有选择范围，则在文档末尾插入
    const length = quill.getLength();
    quill.insertEmbed(length - 1, 'image', imageUrl);
    quill.setSelection(length);
  }
};
/**
 * 图片上传函数
 * 
 * 该函数根据preferences配置的上传方式，选择使用OSS直传或后端上传：
 * - 'direct': OSS直传模式，文件直接从浏览器上传到阿里云OSS
 * - 'backend': 后端上传模式，文件先上传到后端服务器，再由后端上传到OSS
 * 
 * 上传方式说明：
 * 1. OSS直传（direct）：
 *    - 调用uploadToOss函数，直接上传到OSS
 *    - 减少服务器负载，上传速度更快
 *    - 支持上传进度回调（如果需要可以添加）
 * 
 * 2. 后端上传（backend）：
 *    - 调用uploadFile API，通过后端服务器上传
 *    - 兼容现有功能，所有上传逻辑由后端统一处理
 * 
 * 兼容性处理：
 * - 两种上传方式返回的数据结构保持一致：{ url: string }
 * - 上传成功或失败都会显示相应的提示信息
 * - 上传完成后，将isUpload标记设置为false，允许下次上传
 * 
 * @param {File} file - 要上传的图片文件
 * @returns {Promise<string>} - 返回上传后的图片URL，如果上传失败返回空字符串
 */
const uploadImage = async (file: File): Promise<string> => {
  try {
    const { file: preparedFile } = await prepareImageForUpload(file);
    if (!preparedFile) {
      isUpload.value = false;
      return '';
    }

    // 显示上传中的提示
    message.loading({ content: '图片上传中...', key: 'imageUpload' });

    // 从preferences中读取上传方式配置
    // uploadMethod可能的值：'direct'（OSS直传）或 'backend'（后端上传）
    const uploadMethod = preferences.app.uploadMethod || 'direct';

    let data: { url: string };

    // 根据配置选择上传方式
    if (uploadMethod === 'direct') {
      // OSS直传模式：文件直接从浏览器上传到OSS
      // uploadToOss函数会处理签名获取、文件上传等所有逻辑
      data = await uploadToOss({
        file: preparedFile,
        // 如果需要显示上传进度，可以添加onProgress回调
        // onProgress: (percent) => {
        //   message.loading({ content: `图片上传中... ${percent}%`, key: 'imageUpload' });
        // },
      });
    } else {
      // 后端上传模式：文件先上传到后端服务器，再由后端上传到OSS
      // uploadFile函数会将文件发送到后端API（/upload/image）
      data = await uploadFile({
        file: preparedFile,
      });
    }

    // 上传成功，显示成功提示
    message.success({
      content: '图片上传成功',
      key: 'imageUpload',
      duration: 2,
    });
    
    // 重置上传标记，允许下次上传
    isUpload.value = false;
    
    // 返回上传后的图片URL
    return data.url;
  } catch (error) {
    // 处理上传错误
    console.error('图片上传错误:', error);
    
    // 显示错误提示
    message.error({ content: '图片上传失败', key: 'imageUpload', duration: 2 });
    
    // 重置上传标记，允许重试
    isUpload.value = false;
    
    // 返回空字符串，表示上传失败
    return '';
  }
};
</script>
<template>
  <div class="editor-container-box">
    <QuillEditor
      ref="quillEditorRef"
      v-model:content="mValue"
      :options="editorOptions"
      class="editor-container"
      content-type="html"
      theme="snow"
      @ready="setupQuillPasteHandler"
    />
  </div>
</template>

<style scoped>
.editor-container-box {
  width: 100%;
  height: 100%;
}
/* 编辑器容器样式 */
.editor-container {
  height: 250px;
  margin-bottom: 40px;
  /* 确保编辑器有足够的空间显示工具栏和内容区域 */
}

/* Markdown编辑器样式 */
.md-editor-container {
  min-height: 400px;
  margin-bottom: 40px;
}

/* 可以添加额外的样式来自定义编辑器外观 */
:deep(.ql-editor) {
  min-height: 200px;
  font-size: 14px;
  line-height: 1.6;
}

/* 确保图片在编辑器中显示正常 */
:deep(.ql-editor img) {
  max-width: 100%;
  height: auto;
}

/* 自定义 Markdown 编辑器样式 */
:deep(.md-editor) {
  border-radius: 4px;
}

:deep(.md-editor-dark) {
  --md-bk-color: #1e1e1e;
  --md-border-color: #333;
}
</style>
