<template>
  <div>
    <el-upload
      v-if="type === 'url'"
      :action="upload.url"
      :before-upload="handleBeforeUpload"
      :on-success="handleUploadSuccess"
      :on-error="handleUploadError"
      class="editor-img-uploader"
      name="file"
      :show-file-list="false"
      :headers="upload.headers"
    >
      <i ref="uploadRef"></i>
    </el-upload>
  </div>
  <div style="border: 1px solid #ccc">
    <Toolbar :editor="editorRef" :defaultConfig="toolbarConfig" style="border-bottom: 1px solid #ccc" />
    <WangEditor
      :defaultConfig="editorConfig"
      :modelValue="modelValue"
      :style="styles"
      @onChange="handleChange"
      @onCreated="handleCreated"
    />
  </div>
</template>

<script setup lang="ts">
import '@wangeditor/editor/dist/css/style.css';
import { Editor as WangEditor, Toolbar } from '@wangeditor/editor-for-vue';
import { IDomEditor, IEditorConfig, IToolbarConfig } from '@wangeditor/editor';
import { propTypes } from '@/utils/propTypes';
import { globalHeaders } from '@/utils/request';

const emit = defineEmits(['update:modelValue']);

const props = defineProps({
  /* 编辑器的内容 */
  modelValue: propTypes.string,
  /* 高度 */
  height: propTypes.number.def(400),
  /* 最小高度 */
  minHeight: propTypes.number.def(400),
  /* 只读 */
  readOnly: propTypes.bool.def(false),
  /* 上传文件大小限制(MB) */
  fileSize: propTypes.number.def(5),
  /* 类型（base64格式、url格式） */
  type: propTypes.string.def('url')
});

const { proxy } = getCurrentInstance() as ComponentInternalInstance;

const editorRef = shallowRef<IDomEditor>();
const uploadRef = ref<HTMLDivElement>();

const upload = reactive<UploadOption>({
  headers: globalHeaders(),
  url: import.meta.env.VITE_APP_BASE_API + '/resource/oss/upload'
});

const toolbarConfig: Partial<IToolbarConfig> = {};

const editorConfig: Partial<IEditorConfig> = {
  placeholder: '请输入内容...',
  readOnly: props.readOnly,
  MENU_CONF: {}
};

// 图片上传配置
editorConfig.MENU_CONF!['uploadImage'] = {
  server: import.meta.env.VITE_APP_BASE_API + '/resource/oss/upload',
  fieldName: 'file',
  headers: {
    Authorization: globalHeaders().Authorization,
    clientid: import.meta.env.VITE_APP_CLIENT_ID
  },
  customInsert(res: any, insertFn: Function) {
    if (res.code === 200) {
      insertFn(res.data.url, res.data.fileName, res.data.url);
    } else {
      proxy?.$modal.msgError('图片插入失败');
    }
  }
};

const styles = computed(() => {
  const style: any = {};
  if (props.minHeight) {
    style.minHeight = `${props.minHeight}px`;
  }
  if (props.height) {
    style.height = `${props.height}px`;
  }
  style.overflowY = 'hidden';
  return style;
});

const handleCreated = (editor: IDomEditor) => {
  editorRef.value = editor;
};

// 监听 modelValue 变化，手动更新编辑器内容
watch(
  () => props.modelValue,
  (val) => {
    if (!editorRef.value) return;
    // 避免重复设置相同内容导致光标重置
    if (editorRef.value.getHtml() !== val) {
      editorRef.value.setHtml(val || '');
    }
  }
);

const handleChange = (editor: IDomEditor) => {
  emit('update:modelValue', editor.getHtml());
};

// 组件销毁时，也及时销毁编辑器
onBeforeUnmount(() => {
  const editor = editorRef.value;
  if (editor == null) return;
  editor.destroy();
});

// 图片上传成功返回图片地址（备用：el-upload 方式）
const handleUploadSuccess = (res: any) => {
  if (res.code === 200) {
    const editor = editorRef.value;
    if (editor) {
      editor.insertNode({ type: 'image', src: res.data.url, children: [] });
    }
    proxy?.$modal.closeLoading();
  } else {
    proxy?.$modal.msgError('图片插入失败');
    proxy?.$modal.closeLoading();
  }
};

// 图片上传前拦截
const handleBeforeUpload = (file: any) => {
  const type = ['image/jpeg', 'image/jpg', 'image/png', 'image/svg'];
  const isJPG = type.includes(file.type);
  if (!isJPG) {
    proxy?.$modal.msgError(`图片格式错误!`);
    return false;
  }
  if (props.fileSize) {
    const isLt = file.size / 1024 / 1024 < props.fileSize;
    if (!isLt) {
      proxy?.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
      return false;
    }
  }
  proxy?.$modal.loading('正在上传文件，请稍候...');
  return true;
};

// 图片失败拦截
const handleUploadError = (err: any) => {
  proxy?.$modal.msgError('上传文件失败');
};
</script>

<style>
.editor-img-uploader {
  display: none;
}
</style>
