/* eslint-disable ts/no-use-before-define */
import type { Ref } from 'vue'
import type { useMessage } from 'wot-design-uni'
import { computed, ref } from 'vue'
import { markingSettings } from '../useMarkingSettings'
import { useMarkingCommand } from './useMarkingCommand'

export enum MarkingTool {
  SELECT = 'select',
  RECT = 'rect',
  TEXT = 'text',
  PEN = 'pen',
  CORRECT = 'correct',
  WRONG = 'wrong',
  HALF = 'half',
  ERASER = 'eraser',
}

export interface DomShape {
  id: string
  type: string
  x: number
  y: number
  width?: number
  height?: number
  points?: number[]
  text?: string
  fontSize?: number
  fill?: string
  stroke?: string
  strokeWidth?: number
  [key: string]: any
}

export interface SpecialMark {
  id: string
  type: 'correct' | 'wrong' | 'half'
  x: number
  y: number
}

export interface TextAnnotation {
  id: string
  x: number
  y: number
  text: string
  fontSize: number
  color: string
  scoreValue?: number
}

export interface DomMarkingData {
  version: string
  shapes: DomShape[]
  specialMarks: SpecialMark[]
  annotations: TextAnnotation[]
}

interface SimpleDomLayerProps {
  scale: Ref<number>
  currentTool: Ref<MarkingTool>
  initialData?: DomMarkingData
  /** 位移配置，用于多层叠加渲染 */
  offset?: {
    x: number
    y: number
  }
  /** 快捷打分回调 */
  onQuickScore?: (value: number) => boolean
  /** 文本输入回调 */
  onTextInput?: (pos: { x: number, y: number }) => Promise<string | null>
  /** 只读模式，不响应交互事件 */
  readOnly?: boolean
  message: ReturnType<typeof useMessage>
}

/**
 * 简化的DOM图层管理器
 * 使用Vue响应式系统管理标记数据
 */
export function useSimpleDomLayer({
  scale,
  currentTool,
  initialData,
  offset = { x: 0, y: 0 },
  onQuickScore,
  onTextInput,
  readOnly = false,
  message,
}: SimpleDomLayerProps) {
  // 标记数据
  const markingData = ref<DomMarkingData>(
    {
      version: '1.0',
      shapes: [...(initialData?.shapes || [])],
      specialMarks: [...(initialData?.specialMarks || [])],
      annotations: [...(initialData?.annotations || [])],
    },
  )

  // 命令系统
  const commandSystem = useMarkingCommand()

  // 当前绘制状态
  const isDrawing = ref(false)
  const currentDrawingShape = ref<DomShape | null>(null)

  // 计算属性
  const hasMarks = computed(() => {
    return (
      markingData.value.shapes.length > 0
      || markingData.value.specialMarks.length > 0
      || markingData.value.annotations.length > 0
    )
  })

  /**
   * 生成唯一ID
   */
  const generateId = (): string => {
    return `mark_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
  }

  /**
   * 处理鼠标按下事件
   */
  const handleMouseDown = (e: MouseEvent | TouchEvent, containerRect: DOMRect) => {
    if (readOnly)
      return

    // 检测双指手势，直接返回不处理（让全局缩放处理）
    const touchEvent = e as TouchEvent
    if (touchEvent.touches && touchEvent.touches.length >= 2) {
      return
    }

    const pos = getRelativePosition(e, containerRect)
    if (!pos)
      return

    // 快捷打分点击模式
    if (markingSettings.value.quickScoreMode === 'quick' && currentTool.value === MarkingTool.SELECT) {
      handleQuickScoreClick(pos)
      return
    }

    isDrawing.value = true

    switch (currentTool.value) {
      case MarkingTool.PEN:
        startPenDrawing(pos)
        e.preventDefault()
        break
      case MarkingTool.RECT:
        startRectDrawing(pos)
        e.preventDefault()
        break
      case MarkingTool.CORRECT:
        addSpecialMark('correct', pos)
        break
      case MarkingTool.WRONG:
        addSpecialMark('wrong', pos)
        break
      case MarkingTool.HALF:
        addSpecialMark('half', pos)
        break
      case MarkingTool.TEXT:
        addTextAnnotation(pos)
        break
      case MarkingTool.ERASER:
        eraseAt(pos)
        break
    }
  }

  /**
   * 处理鼠标移动事件
   */
  const handleMouseMove = (e: MouseEvent | TouchEvent, containerRect: DOMRect) => {
    if (!isDrawing.value || readOnly)
      return

    // 检测双指手势，直接返回不处理（让全局缩放处理）
    const touchEvent = e as TouchEvent
    if (touchEvent.touches && touchEvent.touches.length >= 2) {
      return
    }

    const pos = getRelativePosition(e, containerRect)
    if (!pos)
      return

    if (currentTool.value === MarkingTool.PEN) {
      e.preventDefault()
      continuePenDrawing(pos)
    }
    else if (currentTool.value === MarkingTool.RECT) {
      e.preventDefault()
      continueRectDrawing(pos)
    }
    else if (currentTool.value === MarkingTool.ERASER) {
      e.preventDefault()
      eraseAt(pos)
    }
  }

  /**
   * 处理鼠标抬起事件
   */
  const handleMouseUp = () => {
    if (!isDrawing.value)
      return

    if (currentDrawingShape.value) {
      finishDrawing()
    }

    isDrawing.value = false
    currentDrawingShape.value = null
  }

  /**
   * 获取相对位置（应用缩放和位移偏移）
   */
  const getRelativePosition = (e: MouseEvent | TouchEvent, containerRect: DOMRect) => {
    let clientX: number
    let clientY: number

    if (typeof window !== 'undefined' && window.MouseEvent && e instanceof MouseEvent) {
      clientX = e.clientX
      clientY = e.clientY
    }
    else {
      const touchEvent = e as TouchEvent
      const touch = touchEvent.touches[0] || touchEvent.changedTouches[0]
      if (!touch)
        return null
      clientX = touch.clientX
      clientY = touch.clientY
    }

    return {
      x: (clientX - containerRect.left) / scale.value - offset.x,
      y: (clientY - containerRect.top) / scale.value - offset.y,
    }
  }

  /**
   * 开始笔绘制
   */
  const startPenDrawing = (pos: { x: number, y: number }) => {
    currentDrawingShape.value = {
      id: generateId(),
      type: 'line',
      x: 0,
      y: 0,
      points: [pos.x, pos.y],
      stroke: markingSettings.value.penColor,
      strokeWidth: markingSettings.value.penWidth,
    }
  }

  /**
   * 继续笔绘制
   */
  const continuePenDrawing = (pos: { x: number, y: number }) => {
    if (currentDrawingShape.value && currentDrawingShape.value.points) {
      currentDrawingShape.value.points.push(
        Number(pos.x.toFixed(1)),
        Number(pos.y.toFixed(1)),
      )
    }
  }

  /**
   * 开始矩形绘制
   */
  const startRectDrawing = (pos: { x: number, y: number }) => {
    currentDrawingShape.value = {
      id: generateId(),
      type: 'rect',
      x: pos.x,
      y: pos.y,
      width: 0,
      height: 0,
      stroke: markingSettings.value.penColor,
      strokeWidth: 2,
      startX: pos.x,
      startY: pos.y,
    }
  }

  /**
   * 继续矩形绘制
   */
  const continueRectDrawing = (pos: { x: number, y: number }) => {
    if (currentDrawingShape.value && currentDrawingShape.value.startX !== undefined) {
      const startX = currentDrawingShape.value.startX
      const startY = currentDrawingShape.value.startY!
      const width = pos.x - startX
      const height = pos.y - startY

      currentDrawingShape.value.width = Math.abs(width)
      currentDrawingShape.value.height = Math.abs(height)
      currentDrawingShape.value.x = width < 0 ? pos.x : startX
      currentDrawingShape.value.y = height < 0 ? pos.y : startY
    }
  }

  /**
   * 完成绘制
   */
  const finishDrawing = () => {
    if (!currentDrawingShape.value)
      return

    // 清理临时属性
    const shape = { ...currentDrawingShape.value }
    delete shape.startX
    delete shape.startY

    console.log('[SimpleDomLayer] finishDrawing - creating AddShapeCommand for:', shape)
    const command = new commandSystem.AddShapeCommand(markingData.value, shape, null)
    commandSystem.executeCommand(command)
  }

  /**
   * 添加特殊标记
   */
  const addSpecialMark = (type: 'correct' | 'wrong' | 'half', pos: { x: number, y: number }) => {
    const mark: SpecialMark = {
      id: generateId(),
      type,
      x: pos.x,
      y: pos.y,
    }

    console.log('[SimpleDomLayer] addSpecialMark - creating AddSpecialMarkCommand for:', mark)
    const command = new commandSystem.AddSpecialMarkCommand(markingData.value, mark, null)
    commandSystem.executeCommand(command)

    isDrawing.value = false
  }

  /**
   * 添加文本注释
   */
  const addTextAnnotation = async (pos: { x: number, y: number }) => {
    let text: string | null = null

    // 如果提供了回调，使用回调获取文本
    if (onTextInput) {
      text = await onTextInput(pos)
    }
    else {
      // 否则使用默认的 message 弹窗
      text = await message.show({
        title: '请输入文字:',
        type: 'prompt',
      }).then((res) => {
        return res.value?.toString() || null
      }).catch(() => null)
    }

    if (text) {
      const annotation: TextAnnotation = {
        id: generateId(),
        x: pos.x,
        y: pos.y,
        text: text.toString(),
        fontSize: markingSettings.value.textSize,
        color: markingSettings.value.textColor,
      }

      console.log('[SimpleDomLayer] addTextAnnotation - creating AddTextCommand for:', annotation)
      const command = new commandSystem.AddTextCommand(markingData.value, annotation, null)
      commandSystem.executeCommand(command)
    }

    isDrawing.value = false
  }

  /**
   * 擦除指定位置的元素
   */
  const eraseAt = (pos: { x: number, y: number }) => {
    // 查找点击位置的元素
    const foundId = findElementAtPosition(pos)

    if (foundId) {
      console.log('[SimpleDomLayer] eraseAt - creating EraseCommand for:', foundId)
      const command = new commandSystem.EraseCommand(markingData.value, foundId, null)
      commandSystem.executeCommand(command)
    }
  }

  /**
   * 查找指定位置的元素
   */
  const findElementAtPosition = (pos: { x: number, y: number }): string | null => {
    // 检查特殊标记（优先级最高，因为它们通常最小）
    for (const mark of markingData.value.specialMarks) {
      if (isPointInSpecialMark(pos, mark)) {
        return mark.id
      }
    }

    // 检查文本注释
    for (const annotation of markingData.value.annotations) {
      if (isPointInText(pos, annotation)) {
        return annotation.id
      }
    }

    // 检查形状
    for (const shape of markingData.value.shapes) {
      if (isPointInShape(pos, shape)) {
        return shape.id
      }
    }

    return null
  }

  /**
   * 判断点是否在特殊标记内
   */
  const isPointInSpecialMark = (pos: { x: number, y: number }, mark: SpecialMark): boolean => {
    const size = 64 // 特殊标记的大小
    return (
      pos.x >= mark.x - size / 2
      && pos.x <= mark.x + size / 2
      && pos.y >= mark.y - size / 2
      && pos.y <= mark.y + size / 2
    )
  }

  /**
   * 判断点是否在文本内
   */
  const isPointInText = (pos: { x: number, y: number }, text: TextAnnotation): boolean => {
    // 简单估算文本宽度和高度
    const estimatedWidth = text.text.length * text.fontSize * 0.6
    const estimatedHeight = text.fontSize * 1.2

    return (
      pos.x >= text.x
      && pos.x <= text.x + estimatedWidth
      && pos.y >= text.y
      && pos.y <= text.y + estimatedHeight
    )
  }

  /**
   * 判断点是否在形状内
   */
  const isPointInShape = (pos: { x: number, y: number }, shape: DomShape): boolean => {
    if (shape.type === 'rect') {
      return (
        pos.x >= shape.x
        && pos.x <= shape.x + (shape.width || 0)
        && pos.y >= shape.y
        && pos.y <= shape.y + (shape.height || 0)
      )
    }
    else if (shape.type === 'line' && shape.points) {
      // 检查点是否靠近线条
      const threshold = (shape.strokeWidth || 2) + 5
      for (let i = 0; i < shape.points.length - 2; i += 2) {
        const x1 = shape.points[i]
        const y1 = shape.points[i + 1]
        const x2 = shape.points[i + 2]
        const y2 = shape.points[i + 3]

        const distance = pointToLineDistance(pos, { x: x1, y: y1 }, { x: x2, y: y2 })
        if (distance < threshold) {
          return true
        }
      }
    }

    return false
  }

  /**
   * 计算点到线段的距离
   */
  const pointToLineDistance = (
    point: { x: number, y: number },
    lineStart: { x: number, y: number },
    lineEnd: { x: number, y: number },
  ): number => {
    const A = point.x - lineStart.x
    const B = point.y - lineStart.y
    const C = lineEnd.x - lineStart.x
    const D = lineEnd.y - lineStart.y

    const dot = A * C + B * D
    const lenSq = C * C + D * D
    let param = -1

    if (lenSq !== 0) {
      param = dot / lenSq
    }

    let xx: number
    let yy: number

    if (param < 0) {
      xx = lineStart.x
      yy = lineStart.y
    }
    else if (param > 1) {
      xx = lineEnd.x
      yy = lineEnd.y
    }
    else {
      xx = lineStart.x + param * C
      yy = lineStart.y + param * D
    }

    const dx = point.x - xx
    const dy = point.y - yy

    return Math.sqrt(dx * dx + dy * dy)
  }

  /**
   * 处理快捷打分点击
   */
  const handleQuickScoreClick = (pos: { x: number, y: number }) => {
    const value = markingSettings.value.quickScoreClickValue
    const scoreMode = markingSettings.value.scoreMode
    const finalValue = scoreMode === 'add' ? value : -value

    // 如果是0则不应用
    if (value === 0) {
      isDrawing.value = false
      return
    }
    const result = onQuickScore(finalValue)
    console.log('[SimpleDomLayer] handleQuickScoreClick - result:', result)
    if (!result) {
      isDrawing.value = false
      return
    }

    // 创建文字标记
    const text = scoreMode === 'add' ? `+${value}` : `-${value}`
    const annotation: TextAnnotation = {
      id: generateId(),
      x: pos.x,
      y: pos.y,
      text,
      fontSize: 48,
      color: scoreMode === 'add' ? '#ff4d4f' : '#1890ff',
      scoreValue: finalValue,
    }

    console.log('[SimpleDomLayer] handleQuickScoreClick - creating text annotation:', annotation)
    const command = new commandSystem.AddTextCommand(markingData.value, annotation, null)
    commandSystem.executeCommand(command)

    isDrawing.value = false
  }

  /**
   * 清空所有标记
   */
  const clearAllMarks = () => {
    console.log('[SimpleDomLayer] clearAllMarks - creating ClearAllCommand')
    const command = new commandSystem.ClearAllCommand(markingData.value, null)
    commandSystem.executeCommand(command)
  }

  /**
   * 删除指定注释
   */
  const deleteAnnotation = (annotationId: string) => {
    console.log('[SimpleDomLayer] deleteAnnotation - creating EraseCommand for:', annotationId)
    const command = new commandSystem.EraseCommand(markingData.value, annotationId, null)
    commandSystem.executeCommand(command)
  }

  return {
    // 数据状态
    markingData,
    hasMarks,
    currentDrawingShape,
    isDrawing,

    // 历史记录状态
    canUndo: commandSystem.canUndo,
    canRedo: commandSystem.canRedo,

    // 事件处理
    handleMouseDown,
    handleMouseMove,
    handleMouseUp,

    // 操作方法
    clearAllMarks,
    deleteAnnotation,
    undo: () => {
      console.log('[SimpleDomLayer] undo triggered')
      return commandSystem.undo()
    },
    redo: () => {
      console.log('[SimpleDomLayer] redo triggered')
      return commandSystem.redo()
    },

    // 数据导入导出
    exportData: () => JSON.stringify(markingData.value),
    importData: (data: string) => {
      try {
        markingData.value = JSON.parse(data)
        return true
      }
      catch {
        return false
      }
    },
  }
}
