<template>
  <div class="rich-text-editor">
    <!-- 工具栏 -->
    <div v-if="showToolbar" class="editor-toolbar">
      <div class="toolbar-group">
        <!-- 文本格式 -->
        <el-button-group size="small">
          <el-button @click="execCommand('bold')" :class="{ active: isActive('bold') }">
            <el-icon><Bold /></el-icon>
          </el-button>
          <el-button @click="execCommand('italic')" :class="{ active: isActive('italic') }">
            <el-icon><Italic /></el-icon>
          </el-button>
          <el-button @click="execCommand('underline')" :class="{ active: isActive('underline') }">
            <el-icon><Underline /></el-icon>
          </el-button>
          <el-button @click="execCommand('strikeThrough')" :class="{ active: isActive('strikeThrough') }">
            <el-icon><Strikethrough /></el-icon>
          </el-button>
        </el-button-group>
        
        <!-- 对齐方式 -->
        <el-button-group size="small">
          <el-button @click="execCommand('justifyLeft')" :class="{ active: isActive('justifyLeft') }">
            <el-icon><AlignLeft /></el-icon>
          </el-button>
          <el-button @click="execCommand('justifyCenter')" :class="{ active: isActive('justifyCenter') }">
            <el-icon><AlignCenter /></el-icon>
          </el-button>
          <el-button @click="execCommand('justifyRight')" :class="{ active: isActive('justifyRight') }">
            <el-icon><AlignRight /></el-icon>
          </el-button>
        </el-button-group>
        
        <!-- 列表 -->
        <el-button-group size="small">
          <el-button @click="execCommand('insertUnorderedList')" :class="{ active: isActive('insertUnorderedList') }">
            <el-icon><List /></el-icon>
          </el-button>
          <el-button @click="execCommand('insertOrderedList')" :class="{ active: isActive('insertOrderedList') }">
            <el-icon><Numbered /></el-icon>
          </el-button>
        </el-button-group>
        
        <!-- 其他功能 -->
        <el-button-group size="small">
          <el-button @click="insertLink">
            <el-icon><Link /></el-icon>
          </el-button>
          <el-button @click="insertImage">
            <el-icon><Picture /></el-icon>
          </el-button>
          <el-button @click="insertTable">
            <el-icon><Grid /></el-icon>
          </el-button>
        </el-button-group>
        
        <!-- 颜色 -->
        <div class="color-picker">
          <el-color-picker
            v-model="textColor"
            size="small"
            @change="changeTextColor"
          />
        </div>
        
        <!-- 清除格式 -->
        <el-button size="small" @click="clearFormat">
          <el-icon><Delete /></el-icon>
        </el-button>
      </div>
    </div>
    
    <!-- 编辑器内容区 -->
    <div
      ref="editorRef"
      class="editor-content"
      :style="{ height: height }"
      contenteditable
      @input="handleInput"
      @paste="handlePaste"
      @keydown="handleKeydown"
      @focus="handleFocus"
      @blur="handleBlur"
      v-html="content"
    />
    
    <!-- 字数统计 -->
    <div v-if="showWordCount" class="editor-footer">
      <span class="word-count">{{ wordCount }} 字</span>
      <span v-if="maxLength" class="word-limit">/ {{ maxLength }}</span>
    </div>
    
    <!-- 插入链接对话框 -->
    <el-dialog
      v-model="linkDialogVisible"
      title="插入链接"
      width="400px"
    >
      <el-form :model="linkForm" label-width="80px">
        <el-form-item label="链接文本">
          <el-input v-model="linkForm.text" placeholder="请输入链接文本" />
        </el-form-item>
        <el-form-item label="链接地址">
          <el-input v-model="linkForm.url" placeholder="请输入链接地址" />
        </el-form-item>
      </el-form>
      
      <template #footer>
        <el-button @click="linkDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmInsertLink">确定</el-button>
      </template>
    </el-dialog>
    
    <!-- 插入图片对话框 -->
    <el-dialog
      v-model="imageDialogVisible"
      title="插入图片"
      width="500px"
    >
      <el-tabs v-model="imageTabActive">
        <el-tab-pane label="上传图片" name="upload">
          <ImageUpload
            :limit="1"
            :multiple="false"
            @success="handleImageUpload"
          />
        </el-tab-pane>
        
        <el-tab-pane label="网络图片" name="url">
          <el-form :model="imageForm" label-width="80px">
            <el-form-item label="图片地址">
              <el-input v-model="imageForm.url" placeholder="请输入图片地址" />
            </el-form-item>
            <el-form-item label="替代文本">
              <el-input v-model="imageForm.alt" placeholder="请输入替代文本" />
            </el-form-item>
          </el-form>
          
          <div class="dialog-footer">
            <el-button @click="imageDialogVisible = false">取消</el-button>
            <el-button type="primary" @click="confirmInsertImage">确定</el-button>
          </div>
        </el-tab-pane>
      </el-tabs>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import {
  Bold,
  Italic,
  Underline,
  Strikethrough,
  AlignLeft,
  AlignCenter,
  AlignRight,
  List,
  Link,
  Picture,
  Grid,
  Delete
} from '@element-plus/icons-vue'
import ImageUpload from '@/components/upload/ImageUpload.vue'

interface Props {
  modelValue?: string
  placeholder?: string
  height?: string
  maxLength?: number
  showToolbar?: boolean
  showWordCount?: boolean
  disabled?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: '',
  placeholder: '请输入内容...',
  height: '300px',
  maxLength: 0,
  showToolbar: true,
  showWordCount: true,
  disabled: false
})

interface Emits {
  (e: 'update:modelValue', value: string): void
  (e: 'change', value: string): void
  (e: 'focus', event: FocusEvent): void
  (e: 'blur', event: FocusEvent): void
}

const emit = defineEmits<Emits>()

// 响应式数据
const editorRef = ref<HTMLElement>()
const content = ref(props.modelValue)
const textColor = ref('#000000')
const linkDialogVisible = ref(false)
const imageDialogVisible = ref(false)
const imageTabActive = ref('upload')
const focused = ref(false)

// 表单数据
const linkForm = ref({
  text: '',
  url: ''
})

const imageForm = ref({
  url: '',
  alt: ''
})

// 计算属性
const wordCount = computed(() => {
  const text = editorRef.value?.innerText || ''
  return text.length
})

// 方法
const handleInput = () => {
  if (!editorRef.value) return
  
  const html = editorRef.value.innerHTML
  content.value = html
  
  // 检查字数限制
  if (props.maxLength && wordCount.value > props.maxLength) {
    ElMessage.warning(`内容不能超过 ${props.maxLength} 字`)
    return
  }
  
  emit('update:modelValue', html)
  emit('change', html)
}

const handlePaste = (event: ClipboardEvent) => {
  event.preventDefault()
  
  const clipboardData = event.clipboardData
  if (!clipboardData) return
  
  // 获取纯文本内容
  const text = clipboardData.getData('text/plain')
  
  // 插入文本
  execCommand('insertText', text)
}

const handleKeydown = (event: KeyboardEvent) => {
  // Ctrl+B 加粗
  if (event.ctrlKey && event.key === 'b') {
    event.preventDefault()
    execCommand('bold')
  }
  
  // Ctrl+I 斜体
  if (event.ctrlKey && event.key === 'i') {
    event.preventDefault()
    execCommand('italic')
  }
  
  // Ctrl+U 下划线
  if (event.ctrlKey && event.key === 'u') {
    event.preventDefault()
    execCommand('underline')
  }
}

const handleFocus = (event: FocusEvent) => {
  focused.value = true
  emit('focus', event)
}

const handleBlur = (event: FocusEvent) => {
  focused.value = false
  emit('blur', event)
}

const execCommand = (command: string, value?: string) => {
  document.execCommand(command, false, value)
  editorRef.value?.focus()
  handleInput()
}

const isActive = (command: string): boolean => {
  return document.queryCommandState(command)
}

const changeTextColor = (color: string) => {
  execCommand('foreColor', color)
}

const insertLink = () => {
  const selection = window.getSelection()
  if (selection && selection.toString()) {
    linkForm.value.text = selection.toString()
  }
  linkDialogVisible.value = true
}

const confirmInsertLink = () => {
  if (!linkForm.value.url) {
    ElMessage.warning('请输入链接地址')
    return
  }
  
  const linkHtml = `<a href="${linkForm.value.url}" target="_blank">${linkForm.value.text || linkForm.value.url}</a>`
  execCommand('insertHTML', linkHtml)
  
  linkDialogVisible.value = false
  linkForm.value = { text: '', url: '' }
}

const insertImage = () => {
  imageDialogVisible.value = true
}

const handleImageUpload = (response: any) => {
  const imageHtml = `<img src="${response.url}" alt="上传图片" style="max-width: 100%; height: auto;" />`
  execCommand('insertHTML', imageHtml)
  imageDialogVisible.value = false
}

const confirmInsertImage = () => {
  if (!imageForm.value.url) {
    ElMessage.warning('请输入图片地址')
    return
  }
  
  const imageHtml = `<img src="${imageForm.value.url}" alt="${imageForm.value.alt}" style="max-width: 100%; height: auto;" />`
  execCommand('insertHTML', imageHtml)
  
  imageDialogVisible.value = false
  imageForm.value = { url: '', alt: '' }
}

const insertTable = () => {
  const tableHtml = `
    <table border="1" style="border-collapse: collapse; width: 100%;">
      <tr>
        <td style="padding: 8px;">单元格1</td>
        <td style="padding: 8px;">单元格2</td>
      </tr>
      <tr>
        <td style="padding: 8px;">单元格3</td>
        <td style="padding: 8px;">单元格4</td>
      </tr>
    </table>
  `
  execCommand('insertHTML', tableHtml)
}

const clearFormat = () => {
  execCommand('removeFormat')
}

const focus = () => {
  editorRef.value?.focus()
}

const blur = () => {
  editorRef.value?.blur()
}

const getContent = () => {
  return content.value
}

const setContent = (html: string) => {
  content.value = html
  if (editorRef.value) {
    editorRef.value.innerHTML = html
  }
}

// 监听外部值变化
watch(() => props.modelValue, (newValue) => {
  if (newValue !== content.value) {
    content.value = newValue
    nextTick(() => {
      if (editorRef.value) {
        editorRef.value.innerHTML = newValue
      }
    })
  }
})

// 生命周期
onMounted(() => {
  if (editorRef.value && props.modelValue) {
    editorRef.value.innerHTML = props.modelValue
  }
})

// 暴露方法
defineExpose({
  focus,
  blur,
  getContent,
  setContent,
  execCommand
})
</script>

<style scoped>
.rich-text-editor {
  @apply border border-gray-300 rounded-lg overflow-hidden;
}

.editor-toolbar {
  @apply bg-gray-50 border-b border-gray-300 p-2;
}

.toolbar-group {
  @apply flex items-center space-x-2 flex-wrap;
}

.color-picker {
  @apply flex items-center;
}

.editor-content {
  @apply p-4 outline-none overflow-y-auto;
  min-height: 200px;
}

.editor-content:empty:before {
  content: attr(placeholder);
  @apply text-gray-400;
}

.editor-footer {
  @apply bg-gray-50 border-t border-gray-300 px-4 py-2 text-right text-sm text-gray-500;
}

.word-count {
  @apply mr-1;
}

.word-limit {
  @apply text-gray-400;
}

.dialog-footer {
  @apply flex justify-end space-x-2 mt-4;
}

:deep(.el-button.active) {
  @apply bg-blue-500 text-white;
}

:deep(.editor-content img) {
  @apply max-w-full h-auto;
}

:deep(.editor-content table) {
  @apply border-collapse w-full;
}

:deep(.editor-content table td) {
  @apply border border-gray-300 p-2;
}

:deep(.editor-content a) {
  @apply text-blue-500 underline;
}
</style>
