<template>
  <div class="image-annotation-container">
    <!-- 工具栏 -->
    <div class="annotation-toolbar">
      <div style="display:none"></div>
      <div class="action-group">
        <el-button size="small" @click="undo" :disabled="!canUndo">
          <el-icon>
            <Back />
          </el-icon>
          撤销
        </el-button>
        <el-button size="small" @click="redo" :disabled="!canRedo">
          <el-icon>
            <Right />
          </el-icon>
          重做
        </el-button>
      </div>
    </div>

    <!-- 画布容器 -->
    <div class="canvas-container" ref="canvasContainer">
      <canvas ref="canvas" class="annotation-canvas" @mousedown="handleMouseDown" @mousemove="handleMouseMove"
        @mouseup="handleMouseUp" @click="handleClick" @contextmenu.prevent />
      <img ref="image" :src="imageUrl" class="source-image" @load="handleImageLoad" style="display: none;" />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, nextTick, watch } from 'vue'
import { Right, Back } from '@element-plus/icons-vue'

interface Point {
  x: number
  y: number
}

interface Annotation {
  type: 'rectangle'
  points: Point[]
  strokeColor: string
  strokeWidth: number
  fontSize?: number
  id: string
}

interface HistoryState {
  annotations: Annotation[]
  currentAnnotation?: Annotation
}

const props = defineProps<{
  imageUrl: string
}>()

const emit = defineEmits<{
  save: [annotations: Annotation[], imageFile: File]
}>()

// 响应式状态
const canvas = ref<HTMLCanvasElement>()
const image = ref<HTMLImageElement>()
const canvasContainer = ref<HTMLDivElement>()
const currentTool = ref<'rectangle'>('rectangle')
const strokeColor = ref('#ff0000')
const strokeWidth = ref(2)
const fontSize = ref(16)
const isDrawing = ref(false)
const startPoint = ref<Point>({ x: 0, y: 0 })
const currentAnnotation = ref<Annotation>()
const annotations = ref<Annotation[]>([])

const history = ref<HistoryState[]>([])
const historyStep = ref(-1)

const canUndo = computed(() => historyStep.value > 0 && history.value.length > 1)
const canRedo = computed(() => historyStep.value < history.value.length - 1)

// 保存当前状态到历史记录
const saveToHistory = () => {
  const currentState: HistoryState = {
    annotations: JSON.parse(JSON.stringify(annotations.value)),
    currentAnnotation: currentAnnotation.value ? JSON.parse(JSON.stringify(currentAnnotation.value)) : undefined
  }
  history.value = history.value.slice(0, historyStep.value + 1)
  history.value.push(currentState)
  historyStep.value++
}

// 撤销
const undo = () => {
  if (canUndo.value) {
    historyStep.value--
    const state = history.value[historyStep.value]
    annotations.value = JSON.parse(JSON.stringify(state.annotations))
    currentAnnotation.value = state.currentAnnotation ? JSON.parse(JSON.stringify(state.currentAnnotation)) : undefined
    redrawCanvas()
  }
}

// 重做
const redo = () => {
  if (canRedo.value) {
    historyStep.value++
    const state = history.value[historyStep.value]
    annotations.value = JSON.parse(JSON.stringify(state.annotations))
    currentAnnotation.value = state.currentAnnotation ? JSON.parse(JSON.stringify(state.currentAnnotation)) : undefined
    redrawCanvas()
  }
}

// 图片加载完成
const handleImageLoad = () => {
  if (!image.value || !canvas.value) return;

  // 确保图片设置了 crossOrigin
  image.value.crossOrigin = "anonymous";

  const img = image.value;
  const container = canvasContainer.value!;

  // 计算适合容器的图片尺寸
  const containerWidth = container.clientWidth;
  const containerHeight = container.clientHeight;
  const imgRatio = img.width / img.height;
  const containerRatio = containerWidth / containerHeight;

  let canvasWidth, canvasHeight;

  if (imgRatio > containerRatio) {
    canvasWidth = containerWidth;
    canvasHeight = containerWidth / imgRatio;
  } else {
    canvasHeight = containerHeight;
    canvasWidth = containerHeight * imgRatio;
  }

  canvas.value.width = canvasWidth;
  canvas.value.height = canvasHeight;

  isDrawing.value = false;
  updateCursor();
  redrawCanvas();
};

// 重绘画布
const redrawCanvas = () => {
  if (!canvas.value || !image.value) return;

  const ctx = canvas.value.getContext('2d')!;
  const img = image.value;

  // 确保图片已加载且 crossOrigin 设置正确
  if (!img.complete || img.naturalWidth === 0) {
    console.warn("Image not fully loaded or crossOrigin not set");
    return;
  }

  ctx.clearRect(0, 0, canvas.value.width, canvas.value.height);
  ctx.save();

  // 计算图片显示尺寸和位置
  const container = canvasContainer.value!;
  const containerWidth = container.clientWidth;
  const containerHeight = container.clientHeight;
  const imgRatio = img.width / img.height;
  const containerRatio = containerWidth / containerHeight;

  let displayWidth, displayHeight, imageX, imageY;

  if (imgRatio > containerRatio) {
    displayWidth = containerWidth;
    displayHeight = containerWidth / imgRatio;
    imageX = 0;
    imageY = (containerHeight - displayHeight) / 2;
  } else {
    displayHeight = containerHeight;
    displayWidth = containerHeight * imgRatio;
    imageX = (containerWidth - displayWidth) / 2;
    imageY = 0;
  }

  // 绘制图片
  ctx.drawImage(img, imageX, imageY, displayWidth, displayHeight);

  // 绘制所有标注
  annotations.value.forEach(annotation => {
    drawAnnotation(ctx, annotation, imageX, imageY);
  });

  if (currentAnnotation.value) {
    drawAnnotation(ctx, currentAnnotation.value, imageX, imageY);
  }

  ctx.restore();
};

// 只支持矩形标注
const drawAnnotation = (ctx: CanvasRenderingContext2D, annotation: Annotation, offsetX = 0, offsetY = 0) => {
  ctx.lineWidth = annotation.strokeWidth
  ctx.lineCap = 'round'
  ctx.lineJoin = 'round'
  const color = annotation.strokeColor
  if (annotation.points.length >= 2) {
    const start = annotation.points[0]
    const end = annotation.points[1]
    const width = end.x - start.x
    const height = end.y - start.y
    ctx.strokeStyle = color
    ctx.strokeRect(start.x + offsetX, start.y + offsetY, width, height)
  }
}

// 鼠标事件处理
const handleMouseDown = (e: MouseEvent) => {
  if (!canvas.value) return

  const rect = canvas.value.getBoundingClientRect()
  const x = e.clientX - rect.left
  const y = e.clientY - rect.top

  // 计算相对于图片的坐标（考虑图片居中偏移）
  const container = canvasContainer.value!
  const containerWidth = container.clientWidth
  const containerHeight = container.clientHeight
  const img = image.value!
  const imgRatio = img.width / img.height
  const containerRatio = containerWidth / containerHeight

  let displayWidth, displayHeight, imageX, imageY

  if (imgRatio > containerRatio) {
    displayWidth = containerWidth
    displayHeight = containerWidth / imgRatio
    imageX = 0
    imageY = (containerHeight - displayHeight) / 2
  } else {
    displayHeight = containerHeight
    displayWidth = containerHeight * imgRatio
    imageX = (containerWidth - displayWidth) / 2
    imageY = 0
  }

  // 转换为相对于图片的坐标
  const imageXCoord = x - imageX
  const imageYCoord = y - imageY

  isDrawing.value = true
  startPoint.value = { x: imageXCoord, y: imageYCoord }

  // 创建新标注
  currentAnnotation.value = {
    type: 'rectangle',
    points: [{ x: imageXCoord, y: imageYCoord }],
    strokeColor: strokeColor.value,
    strokeWidth: strokeWidth.value,
    fontSize: fontSize.value,
    id: Date.now().toString()
  }
}

const handleMouseMove = (e: MouseEvent) => {
  if (!canvas.value) return

  const rect = canvas.value.getBoundingClientRect()
  const x = e.clientX - rect.left
  const y = e.clientY - rect.top

  if (!isDrawing.value) return

  // 计算相对于图片的坐标（考虑图片居中偏移）
  const container = canvasContainer.value!
  const containerWidth = container.clientWidth
  const containerHeight = container.clientHeight
  const img = image.value!
  const imgRatio = img.width / img.height
  const containerRatio = containerWidth / containerHeight

  let displayWidth, displayHeight, imageX, imageY

  if (imgRatio > containerRatio) {
    displayWidth = containerWidth
    displayHeight = containerWidth / imgRatio
    imageX = 0
    imageY = (containerHeight - displayHeight) / 2
  } else {
    displayHeight = containerHeight
    displayWidth = containerHeight * imgRatio
    imageX = (containerWidth - displayWidth) / 2
    imageY = 0
  }

  // 转换为相对于图片的坐标
  const imageXCoord = x - imageX
  const imageYCoord = y - imageY

  if (!currentAnnotation.value) return

  // 更新当前标注的第二个点
  if (currentAnnotation.value.points.length > 1) {
    currentAnnotation.value.points[1] = { x: imageXCoord, y: imageYCoord }
  } else {
    currentAnnotation.value.points.push({ x: imageXCoord, y: imageYCoord })
  }

  redrawCanvas()
}

const handleMouseUp = () => {
  if (!isDrawing.value) return

  isDrawing.value = false

  if (!currentAnnotation.value) return

  // 完成当前标注
  if (currentAnnotation.value.points.length >= 2) {
    annotations.value.push(currentAnnotation.value)
    saveToHistory()
  }

  currentAnnotation.value = undefined
  redrawCanvas()
}

const handleClick = (e: MouseEvent) => {
  // 仅保留函数结构，无需实现
}

// 工具切换时更新鼠标样式
const updateCursor = () => {
  if (!canvas.value) return
  canvas.value.style.cursor = 'crosshair'
}

// 保存标注
// const saveAnnotation = () => {
//   if (!canvas.value) return
//   const imageData = canvas.value.toDataURL('image/png')

//   emit('save', annotations.value, imageData)
// }

const saveAnnotation = async () => {
  if (!canvas.value) return;

  try {
    // 确保画布内容已渲染
    await nextTick();

    // 创建临时画布并复制内容
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = canvas.value.width;
    tempCanvas.height = canvas.value.height;
    const tempCtx = tempCanvas.getContext('2d');
    if (!tempCtx) throw new Error("无法获取画布上下文");

    // 绘制原画布内容
    tempCtx.drawImage(canvas.value, 0, 0);

    // 转换为 Blob
    const blob = await new Promise<Blob | null>((resolve) => {
      tempCanvas.toBlob((blob) => {
        resolve(blob);
      }, 'image/png', 0.9); // 可调整质量（0-1）
    });

    if (!blob) throw new Error("无法生成 Blob");

    // 创建 File 对象
    const file = new File([blob], 'annotated-image.png', {
      type: 'image/png',
      lastModified: Date.now(),
    });

    // 触发保存事件
    emit('save', annotations.value, file);
  } catch (error) {
    console.error("保存失败:", error);
  }
};

// 监听工具变化更新鼠标样式
watch(currentTool, () => {
  updateCursor()
})

// 监听图片URL变化，清空画板
watch(() => props.imageUrl, (newUrl, oldUrl) => {
  if (newUrl && newUrl !== oldUrl) {
    // 清空所有标注
    annotations.value = []
    currentAnnotation.value = undefined
    // 重置历史记录
    history.value = []
    historyStep.value = -1
    // 切换到矩形标注模式
    currentTool.value = 'rectangle'
    // 重置样式选项到默认值
    strokeColor.value = '#ff0000'
    strokeWidth.value = 2
    fontSize.value = 16
    // 更新鼠标样式
    updateCursor()
    // 重新初始化
    nextTick(() => {
      handleImageLoad()
      saveToHistory()
    })
  }
}, { immediate: false })


watch(() => props.imageUrl, (newUrl) => {
  if (newUrl) {
    const img = new Image();
    img.onload = () => {
      console.log('Image loaded');
      handleImageLoad();
    };
    img.src = newUrl;
  }
}, { immediate: true });

// 初始化
onMounted(() => {
  nextTick(() => {
    handleImageLoad()
    // 初始化历史记录
    saveToHistory()
  })
})

// 暴露方法
defineExpose({
  annotations,
  saveAnnotation
})
</script>

<style scoped>
.image-annotation-container {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: #f5f5f5;
}

.annotation-toolbar {
  display: flex;
  align-items: center;
  padding: 12px 16px;
  background: white;
  border-bottom: 1px solid #e4e7ed;
  gap: 16px;
  flex-wrap: wrap;
}

.tool-group {
  display: flex;
  align-items: center;
}

.style-group {
  display: flex;
  align-items: center;
  gap: 12px;
}

.action-group {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.control-with-icon {
  display: flex;
  align-items: center;
  gap: 6px;
}

.control-icon {
  color: #666;
  font-size: 14px;
}

.canvas-container {
  flex: 1;
  position: relative;
  overflow: hidden;
  background: #f0f0f0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.annotation-canvas {
  border: 1px solid #ddd;
  cursor: crosshair;
  background: white;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.source-image {
  display: none;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .annotation-toolbar {
    flex-direction: column;
    gap: 12px;
  }

  .style-group {
    flex-wrap: wrap;
    justify-content: center;
  }
}
</style>