<template>
  <div ref="editorWrapper" class="rich-edit-wrapper" :class="{ 'is-fullscreen': isFullscreen }">
    <!-- 独立的全屏按钮（浮在编辑器右上角） -->
    <div class="fullscreen-toggle-btn" @click="toggleFullscreen" :title="isFullscreen ? '退出全屏 (ESC)' : '全屏编辑'">
      <svg v-if="!isFullscreen" viewBox="0 0 1024 1024" width="18" height="18">
        <path d="M290 236.4l43.9-43.9c4.7-4.7 4.7-12.3 0-17L231.4 73c-4.7-4.7-12.3-4.7-17 0L71 216.4c-4.7 4.7-4.7 12.3 0 17l43.9 43.9c4.7 4.7 12.3 4.7 17 0l100.7-100.7 57.4 57.4c4.7 4.7 12.3 4.7 17 0zM642.1 845.5L734 753.6c4.7-4.7 4.7-12.3 0-17l-43.9-43.9c-4.7-4.7-12.3-4.7-17 0l-100.7 100.7-57.4-57.4c-4.7-4.7-12.3-4.7-17 0l-43.9 43.9c-4.7 4.7-4.7 12.3 0 17L597 939.8c4.7 4.7 12.3 4.7 17 0l43.9-43.9c4.7-4.7 4.7-12.3 0-17l-57.4-57.4 41.6-42zM845.5 381.9L753.6 290c-4.7-4.7-12.3-4.7-17 0l-43.9 43.9c-4.7 4.7-4.7 12.3 0 17l100.7 100.7-57.4 57.4c-4.7 4.7-4.7 12.3 0 17l43.9 43.9c4.7 4.7 12.3 4.7 17 0L939.8 427c4.7-4.7 4.7-12.3 0-17l-43.9-43.9c-4.7-4.7-12.3-4.7-17 0l-57.4 57.4-42-41.6zM381.9 178.5L290 270.4c-4.7 4.7-4.7 12.3 0 17l43.9 43.9c4.7 4.7 12.3 4.7 17 0l100.7-100.7 57.4 57.4c4.7 4.7 12.3 4.7 17 0l43.9-43.9c4.7-4.7 4.7-12.3 0-17L427 84.2c-4.7-4.7-12.3-4.7-17 0l-43.9 43.9c-4.7 4.7-4.7 12.3 0 17l57.4 57.4-41.6 42z" fill="currentColor"/>
      </svg>
      <svg v-else viewBox="0 0 1024 1024" width="18" height="18">
        <path d="M204.8 819.2h204.8v204.8h-204.8v-204.8zM614.4 0h204.8v204.8h-204.8v-204.8zM0 614.4h204.8v204.8h-204.8v-204.8zM819.2 0h204.8v204.8h-204.8v-204.8z" fill="currentColor"/>
      </svg>
    </div>

    <Toolbar
      :editor="editorRef"
      :default-config="toolbarConfig"
      mode="default"
    />
    <Editor
      v-model="valueHtml"
      class="editor-content"
      :style="editorStyle"
      :default-config="editorConfig"
      mode="default"
      @onCreated="handleCreated"
      @onChange="change"
    />
  </div>
</template>

<script setup>
import '@wangeditor/editor/dist/css/style.css'

const basePath = import.meta.env.VITE_BASE_API

import { onBeforeUnmount, ref, shallowRef, watch, computed, onMounted } from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'

import { ElMessage } from 'element-plus'
import { getUrl } from '@/utils/image'
import botLogo from '@/assets/bot_logo.png'
import { useUserStore } from '@/pinia/modules/user'

const emits = defineEmits(['change', 'update:modelValue'])

const change = (editor) => {
  emits('change', editor)
  emits('update:modelValue', valueHtml.value)
}

const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  useWatermark: {
    type: Boolean,
    default: false
  }
})

const editorRef = shallowRef()
const valueHtml = ref('')
const userStore = useUserStore()
const editorWrapper = ref(null)
const isFullscreen = ref(false)
const originalParent = ref(null)
const originalNextSibling = ref(null)

const editorStyle = computed(() => ({
  minHeight: '25rem',
  height: isFullscreen.value ? 'calc(100vh - 42px)' : '400px'
}))

const toolbarConfig = {}

// 创建自定义上传函数
const createCustomUpload = () => {
  return async (file, insertFn) => {
    const shouldUseWatermark = props.useWatermark

    // 未开启水印则直接上传原图
    if (!shouldUseWatermark) {
      const formData = new FormData()
      formData.append('file', file)
      const resp = await fetch(basePath + '/fileUploadAndDownload/upload?noSave=1', {
        method: 'POST',
        body: formData,
        headers: {
          'x-token': userStore.token,
          'x-user-id': userStore.userInfo.ID
        }
      })
      const res = await resp.json()
      if (res.code === 0) {
        const urlPath = getUrl(res.data.file.url)
        insertFn(urlPath, res.data.file.name)
      } else {
        ElMessage.error(res.msg || '上传失败')
      }
      return
    }

    try {
      const watermarkedBlob = await addBottomWatermark(file, {
        stripRatio: 0.18,
        background: 'rgba(255,255,255,0.96)',
        text: '好运助手',
        textColor: '#333',
        fontFamily: 'PingFang SC, Microsoft YaHei, Arial',
        logo: botLogo
      })

      const newFile = new File([watermarkedBlob], file.name, { type: watermarkedBlob.type || file.type })
      const formData = new FormData()
      formData.append('file', newFile)
      const resp = await fetch(basePath + '/fileUploadAndDownload/upload?noSave=1', {
        method: 'POST',
        body: formData,
        headers: {
          'x-token': userStore.token,
          'x-user-id': userStore.userInfo.ID
        }
      })
      const res = await resp.json()
      if (res.code === 0) {
        const urlPath = getUrl(res.data.file.url)
        insertFn(urlPath, res.data.file.name)
      } else {
        ElMessage.error(res.msg || '上传失败')
      }
    } catch {
      ElMessage.error('处理水印失败')
      // 降级：直接走原图上传
      const formData = new FormData()
      formData.append('file', file)
      const resp = await fetch(basePath + '/fileUploadAndDownload/upload?noSave=1', {
        method: 'POST',
        body: formData,
        headers: {
          'x-token': userStore.token,
          'x-user-id': userStore.userInfo.ID
        }
      })
      const res = await resp.json()
      if (res.code === 0) {
        const urlPath = getUrl(res.data.file.url)
        insertFn(urlPath, res.data.file.name)
      } else {
        ElMessage.error(res.msg || '上传失败')
      }
    }
  }
}

const editorConfig = computed(() => ({
  placeholder: '请输入内容...',
  MENU_CONF: {
    uploadImage: {
      server: basePath + '/fileUploadAndDownload/upload?noSave=1',
      fieldName: 'file',
      maxFileSize: 1024 * 1024 * 10,
      maxNumberOfFiles: 1,
      customUpload: createCustomUpload()
    },
    uploadVideo: {
      server: basePath + '/fileUploadAndDownload/upload?noSave=1',
      fieldName: 'file',
      maxFileSize: 1024 * 1024 * 100,
      maxNumberOfFiles: 1,
      customInsert(res, insertFn) {
        if (res.code === 0) {
          const urlPath = getUrl(res.data.file.url)
          insertFn(urlPath, res.data.file.name)
          return
        }
        ElMessage.error(res.msg)
      }
    }
  }
}))

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

  // 如果是全屏状态，先退出全屏
  if (isFullscreen.value) {
    exitFullscreen()
  }

  // 移除键盘监听
  document.removeEventListener('keydown', handleEscKey)

  editor.destroy()
})

const handleCreated = (editor) => {
  editorRef.value = editor
  valueHtml.value = props.modelValue

  // 动态更新上传配置
  if (editor && editor.getConfig) {
    const config = editor.getConfig()
    if (config.MENU_CONF && config.MENU_CONF.uploadImage) {
      config.MENU_CONF.uploadImage.customUpload = createCustomUpload()
    }
  }

  // 修复点击区域问题
  setTimeout(() => {
    const editorContainer = editor.getEditableContainer()
    if (editorContainer) {
      editorContainer.style.cursor = 'text'
      editorContainer.style.minHeight = '300px'

      editorContainer.addEventListener('click', (e) => {
        if (e.target === editorContainer) {
          editor.focus()
        }
      })
    }
  }, 100)
}

// 监听 ESC 键退出全屏
function handleEscKey(e) {
  if (e.key === 'Escape' && isFullscreen.value) {
    exitFullscreen()
  }
}

onMounted(() => {
  // 监听 ESC 键
  document.addEventListener('keydown', handleEscKey)
})

// 切换全屏
function toggleFullscreen() {
  if (isFullscreen.value) {
    exitFullscreen()
  } else {
    enterFullscreen()
  }
}

// 进入全屏
function enterFullscreen() {
  if (!editorWrapper.value) return

  // 保存原始位置
  originalParent.value = editorWrapper.value.parentElement
  originalNextSibling.value = editorWrapper.value.nextElementSibling

  isFullscreen.value = true

  // 添加全屏样式类
  document.body.classList.add('rich-editor-fullscreen')

  // 移动到 body 下（避免受父元素样式影响）
  document.body.appendChild(editorWrapper.value)
}

// 退出全屏
function exitFullscreen() {
  if (!editorWrapper.value || !originalParent.value) return

  isFullscreen.value = false

  // 移除全屏样式类
  document.body.classList.remove('rich-editor-fullscreen')

  // 恢复到原始位置
  if (originalNextSibling.value) {
    originalParent.value.insertBefore(editorWrapper.value, originalNextSibling.value)
  } else {
    originalParent.value.appendChild(editorWrapper.value)
  }

  // 清空保存的引用
  originalParent.value = null
  originalNextSibling.value = null
}

watch(
  () => props.modelValue,
  () => {
    valueHtml.value = props.modelValue
  }
)

// 监听 useWatermark 变化，动态更新编辑器配置
watch(
  () => props.useWatermark,
  () => {
    if (editorRef.value && editorRef.value.getConfig) {
      const config = editorRef.value.getConfig()
      if (config.MENU_CONF && config.MENU_CONF.uploadImage) {
        config.MENU_CONF.uploadImage.customUpload = createCustomUpload()
      }
    }
  }
)

// 水印相关函数
async function addBottomWatermark(file, options) {
  const { stripRatio = 0.18, background = 'rgba(255,255,255,0.96)', text = '', textColor = '#333', fontFamily = 'Arial', logo } = options || {}

  const img = await fileToImage(file)
  const width = img.naturalWidth || img.width
  const height = img.naturalHeight || img.height
  const stripHeight = Math.max(60, Math.floor(height * stripRatio))

  const canvas = document.createElement('canvas')
  canvas.width = width
  canvas.height = height + stripHeight
  const ctx = canvas.getContext('2d')

  // 原图
  ctx.drawImage(img, 0, 0, width, height)

  // 底部水印条背景
  ctx.fillStyle = background
  ctx.fillRect(0, height, width, stripHeight)

  // 左侧 Logo
  let logoSize = Math.floor(stripHeight * 0.6)
  let logoPadding = Math.floor(stripHeight * 0.2)
  if (logo) {
    try {
      const logoImg = await srcToImage(logo)
      const ratio = logoImg.width / logoImg.height
      const drawW = logoSize
      const drawH = Math.floor(drawW / ratio)
      const y = height + Math.floor((stripHeight - drawH) / 2)
      ctx.drawImage(logoImg, logoPadding, y, drawW, drawH)
    } catch { void 0 }
  }

  // 右侧文字
  ctx.fillStyle = textColor
  const fontSize = Math.floor(stripHeight * 0.38)
  ctx.font = `${fontSize}px ${fontFamily}`
  ctx.textBaseline = 'middle'
  ctx.textAlign = 'right'
  const textPadding = Math.floor(stripHeight * 0.25)
  ctx.fillText(text, width - textPadding, height + Math.floor(stripHeight / 2))

  const blob = await canvasToBlob(canvas, file.type || 'image/png')
  return blob
}

function fileToImage(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = () => {
      const img = new Image()
      img.onload = () => resolve(img)
      img.onerror = reject
      img.src = reader.result
    }
    reader.onerror = reject
    reader.readAsDataURL(file)
  })
}

function srcToImage(src) {
  return new Promise((resolve, reject) => {
    const img = new Image()
    img.crossOrigin = 'anonymous'
    img.onload = () => resolve(img)
    img.onerror = reject
    img.src = src
  })
}

function canvasToBlob(canvas, mime) {
  return new Promise((resolve) => {
    if (canvas.toBlob) {
      canvas.toBlob((blob) => resolve(blob), mime, 0.92)
    } else {
      const dataURL = canvas.toDataURL(mime)
      const arr = dataURL.split(',')
      const bstr = atob(arr[1])
      let n = bstr.length
      const u8arr = new Uint8Array(n)
      while (n--) u8arr[n] = bstr.charCodeAt(n)
      const blob = new Blob([u8arr], { type: mime })
      resolve(blob)
    }
  })
}
</script>

<style scoped lang="scss">
.rich-edit-wrapper {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
  background: #fff;
  position: relative;

  &.is-fullscreen {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    bottom: 0 !important;
    width: 100vw !important;
    height: 100vh !important;
    z-index: 99999 !important;
    margin: 0 !important;
    padding: 0 !important;
    border: none !important;
    border-radius: 0 !important;
    display: flex !important;
    flex-direction: column !important;

    .editor-content {
      flex: 1 !important;
      overflow-y: auto !important;
    }

    .fullscreen-toggle-btn {
      top: 10px;
      right: 20px;
      background: rgba(0, 0, 0, 0.7);
      color: white;

      &:hover {
        background: rgba(0, 0, 0, 0.85);
      }
    }
  }
}

.editor-content {
  overflow-y: auto;
  overflow-x: hidden;
}

.fullscreen-toggle-btn {
  position: absolute;
  top: 5px;
  right: 10px;
  z-index: 10;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f1f1f1;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
  color: #666;

  &:hover {
    background: #e0e0e0;
    color: #333;
  }

  svg {
    display: block;
  }
}

// 编辑器内容区域滚动条样式
:deep(.w-e-text-container) {
  min-height: 300px !important;
  cursor: text !important;
  overflow-y: auto !important;
  overflow-x: hidden !important;

  // 自定义滚动条样式
  &::-webkit-scrollbar {
    display: block !important;
    width: 8px;
    height: 8px;
  }

  &::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 4px;
  }

  &::-webkit-scrollbar-thumb {
    background: #c1c1c1;
    border-radius: 4px;
    transition: background 0.3s;

    &:hover {
      background: #a8a8a8;
    }
  }

  // Firefox 滚动条样式
  scrollbar-width: thin;
  scrollbar-color: #c1c1c1 #f1f1f1;
}

:deep(.w-e-scroll) {
  min-height: 300px !important;
  cursor: text !important;
  overflow-y: auto !important;
  overflow-x: hidden !important;

  // 自定义滚动条样式
  &::-webkit-scrollbar {
    display: block !important;
    width: 8px;
    height: 8px;
  }

  &::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 4px;
  }

  &::-webkit-scrollbar-thumb {
    background: #c1c1c1;
    border-radius: 4px;
    transition: background 0.3s;

    &:hover {
      background: #a8a8a8;
    }
  }

  // Firefox 滚动条样式
  scrollbar-width: thin;
  scrollbar-color: #c1c1c1 #f1f1f1;
}

:deep(.w-e-text-placeholder) {
  pointer-events: none;
}

:deep(.w-e-text-container .w-e-scroll) {
  cursor: text !important;
}

:deep(.w-e-text-container .w-e-scroll .w-e-text) {
  min-height: 300px !important;
  cursor: text !important;
}

// 编辑器外层容器滚动条样式
.editor-content {
  &::-webkit-scrollbar {
    display: block !important;
    width: 8px;
    height: 8px;
  }

  &::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 4px;
  }

  &::-webkit-scrollbar-thumb {
    background: #c1c1c1;
    border-radius: 4px;
    transition: background 0.3s;

    &:hover {
      background: #a8a8a8;
    }
  }

  // Firefox 滚动条样式
  scrollbar-width: thin;
  scrollbar-color: #c1c1c1 #f1f1f1;
}
</style>

<style lang="scss">
// 全局样式：全屏模式下隐藏其他元素
body.rich-editor-fullscreen {
  overflow: hidden !important;

  // 隐藏主要布局容器
  > #app {
    display: none !important;
  }

  // 显示全屏编辑器
  > .rich-edit-wrapper.is-fullscreen {
    display: flex !important;
  }
}
</style>
