<template>
  <div class="rich-text-component">
    <div class="rich-text-editor" :class="{ 'is-disabled': disabled, 'is-error': error }">
      <!-- 工具栏 -->
      <div ref="toolbarRef" class="editor-toolbar">
        <!-- 字体样式 -->
        <span class="ql-formats">
          <select class="ql-header" title="标题">
            <option value="1">标题1</option>
            <option value="2">标题2</option>
            <option value="3">标题3</option>
            <option value="">正文</option>
          </select>
          
          <!-- 字体大小 -->
          <select class="ql-size" title="字体大小">
            <option value="small">小</option>
            <option selected>正常</option>
            <option value="large">大</option>
            <option value="huge">特大</option>
          </select>
        </span>
        
        <!-- 加粗、斜体、下划线 -->
        <span class="ql-formats">
          <button type="button" class="ql-bold" title="加粗"></button>
          <button type="button" class="ql-italic" title="斜体"></button>
          <button type="button" class="ql-underline" title="下划线"></button>
          <button type="button" class="ql-strike" title="删除线"></button>
          <button type="button" class="ql-code" title="行内代码"></button>
        </span>
        
        <!-- 文字颜色和背景色 -->
        <span class="ql-formats">
          <select class="ql-color" title="文字颜色"></select>
          <select class="ql-background" title="背景颜色"></select>
        </span>
        
        <!-- 列表 -->
        <span class="ql-formats">
          <button type="button" class="ql-list" value="ordered" title="有序列表"></button>
          <button type="button" class="ql-list" value="bullet" title="无序列表"></button>
        </span>
        
        <!-- 对齐方式 -->
        <span class="ql-formats">
          <select class="ql-align" title="对齐方式">
            <option selected></option>
            <option value="center">居中</option>
            <option value="right">右对齐</option>
            <option value="justify">两端对齐</option>
          </select>
        </span>
        
        <!-- 链接、图片、视频 -->
        <span class="ql-formats">
          <button type="button" class="ql-link" title="插入链接"></button>
          <button type="button" class="ql-image" title="插入图片"></button>
          <button type="button" class="ql-video" title="插入视频"></button>
        </span>
        
        <!-- 代码块、引用 -->
        <span class="ql-formats">
          <button type="button" class="ql-code-block" title="代码块"></button>
          <button type="button" class="ql-blockquote" title="引用"></button>
        </span>
        
        <!-- 清除格式 -->
        <span class="ql-formats">
          <button type="button" class="ql-clean" title="清除格式"></button>
        </span>
      </div>
      
      <!-- 编辑器内容区域 -->
      <div 
        ref="editorRef" 
        class="editor-content"
        :style="{ height: height }"
      ></div>
    </div>
    
    <!-- 字符统计 -->
    <div v-if="showWordCount" class="word-count">
      字数：{{ wordCount }} / {{ maxLength || '无限制' }}
    </div>
    
    <!-- 错误提示 -->
    <div v-if="error" class="error-message">
      {{ errorMessage }}
    </div>

    <!-- 文件上传对话框 -->
    <FileUpload
      v-model="uploadDialogVisible"
      :title="uploadType === 'image' ? '上传图片' : '上传视频'"
      :accept="uploadType === 'image' ? 'image/*' : 'video/*'"
      :module="uploadModule"
      :max-size="uploadType === 'image' ? 5 : 100"
      @success="handleUploadSuccess"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch, computed } from 'vue';
import Quill from 'quill';
import { FileUpload } from '@/components/file';
import type { SysFile } from '@/types';
import { FILE_DOWNLOAD_URL } from '@/config';
import { registerImageResize } from '@/utils/quill-resize';
// Quill 样式已在 main.ts 中全局引入

interface Props {
  modelValue?: string;
  placeholder?: string;
  height?: string;
  disabled?: boolean;
  readOnly?: boolean;
  maxLength?: number;
  showWordCount?: boolean;
  error?: boolean;
  errorMessage?: string;
  uploadModule?: string; // 上传文件的模块名
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: '',
  placeholder: '请输入内容...',
  height: '300px',
  disabled: false,
  readOnly: false,
  maxLength: 0,
  showWordCount: false,
  error: false,
  errorMessage: '',
  uploadModule: 'article'
});

const emit = defineEmits<{
  'update:modelValue': [value: string];
  'change': [value: string];
  'blur': [];
  'focus': [];
}>();

const toolbarRef = ref<HTMLElement>();
const editorRef = ref<HTMLElement>();
let quillInstance: Quill | null = null;

// 文件上传相关
const uploadDialogVisible = ref(false);
const uploadType = ref<'image' | 'video'>('image');
const uploadModule = computed(() => props.uploadModule);
let currentUploadRange: any = null; // 保存当前光标位置

// 字符统计
const wordCount = computed(() => {
  if (!quillInstance) return 0;
  return quillInstance.getText().trim().length;
});

onMounted(() => {
  initQuill();
});

onBeforeUnmount(() => {
  if (quillInstance) {
    quillInstance = null;
  }
});

// 监听外部值变化
watch(() => props.modelValue, (newValue) => {
  if (quillInstance && newValue !== quillInstance.root.innerHTML) {
    quillInstance.root.innerHTML = newValue;
  }
});

// 监听禁用状态
watch(() => props.disabled, (newValue) => {
  if (quillInstance) {
    quillInstance.enable(!newValue);
  }
});

// 监听只读状态
watch(() => props.readOnly, (newValue) => {
  if (quillInstance) {
    quillInstance.enable(!newValue);
  }
});

function initQuill() {
  if (!editorRef.value || !toolbarRef.value) return;
  
  // 自定义视频 Blot（支持本地视频文件）
  const BlockEmbed: any = Quill.import('blots/block/embed');
  
  class VideoBlot extends BlockEmbed {
    static blotName = 'customVideo';
    static tagName = 'video';
    
    static create(value: string) {
      const node = super.create() as HTMLVideoElement;
      node.setAttribute('src', value);
      node.setAttribute('controls', 'true');
      node.setAttribute('class', 'custom-video');
      node.setAttribute('data-custom-video', 'true');
      // 视频默认居中显示
      node.setAttribute('style', 'max-width: 100%; display: block; margin: 0 auto;');
      return node;
    }
    
    static value(node: HTMLVideoElement) {
      return node.getAttribute('src');
    }
  }
  
  // 自定义图片 Blot（与文字同行显示）
  const InlineEmbed: any = Quill.import('blots/embed');
  
  class CustomImageBlot extends InlineEmbed {
    static blotName = 'customImage';
    static tagName = 'img';
    
    static create(value: string) {
      const node = super.create() as HTMLImageElement;
      node.setAttribute('src', value);
      node.setAttribute('class', 'custom-image');
      node.setAttribute('data-custom-image', 'true');
      // 图片与文字同行显示
      node.setAttribute('style', 'max-width: 100%; display: inline-block; vertical-align: bottom;');
      return node;
    }
    
    static value(node: HTMLImageElement) {
      return node.getAttribute('src');
    }
  }

  Quill.register(VideoBlot);
  Quill.register(CustomImageBlot);
  
  // 注册图片/视频拉伸模块
  registerImageResize();
  
  // 配置选项
  const options = {
    theme: 'snow',
    modules: {
      toolbar: {
        // 1. 指定工具栏 DOM 容器
        container: toolbarRef.value,
        // 2. 自定义处理器
        handlers: {
          // 自定义图片上传处理器
          image: function() {
            handleImageUpload();
          },
          // 自定义视频上传处理器
          video: function() {
            handleVideoUpload();
          },
          // 清除格式处理器
          clean: function() {
            if (quillInstance) {
              const range = quillInstance.getSelection();
              if (range) {
                quillInstance.removeFormat(range.index, range.length);
              } else {
                quillInstance.removeFormat(0, quillInstance.getLength());
              }
            }
          }
        }
      },
      clipboard: {
        matchVisual: false
      },
      // 启用图片/视频缩放模块
      imageResize: {
        onResizeEnd: () => {
          // 强制触发内容更新
          if (quillInstance) {
            const html = quillInstance.root.innerHTML;
            emit('update:modelValue', html);
            emit('change', html);
          }
        }
      }
    },
    placeholder: props.placeholder,
    readOnly: props.readOnly || props.disabled
  };
  
  // 创建编辑器实例
  quillInstance = new Quill(editorRef.value, options);
  
  // 设置初始内容
  if (props.modelValue) {
    quillInstance.root.innerHTML = props.modelValue;
  }
  
  // 监听内容变化
  quillInstance.on('text-change', () => {
    if (!quillInstance) return;
    
    const html = quillInstance.root.innerHTML;
    const text = quillInstance.getText().trim();
    
    // 检查字数限制
    if (props.maxLength && text.length > props.maxLength) {
      quillInstance.deleteText(props.maxLength, text.length);
      return;
    }
    
    emit('update:modelValue', html);
    emit('change', html);
  });
  
  // 监听图片/视频尺寸变化
  quillInstance.root.addEventListener('input', () => {
    if (!quillInstance) return;
    
    const html = quillInstance.root.innerHTML;
    emit('update:modelValue', html);
    emit('change', html);
  });
  
  // 监听焦点事件
  quillInstance.on('selection-change', (range: any) => {
    if (range) {
      emit('focus');
    } else {
      emit('blur');
    }
  });
}

// 获取纯文本内容
function getText(): string {
  return quillInstance?.getText() || '';
}

// 获取HTML内容
function getHTML(): string {
  return quillInstance?.root.innerHTML || '';
}

// 清空内容
function clear(): void {
  quillInstance?.setText('');
}

// 设置内容
function setContent(content: string): void {
  if (quillInstance) {
    quillInstance.root.innerHTML = content;
  }
}

// 聚焦
function focus(): void {
  quillInstance?.focus();
}

// 失焦
function blur(): void {
  quillInstance?.blur();
}

// 处理图片上传
function handleImageUpload() {
  if (!quillInstance) return;
  
  // 保存当前光标位置
  currentUploadRange = quillInstance.getSelection();
  
  // 设置上传类型并打开上传对话框
  uploadType.value = 'image';
  uploadDialogVisible.value = true;
}

// 处理视频上传
function handleVideoUpload() {
  if (!quillInstance) return;
  
  // 保存当前光标位置
  currentUploadRange = quillInstance.getSelection();
  
  // 设置上传类型并打开上传对话框
  uploadType.value = 'video';
  uploadDialogVisible.value = true;
}

// 处理上传成功
function handleUploadSuccess(files: SysFile[]) {
  if (!quillInstance || !files || files.length === 0) return;
  
  files.forEach(file => {
    // 拼接下载URL
    const downloadUrl = FILE_DOWNLOAD_URL + file.fileID;
    
    // 获取插入位置（使用保存的光标位置，如果没有则使用当前光标）
    const range = currentUploadRange || quillInstance!.getSelection() || { index: quillInstance!.getLength() };
    
    // 根据类型插入内容
    if (uploadType.value === 'image') {
      // 插入自定义图片（与文字同行显示）
      quillInstance!.insertEmbed(range.index, 'customImage', downloadUrl);
      // 移动光标到图片后面
      quillInstance!.setSelection(range.index + 1);
    } else if (uploadType.value === 'video') {
      // 插入自定义视频（单行居中显示）
      quillInstance!.insertEmbed(range.index, 'customVideo', downloadUrl);
      // 移动光标到视频后面
      quillInstance!.setSelection(range.index + 1);
    }
  });
  
  // 清空光标位置
  currentUploadRange = null;
}

// 暴露方法给父组件
defineExpose({
  getText,
  getHTML,
  clear,
  setContent,
  focus,
  blur
});
</script>

<style lang="scss">
// 富文本内容样式（全局，可复用）
.rich-text-content,
.ql-editor {
  line-height: 1.8;
  color: #303133;
  
  p {
    margin: 0 0 12px 0;
    
    &:last-child {
      margin-bottom: 0;
    }
  }
  
  h1, h2, h3, h4, h5, h6 {
    margin: 16px 0 12px 0;
    font-weight: 600;
  }
  
  ul, ol {
    padding-left: 1.5em;
    margin: 12px 0;
  }
  
  blockquote {
    border-left: 4px solid #C62828;
    padding-left: 16px;
    margin: 12px 0;
    color: #606266;
  }
  
  // 代码块样式
  pre {
    background: #282c34;
    color: #abb2bf;
    padding: 12px;
    border-radius: 4px;
    overflow-x: auto;
    margin: 12px 0;
    
    code {
      background: none;
      padding: 0;
      color: inherit;
      font-size: 14px;
    }
  }
  
  // 行内代码样式（不在 pre 中的 code）
  code:not(pre code) {
    background: #f5f7fa;
    padding: 2px 4px;
    border-radius: 3px;
    font-family: 'Courier New', monospace;
    font-size: 0.9em;
    color: #e83e8c;
  }
  
  a {
    color: #C62828;
    text-decoration: underline;
    
    &:hover {
      color: #A82020;
    }
  }
  
  // 图片样式 - 默认内联显示，底部对齐
  img {
    max-width: 100%;
    height: auto;
    display: inline-block;
    vertical-align: bottom;
  }
  
  // 视频容器样式 - 默认内联显示，底部对齐
  iframe, video {
    max-width: 100%;
    height: auto;
    display: inline-block;
    vertical-align: bottom;
  }
  
  // 自定义视频默认样式 - 单行居中显示
  .custom-video {
    max-width: 100%;
    height: auto;
    display: block;
    margin: 0 auto;
  }
  
  // 自定义图片默认样式 - 与文字同行显示
  .custom-image {
    max-width: 100%;
    height: auto;
    display: inline-block;
    vertical-align: bottom;
  }
  
  // Quill 视频包装器
  .ql-video {
    display: inline-block;
    max-width: 100%;
  }
  
  // 支持对齐方式 - 图片和视频分别处理
  .ql-align-center {
    text-align: center !important;
    
    // 视频始终居中显示
    video, .custom-video {
      display: block !important;
      margin-left: auto !important;
      margin-right: auto !important;
    }
    
    // 图片跟随文字对齐
    img, .custom-image {
      display: inline-block !important;
      vertical-align: bottom !important;
    }
  }
  
  .ql-align-right {
    text-align: right !important;
    
    // 视频始终居中显示
    video, .custom-video {
      display: block !important;
      margin-left: auto !important;
      margin-right: auto !important;
    }
    
    // 图片跟随文字对齐
    img, .custom-image {
      display: inline-block !important;
      vertical-align: bottom !important;
    }
  }
  
  .ql-align-left {
    text-align: left !important;
    
    // 视频始终居中显示
    video, .custom-video {
      display: block !important;
      margin-left: auto !important;
      margin-right: auto !important;
    }
    
    // 图片跟随文字对齐
    img, .custom-image {
      display: inline-block !important;
      vertical-align: bottom !important;
    }
  }
  
  .ql-align-justify {
    text-align: justify;
  }
}
</style>

<style lang="scss" scoped>
.rich-text-component {
  width: 100%;
}

.rich-text-editor {
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  transition: border-color 0.2s;
  
  &:hover {
    border-color: #c0c4cc;
  }
  
  &.is-disabled {
    background-color: #f5f7fa;
    cursor: not-allowed;
    
    :deep(.ql-toolbar),
    :deep(.ql-container) {
      cursor: not-allowed;
    }
  }
  
  &.is-error {
    border-color: #f56c6c;
  }
}

.editor-toolbar {
  border-bottom: 1px solid #dcdfe6;
  background: #fafafa;
  border-radius: 4px 4px 0 0;
  padding: 8px;
  
  :deep(.ql-formats) {
    margin-right: 15px;
  }
  
  :deep(button) {
    width: 28px;
    height: 28px;
    margin: 2px;
    
    &:hover {
      color: #C62828;
    }
    
    &.ql-active {
      color: #C62828;
    }
  }
  
  :deep(select) {
    margin: 2px;
  }
}

.editor-content {
  border-radius: 0 0 4px 4px;
  
  :deep(.ql-editor) {
    min-height: 100%;
    font-size: 14px;
    
    &.ql-blank::before {
      color: #c0c4cc;
      font-style: normal;
    }
  }
}

.word-count {
  margin-top: 8px;
  font-size: 12px;
  color: #909399;
  text-align: right;
}

.error-message {
  margin-top: 8px;
  font-size: 12px;
  color: #f56c6c;
}
</style>

