<script setup lang="ts">
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { onBeforeUnmount, shallowRef } from 'vue'
import { getAliOssTokenAxios } from '@/service/api/upload'
import { browserPathJoin } from '@/utils/date'
import { initOSSClient, uploadFileToOSS } from '@/utils/oss'
import '@wangeditor/editor/dist/css/style.css'

interface Props {
  modelValue: string
  placeholder?: string
  mode?: 'default' | 'simple'
  height?: string
  path?: string
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: '',
  placeholder: '请输入内容...',
  mode: 'default',
  height: '300px',
  path: 'temp',
})

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

// Editor Logic
const editorRef = shallowRef()
const toolbarConfig = {
  excludeKeys: [],
}

type InsertFnType = (url: string, alt: string, href: string) => void

async function customUpload(file: File, insertFn: InsertFnType) {
  try {
    const { data: tokenData, error: tokenError } = await getAliOssTokenAxios()
    if (tokenError || !tokenData) {
      window.$message?.error('获取上传凭证失败')
      return
    }
    const client = initOSSClient(tokenData?.data || {})
    const path = `${props.path}/${Date.now()}/${file.name}`

    await uploadFileToOSS(client, file, path)

    const url = browserPathJoin(import.meta.env.VITE_BASE_OSS_URL, path)
    insertFn(url, file.name, url)
  }
  catch (error) {
    console.error('上传失败', error)
    window.$message?.error('上传失败')
  }
}

const editorConfig = {
  placeholder: props.placeholder,
  MENU_CONF: {
    uploadImage: {
      customUpload,
    },
    uploadVideo: {
      customUpload,
    },
  },
}

// 监听 placeholder 变化
// watch(() => props.placeholder, (_newVal) => {
//   if (editorRef.value) {
//     // 似乎 wangeditor 不支持动态修改 placeholder，这里作为占位
//   }
// })

function handleCreated(editor: any) {
  editorRef.value = editor
}

function handleChange(editor: any) {
  emit('update:modelValue', editor.getHtml())
}

onBeforeUnmount(() => {
  const editor = editorRef.value
  if (editor == null)
    return
  editor.destroy()
})
</script>

<template>
  <div class="overflow-hidden border border-gray-200 rounded-lg bg-white">
    <Toolbar
      style="border-bottom: 1px solid #eee"
      :editor="editorRef"
      :default-config="toolbarConfig"
      :mode="mode"
    />
    <div :style="{ height: props.height }">
      <Editor
        :model-value="modelValue"
        :style="{ height: '100%', overflowY: 'hidden' }"
        :default-config="editorConfig"
        :mode="mode"
        @on-created="handleCreated"
        @on-change="handleChange"
      />
    </div>
  </div>
</template>

<style scoped>
:deep(.w-e-text-container) {
  background-color: transparent;
}
</style>
