/**
 * @description Quill 图片/视频缩放功能
 * @author yslg
 * @since 2025-10-18
 */

import Quill from 'quill';

interface ResizeOptions {
  modules?: string[];
  onResizeEnd?: (element: HTMLElement) => void; // 拉伸结束回调
}

interface ResizeState {
  startX: number;
  startY: number;
  startWidth: number;
  startHeight: number;
  aspectRatio: number;
  position: string;
}

export class ImageResize {
  quill: any;
  options: ResizeOptions;
  overlay: HTMLElement | null = null;
  element: HTMLImageElement | HTMLVideoElement | null = null;
  resizeState: ResizeState | null = null;

  constructor(quill: any, options: ResizeOptions = {}) {
    this.quill = quill;
    this.options = options;
    
    
    // 等待编辑器完全初始化
    setTimeout(() => {
      this.initEventListeners();
    }, 100);
  }

  private initEventListeners() {
    // 监听编辑器点击事件
    this.quill.root.addEventListener('click', this.handleClick.bind(this));
    
    // 点击编辑器外部时隐藏 resize 控件
    document.addEventListener('click', this.handleDocumentClick.bind(this));
  }

  handleClick(e: MouseEvent) {
    const target = e.target as HTMLElement;
    
    
    // 检查是否点击了图片或视频
    if (this.isResizableElement(target)) {
      this.showResizer(target as HTMLImageElement | HTMLVideoElement);
    } else if (!this.overlay || !this.overlay.contains(target)) {
      this.hideResizer();
    }
  }

  private isResizableElement(element: HTMLElement): boolean {
    return element.tagName === 'IMG' || element.tagName === 'VIDEO';
  }

  handleDocumentClick(e: MouseEvent) {
    const target = e.target as HTMLElement;
    
    // 如果点击的不是编辑器内的元素，隐藏 resizer
    if (!this.quill.root.contains(target) && this.overlay) {
      this.hideResizer();
    }
  }

  showResizer(element: HTMLImageElement | HTMLVideoElement) {
    this.element = element;
    
    
    // 创建遮罩层
    if (!this.overlay) {
      this.createOverlay();
    }
    
    if (!this.overlay) return;
    
    // 更新遮罩层位置和大小
    this.updateOverlayPosition(element);
    
  }

  private updateOverlayPosition(element: HTMLImageElement | HTMLVideoElement) {
    if (!this.overlay) return;
    
    const rect = element.getBoundingClientRect();
    const containerRect = this.quill.root.getBoundingClientRect();
  
    
    this.overlay.style.display = 'block';
    this.overlay.style.left = `${rect.left - containerRect.left + this.quill.root.scrollLeft}px`;
    this.overlay.style.top = `${rect.top - containerRect.top + this.quill.root.scrollTop}px`;
    this.overlay.style.width = `${rect.width}px`;
    this.overlay.style.height = `${rect.height}px`;
  }

  hideResizer() {
    if (this.overlay) {
      this.overlay.style.display = 'none';
    }
    this.element = null;
    this.resizeState = null;
  }

  createOverlay() {
    // 创建遮罩层
    this.overlay = document.createElement('div');
    this.overlay.className = 'quill-resize-overlay';
    this.overlay.style.cssText = `
      position: absolute;
      border: 2px solid #409eff;
      box-sizing: border-box;
      display: none;
      z-index: 100;
    `;
    
    // 创建8个拉伸手柄
    const positions = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w'];
    positions.forEach(pos => {
      const handle = document.createElement('div');
      handle.className = `quill-resize-handle quill-resize-handle-${pos}`;
      handle.style.cssText = `
        position: absolute;
        width: 12px;
        height: 12px;
        background: #409eff;
        border: 2px solid #fff;
        border-radius: 50%;
        cursor: ${this.getCursor(pos)};
      `;
      
      // 设置位置
      this.setHandlePosition(handle, pos);
      
      // 添加拖拽事件
      handle.addEventListener('mousedown', (e) => this.handleMouseDown(e, pos));
      
      this.overlay!.appendChild(handle);
    });
    
    this.quill.root.parentNode.style.position = 'relative';
    this.quill.root.parentNode.appendChild(this.overlay);
  }

  setHandlePosition(handle: HTMLElement, position: string) {
    const offset = '-6px'; // handle 宽度的一半
    
    switch (position) {
      case 'nw':
        handle.style.top = offset;
        handle.style.left = offset;
        break;
      case 'n':
        handle.style.top = offset;
        handle.style.left = '50%';
        handle.style.marginLeft = offset;
        break;
      case 'ne':
        handle.style.top = offset;
        handle.style.right = offset;
        break;
      case 'e':
        handle.style.top = '50%';
        handle.style.right = offset;
        handle.style.marginTop = offset;
        break;
      case 'se':
        handle.style.bottom = offset;
        handle.style.right = offset;
        break;
      case 's':
        handle.style.bottom = offset;
        handle.style.left = '50%';
        handle.style.marginLeft = offset;
        break;
      case 'sw':
        handle.style.bottom = offset;
        handle.style.left = offset;
        break;
      case 'w':
        handle.style.top = '50%';
        handle.style.left = offset;
        handle.style.marginTop = offset;
        break;
    }
  }

  getCursor(position: string): string {
    const cursors: Record<string, string> = {
      'nw': 'nw-resize',
      'n': 'n-resize',
      'ne': 'ne-resize',
      'e': 'e-resize',
      'se': 'se-resize',
      's': 's-resize',
      'sw': 'sw-resize',
      'w': 'w-resize'
    };
    return cursors[position] || 'default';
  }

  handleMouseDown(e: MouseEvent, position: string) {
    e.preventDefault();
    e.stopPropagation();
    
    if (!this.element || !this.overlay) return;
    
    // 初始化拉伸状态
    this.resizeState = {
      startX: e.clientX,
      startY: e.clientY,
      startWidth: this.element.offsetWidth,
      startHeight: this.element.offsetHeight,
      aspectRatio: this.element.offsetWidth / this.element.offsetHeight,
      position
    };
    
    const handleMouseMove = (moveEvent: MouseEvent) => {
      if (!this.element || !this.overlay || !this.resizeState) return;
      
      this.updateElementSize(moveEvent);
    };
    
    const handleMouseUp = () => {
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
      
      // 拉伸结束，触发更新
      this.onResizeEnd();
    };
    
    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);
  }

  private updateElementSize(moveEvent: MouseEvent) {
    if (!this.element || !this.overlay || !this.resizeState) return;
    
    const deltaX = moveEvent.clientX - this.resizeState.startX;
    const deltaY = moveEvent.clientY - this.resizeState.startY;
    
    let newWidth = this.resizeState.startWidth;
    let newHeight = this.resizeState.startHeight;
    
    // 根据拉伸方向计算新尺寸
    if (this.resizeState.position.includes('e')) {
      newWidth = this.resizeState.startWidth + deltaX;
    } else if (this.resizeState.position.includes('w')) {
      newWidth = this.resizeState.startWidth - deltaX;
    }
    
    if (this.resizeState.position.includes('s')) {
      newHeight = this.resizeState.startHeight + deltaY;
    } else if (this.resizeState.position.includes('n')) {
      newHeight = this.resizeState.startHeight - deltaY;
    }
    
    // 保持纵横比（对于对角拉伸）
    if (this.resizeState.position.length === 2) {
      newHeight = newWidth / this.resizeState.aspectRatio;
    }
    
    // 限制最小尺寸
    if (newWidth < 50) newWidth = 50;
    if (newHeight < 50) newHeight = 50;
    
    // 应用新尺寸
    this.applyElementSize(newWidth, newHeight);
    
    // 更新遮罩层
    this.overlay.style.width = `${newWidth}px`;
    this.overlay.style.height = `${newHeight}px`;
  }

  private applyElementSize(width: number, height: number) {
    if (!this.element) return;
    
    // 同时设置 style 和属性
    this.element.style.width = `${width}px`;
    this.element.style.height = `${height}px`;
    this.element.setAttribute('width', `${width}`);
    this.element.setAttribute('height', `${height}`);
  }

  private onResizeEnd() {
    if (!this.element) return;
    
    
    // 调用自定义回调
    if (this.options.onResizeEnd) {
      this.options.onResizeEnd(this.element);
    }
    
    // 强制触发 Quill 的内容更新
    this.triggerQuillUpdate();
  }

  private triggerQuillUpdate() {
    // 方案1: 使用 Quill 的内部方法
    if (this.quill.emitter) {
      this.quill.emitter.emit('text-change', {
        oldRange: null,
        range: null,
        source: 'user'
      });
    }
    
    // 方案2: 触发 DOM 事件
    const inputEvent = new Event('input', { bubbles: true });
    this.quill.root.dispatchEvent(inputEvent);
    
    // 方案3: 强制更新 Quill 内容
    setTimeout(() => {
      if (this.quill.update) {
        this.quill.update();
      }
    }, 0);
  }

  destroy() {
    if (this.overlay) {
      this.overlay.remove();
    }
    document.removeEventListener('click', this.handleDocumentClick);
  }
}

// 注册为 Quill 模块
export function registerImageResize() {
  Quill.register('modules/imageResize', ImageResize);
}

// 默认导出类
export default ImageResize;

