<template>
  <div class="table-canvas" ref="containerRef">
    <v-stage 
      ref="stageRef"
      :config="stageConfig"
      @mousedown="handleStageMouseDown"
      @mousemove="handleStageMouseMove"
      @mouseup="handleStageMouseUp"
      @dragend="handleStageDragEnd"
    >
      <!-- 图片层（带旋转变换） -->
      <v-layer :config="imageLayerConfig">
        <v-image 
          v-if="imageObj"
          :config="{
            image: imageObj,
            width: displayWidth,
            height: displayHeight
          }"
        />
      </v-layer>
      
      <!-- 表格边界框层（不跟随旋转，保持横平竖直） -->
      <v-layer>
        <!-- 已定义的边界框 -->
        <v-rect
          v-if="editorStore.hasDefinedBbox"
          :config="{
            x: displayTableBbox[0],
            y: displayTableBbox[1],
            width: displayTableBbox[2] - displayTableBbox[0],
            height: displayTableBbox[3] - displayTableBbox[1],
            // stroke: '#67c23a',
            stroke: '#ff0000', // 使用红色边框更醒目
            strokeWidth: 2,
            dash: [8, 4],
            listening: false
          }"
        />
        
        <!-- 正在绘制的边界框 -->
        <v-rect
          v-if="isDrawingBbox && bboxStart && bboxEnd"
          :config="{
            x: Math.min(bboxStart.x, bboxEnd.x),
            y: Math.min(bboxStart.y, bboxEnd.y),
            width: Math.abs(bboxEnd.x - bboxStart.x),
            height: Math.abs(bboxEnd.y - bboxStart.y),
            stroke: '#ff9900', // 使用橙色边框更醒目
            strokeWidth: 2,
            dash: [5, 5],
            listening: false
          }"
        />
      </v-layer>
      
      <!-- 线条层（不跟随旋转，保持横平竖直） -->
      <v-layer>
        <!-- 横线 -->
        <v-group
          v-for="(y, index) in displayHorizontalLines"
          :key="'h-' + index"
          :config="{
            x: 0,
            y: y,
            draggable: !editorStore.isDefiningBbox,
            dragBoundFunc: (pos: { x: number; y: number }) => horizontalDragBound(pos, index)
          }"
          @click="() => selectLine('h', index)"
          @dragstart="handleLineDragStart"
          @dragmove="(e: KonvaEventObject<DragEvent>) => handleHorizontalDragMove(e)"
          @dragend="(e: KonvaEventObject<DragEvent>) => handleHorizontalDragEnd(e, index)"
        >
          <v-line
            :config="{
              points: [horizontalLineEndpoints.x1, 0, horizontalLineEndpoints.x2, 0],
              stroke: getLineColor('h', index),
              strokeWidth: isLineSelected('h', index) ? 3 : 2,
              hitStrokeWidth: 10
            }"
          />
          <!-- 左侧标签 -->
          <v-label
            :config="{
              x: horizontalLineEndpoints.x1 - 40,
              y: -10
            }"
          >
            <v-tag
              :config="{
                fill: 'white',
                stroke: 'black',
                strokeWidth: 1,
                cornerRadius: 3
              }"
            />
            <v-text
              :config="{
                text: 'R' + (index + 1),
                fontSize: 12,
                fontFamily: 'Arial',
                fill: getLineColor('h', index),
                padding: 3
              }"
            />
          </v-label>
          <!-- 右侧标签 -->
          <v-label
            :config="{
              x: horizontalLineEndpoints.x2 + 10,
              y: -10
            }"
          >
            <v-tag
              :config="{
                fill: 'white',
                stroke: 'black',
                strokeWidth: 1,
                cornerRadius: 3
              }"
            />
            <v-text
              :config="{
                text: 'R' + (index + 1),
                fontSize: 12,
                fontFamily: 'Arial',
                fill: getLineColor('h', index),
                padding: 3
              }"
            />
          </v-label>
        </v-group>
        
        <!-- 竖线 -->
        <v-group
          v-for="(x, index) in displayVerticalLines"
          :key="'v-' + index"
          :config="{
            x: x,
            y: 0,
            draggable: !editorStore.isDefiningBbox,
            dragBoundFunc: (pos: { x: number; y: number }) => verticalDragBound(pos, index)
          }"
          @click="() => selectLine('v', index)"
          @dragstart="handleLineDragStart"
          @dragmove="(e: KonvaEventObject<DragEvent>) => handleVerticalDragMove(e)"
          @dragend="(e: KonvaEventObject<DragEvent>) => handleVerticalDragEnd(e, index)"
        >
          <v-line
            :config="{
              points: [0, verticalLineEndpoints.y1, 0, verticalLineEndpoints.y2],
              stroke: getLineColor('v', index),
              strokeWidth: isLineSelected('v', index) ? 3 : 2,
              hitStrokeWidth: 10
            }"
          />
          <!-- 上方标签 -->
          <v-label
            :config="{
              x: -12,
              y: verticalLineEndpoints.y1 - 25
            }"
          >
            <v-tag
              :config="{
                fill: 'white',
                stroke: 'black',
                strokeWidth: 1,
                cornerRadius: 3
              }"
            />
            <v-text
              :config="{
                text: 'C' + (index + 1),
                fontSize: 12,
                fontFamily: 'Arial',
                fill: getLineColor('v', index),
                padding: 3
              }"
            />
          </v-label>
          <!-- 下方标签 -->
          <v-label
            :config="{
              x: -12,
              y: verticalLineEndpoints.y2 + 10
            }"
          >
            <v-tag
              :config="{
                fill: 'white',
                stroke: 'black',
                strokeWidth: 1,
                cornerRadius: 3
              }"
            />
            <v-text
              :config="{
                text: 'C' + (index + 1),
                fontSize: 12,
                fontFamily: 'Arial',
                fill: getLineColor('v', index),
                padding: 3
              }"
            />
          </v-label>
        </v-group>
      </v-layer>
    </v-stage>
    
    <!-- 工具栏 -->
    <div class="canvas-toolbar">
      <el-button-group>
        <el-button size="small" @click="zoomIn" title="放大">
          <el-icon><ZoomIn /></el-icon>
        </el-button>
        <el-button size="small" @click="zoomOut" title="缩小">
          <el-icon><ZoomOut /></el-icon>
        </el-button>
        <el-button size="small" @click="resetView" title="重置视图">
          <el-icon><Refresh /></el-icon>
        </el-button>
      </el-button-group>
      <span class="zoom-display">{{ Math.round(editorStore.zoom * 100) }}%</span>

      <el-button-group>
        <el-button
          size="small"
          :type="viewMode === 'table' ? 'primary' : 'default'"
          @click="focusTableView(true)"
          :disabled="!hasTableBbox"
          title="聚焦表格区域"
        >
          <el-icon><View /></el-icon>
          表格视图
        </el-button>
        <el-button
          size="small"
          :type="viewMode === 'image' ? 'primary' : 'default'"
          @click="focusFullImage(true)"
          title="查看整张图片"
        >
          <el-icon><FullScreen /></el-icon>
          全图视图
        </el-button>
      </el-button-group>
      
      <!-- 定义边界框按钮 -->
      <el-button 
        size="small" 
        :type="editorStore.isDefiningBbox ? 'warning' : 'default'"
        @click="toggleDefineBbox"
        title="框选表格区域"
      >
        <el-icon><Crop /></el-icon>
        {{ editorStore.isDefiningBbox ? '完成框选' : '框选表格' }}
      </el-button>
    </div>
    
    <!-- 提示信息 -->
    <div v-if="editorStore.isDefiningBbox" class="bbox-hint">
      按住鼠标左键拖动绘制表格边界框
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { useEditorStore } from '@/stores'
import { useCanvasInteraction } from '@/composables'
import { ZoomIn, ZoomOut, Refresh, Crop, View, FullScreen } from '@element-plus/icons-vue'
import type { KonvaEventObject } from 'konva/lib/Node'

const editorStore = useEditorStore()
const { 
  displayToOriginal, 
  displayHorizontalLines,
  displayVerticalLines,
  displayTableBbox,
  horizontalLineEndpoints,
  verticalLineEndpoints
} = useCanvasInteraction()

const containerRef = ref<HTMLElement | null>(null)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const stageRef = ref<any>(null)
const imageObj = ref<HTMLImageElement | null>(null)
const viewMode = ref<'table' | 'image' | 'free'>('image')
const hasTableBbox = computed(() => editorStore.hasDefinedBbox)

// 边界框绘制状态
const isDrawingBbox = ref(false)
const bboxStart = ref<{ x: number; y: number } | null>(null)
const bboxEnd = ref<{ x: number; y: number } | null>(null)

// 计算画布尺寸
const stageConfig = computed(() => ({
  width: containerRef.value?.clientWidth || 800,
  height: containerRef.value?.clientHeight || 600,
  scaleX: editorStore.zoom,
  scaleY: editorStore.zoom,
  x: editorStore.stagePos.x,
  y: editorStore.stagePos.y,
  draggable: !editorStore.isDefiningBbox  // 定义边界框时禁止拖拽画布
}))

// 显示尺寸（原图尺寸 * scaleFactor）
const displayWidth = computed(() => editorStore.imageSize.width * editorStore.scaleFactor)
const displayHeight = computed(() => editorStore.imageSize.height * editorStore.scaleFactor)

// 旋转角度（度）供 Konva 使用
const imageRotation = computed(() => editorStore.skewAngle)

// 图片、边界框、线条的统一旋转配置（绕图片中心）
const imageLayerConfig = computed(() => ({
  rotation: imageRotation.value,
  offsetX: displayWidth.value / 2,
  offsetY: displayHeight.value / 2,
  x: displayWidth.value / 2,
  y: displayHeight.value / 2
}))

// 加载图片并应用表格视图
watch(() => editorStore.imageSrc, (newSrc: string | null) => {
  if (newSrc) {
    const img = new Image()
    img.onload = () => {
      imageObj.value = img
      // 图片加载完成后，设置默认表格视图
      viewMode.value = 'table'
      // 使用 setTimeout 确保 Vue 响应式更新和 DOM 渲染完成
      setTimeout(() => {
        applyViewMode()
      }, 50)
    }
    img.src = `data:image/png;base64,${newSrc}`
  } else {
    imageObj.value = null
    viewMode.value = 'image'
  }
}, { immediate: true })

function clampZoom(value: number) {
  return Math.max(0.25, Math.min(2.0, value))
}

function getContainerSize() {
  const width = containerRef.value?.clientWidth || 0
  const height = containerRef.value?.clientHeight || 0
  // console.log('Container size:', { width, height })  // 添加日志
  return { width, height }
}

function focusFullImage(setMode = false) {
  const { width: containerWidth, height: containerHeight } = getContainerSize()
  if (!containerWidth || !containerHeight || !displayWidth.value || !displayHeight.value) return

  const zoomX = containerWidth / displayWidth.value
  const zoomY = containerHeight / displayHeight.value
  const targetZoom = clampZoom(Math.min(zoomX, zoomY) * 0.95)
  const centerX = displayWidth.value / 2
  const centerY = displayHeight.value / 2

  editorStore.setZoom(targetZoom)
  editorStore.setStagePos(
    containerWidth / 2 - centerX * targetZoom,
    containerHeight / 2 - centerY * targetZoom
  )

  if (setMode) {
    viewMode.value = 'image'
  }
}

function focusTableView(setMode = false) {
  const { width: containerWidth, height: containerHeight } = getContainerSize()
  if (!containerWidth || !containerHeight) return

  if (!hasTableBbox.value) {
    focusFullImage(setMode)
    return
  }

  const hLines = displayHorizontalLines.value
  const vLines = displayVerticalLines.value
  
  if (hLines.length === 0 || vLines.length === 0) {
    focusFullImage(setMode)
    return
  }
  
  const x1 = Math.min(...vLines)
  const x2 = Math.max(...vLines)
  const y1 = Math.min(...hLines)
  const y2 = Math.max(...hLines)

  // 考虑标签占用的空间和底部遮挡
  const PADDING = 15
  const BOTTOM_OVERLAY = 60 // 底部工具栏高度
  
  const paddedX1 = x1 - PADDING
  const paddedX2 = x2 + PADDING
  const paddedY1 = y1 - PADDING
  const paddedY2 = y2 + PADDING

  const bboxWidth = paddedX2 - paddedX1
  const bboxHeight = paddedY2 - paddedY1

  if (bboxWidth <= 0 || bboxHeight <= 0) {
    focusFullImage(setMode)
    return
  }

  // 计算可视区域高度
  const visibleHeight = Math.max(100, containerHeight - BOTTOM_OVERLAY)

  // 计算缩放比例
  const zoomX = containerWidth / bboxWidth
  const zoomY = visibleHeight / bboxHeight
  // 使用 0.9 的系数，留出一点边距
  const targetZoom = clampZoom(Math.min(zoomX, zoomY) * 0.9)
  
  // 计算表格中心点
  const centerX = (paddedX1 + paddedX2) / 2
  const centerY = (paddedY1 + paddedY2) / 2
  
  // 将表格中心对齐到可视区域中心
  const offsetX = containerWidth / 2 - centerX * targetZoom
  const offsetY = visibleHeight / 2 - centerY * targetZoom

  // console.log('Lines range:', { x1, x2, y1, y2 })
  // console.log('Padded bbox:', { paddedX1, paddedX2, paddedY1, paddedY2, bboxWidth, bboxHeight })
  // console.log('Zoom calculation:', { zoomX, zoomY, targetZoom, visibleHeight })
  // console.log('Center:', { centerX, centerY })
  // console.log('Offset:', { offsetX, offsetY })

  editorStore.setZoom(targetZoom)
  editorStore.setStagePos(offsetX, offsetY)

  if (setMode) {
    viewMode.value = 'table'
  }
}

function applyViewMode() {
  if (!editorStore.hasData) return
  if (viewMode.value === 'free') return
  if (viewMode.value === 'table') {
    if (hasTableBbox.value) {
      focusTableView()
    } else {
      viewMode.value = 'image'
      focusFullImage()
    }
    return
  }
  focusFullImage()
}

watch(
  () => [hasTableBbox.value, displayWidth.value, displayHeight.value, displayTableBbox.value.join(',')],
  () => {
    if (viewMode.value !== 'free') {
      applyViewMode()
    }
  }
)

function handleStageDragEnd(e: KonvaEventObject<DragEvent>) {
  const stageNode = stageRef.value?.getNode()
  // 仅在舞台本身被拖拽时更新位置
  if (stageNode && e.target === stageNode) {
    editorStore.setStagePos(stageNode.x(), stageNode.y())
    viewMode.value = 'free'
  }
}

function handleLineDragStart() {
  viewMode.value = 'free'
}

// 横线拖拽移动中 - 实时修正 X 轴偏移
function handleHorizontalDragMove(e: KonvaEventObject<DragEvent>) {
  const node = e.target
  // 横线只能垂直移动，强制 X 轴为 0
  if (node.x() !== 0) {
    node.x(0)
  }
}

// 竖线拖拽移动中 - 实时修正 Y 轴偏移
function handleVerticalDragMove(e: KonvaEventObject<DragEvent>) {
  const node = e.target
  // 竖线只能水平移动，强制 Y 轴为 0
  if (node.y() !== 0) {
    node.y(0)
  }
}

// 横线拖拽约束
// pos 是 group 即将移动到的绝对位置
function horizontalDragBound(pos: { x: number; y: number }, _index: number) {
  // 约束 Y 在图片边界内（不是表格边界，允许调整到任意位置）
  return {
    x: 0,  // 横线 X 保持 0
    y: Math.max(0, Math.min(pos.y, displayHeight.value))
  }
}

// 竖线拖拽约束
function verticalDragBound(pos: { x: number; y: number }, _index: number) {
  // 约束 X 在图片边界内（不是表格边界，允许调整到任意位置）
  return {
    x: Math.max(0, Math.min(pos.x, displayWidth.value)),
    y: 0  // 竖线 Y 保持 0
  }
}

// 横线拖拽结束
function handleHorizontalDragEnd(e: KonvaEventObject<DragEvent>, index: number) {
  const node = e.target
  const newY = node.y()  // group 的新 Y 位置就是线条的显示坐标
  
  // 转换为原图坐标
  const originalY = displayToOriginal(newY)
  editorStore.updateLinePosition('h', index, originalY)
  
  // 重置 x 位置（确保横线只垂直移动）
  node.x(0)
  viewMode.value = 'free'
}

// 竖线拖拽结束
function handleVerticalDragEnd(e: KonvaEventObject<DragEvent>, index: number) {
  const node = e.target
  const newX = node.x()  // group 的新 X 位置就是线条的显示坐标
  
  // 转换为原图坐标
  const originalX = displayToOriginal(newX)
  editorStore.updateLinePosition('v', index, originalX)
  
  // 重置 y 位置（确保竖线只水平移动）
  node.y(0)
  viewMode.value = 'free'
}

// 选中线条
function selectLine(type: 'h' | 'v', index: number) {
  if (!editorStore.isDefiningBbox) {
    editorStore.selectLine({ type, index })
  }
}

// 检查线条是否被选中
function isLineSelected(type: 'h' | 'v', index: number): boolean {
  const selected = editorStore.selectedLine
  return selected !== null && selected.type === type && selected.index === index
}

// 获取线条颜色
function getLineColor(type: 'h' | 'v', index: number): string {
  const isSelected = isLineSelected(type, index)
  const isModified = type === 'h' 
    ? editorStore.structure.modified_h_lines.includes(index)
    : editorStore.structure.modified_v_lines.includes(index)
  
  if (isSelected) return '#f56c6c'  // 选中：红色
  if (isModified) return '#e6a23c'  // 修改过：橙色
  return '#409eff'  // 普通：蓝色
}

// 获取鼠标在画布上的位置
function getPointerPosition(): { x: number; y: number } | null {
  const stage = stageRef.value?.getNode()
  if (!stage) return null
  
  const pos = stage.getPointerPosition()
  if (!pos) return null
  
  // 考虑缩放和偏移
  return {
    x: (pos.x - editorStore.stagePos.x) / editorStore.zoom,
    y: (pos.y - editorStore.stagePos.y) / editorStore.zoom
  }
}

// 画布鼠标事件处理
function handleStageMouseDown(e: KonvaEventObject<MouseEvent>) {
  // 如果是定义边界框模式
  if (editorStore.isDefiningBbox) {
    const pos = getPointerPosition()
    if (pos) {
      isDrawingBbox.value = true
      bboxStart.value = pos
      bboxEnd.value = pos
    }
    return
  }
  
  // 如果点击的是画布背景，取消选中
  if (e.target === e.target.getStage()) {
    editorStore.clearSelection()
  }
}

function handleStageMouseMove() {
  if (editorStore.isDefiningBbox && isDrawingBbox.value) {
    const pos = getPointerPosition()
    if (pos) {
      bboxEnd.value = pos
    }
  }
}

function handleStageMouseUp() {
  if (editorStore.isDefiningBbox && isDrawingBbox.value && bboxStart.value && bboxEnd.value) {
    // 计算边界框（确保 x1 < x2, y1 < y2）
    const x1 = Math.min(bboxStart.value.x, bboxEnd.value.x)
    const y1 = Math.min(bboxStart.value.y, bboxEnd.value.y)
    const x2 = Math.max(bboxStart.value.x, bboxEnd.value.x)
    const y2 = Math.max(bboxStart.value.y, bboxEnd.value.y)
    
    // 检查边界框是否有效（至少有一定大小）
    if (x2 - x1 > 10 && y2 - y1 > 10) {
      // 转换为原图坐标
      const originalBbox = [
        displayToOriginal(x1),
        displayToOriginal(y1),
        displayToOriginal(x2),
        displayToOriginal(y2)
      ]
      editorStore.updateTableBbox(originalBbox)
      viewMode.value = 'table'
      nextTick(() => applyViewMode())
    }
    
    // 结束绘制
    isDrawingBbox.value = false
    bboxStart.value = null
    bboxEnd.value = null
  }
}

// 切换定义边界框模式
function toggleDefineBbox() {
  editorStore.setDefiningBbox(!editorStore.isDefiningBbox)
  if (!editorStore.isDefiningBbox) {
    isDrawingBbox.value = false
    bboxStart.value = null
    bboxEnd.value = null
  }
}

// 缩放按钮
function zoomIn() {
  viewMode.value = 'free'
  editorStore.setZoom(editorStore.zoom + 0.1)
}

function zoomOut() {
  viewMode.value = 'free'
  editorStore.setZoom(editorStore.zoom - 0.1)
}

function resetView() {
  viewMode.value = hasTableBbox.value ? 'table' : 'image'
  applyViewMode()
}

const handleResize = () => {
  if (viewMode.value !== 'free') {
    applyViewMode()
  }
}

onMounted(() => {
  window.addEventListener('resize', handleResize)
})

onBeforeUnmount(() => {
  window.removeEventListener('resize', handleResize)
})
</script>

<style scoped>
.table-canvas {
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;
  background: #e8e8e8;
}

.canvas-toolbar {
  position: absolute;
  top: 12px;
  left: 12px;
  display: flex;
  align-items: center;
  gap: 12px;
  z-index: 10;
}

.zoom-display {
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  padding: 4px 12px;
  border-radius: 4px;
  font-size: 13px;
}

.bbox-hint {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(230, 162, 60, 0.9);
  color: #fff;
  padding: 8px 16px;
  border-radius: 4px;
  font-size: 14px;
  z-index: 10;
}
</style>
