<template>
  <div class="main_container" id="container" ref="mainContainer" @mousedown="onMouseDown" @mousemove="onMouseMove"
    @mouseup="onMouseUp" @wheel="onWheel">
    <canvas id="paperCanvas" ref="paperCanvas" :width="canvasInfo.width" :height="canvasInfo.height"></canvas>
    <div class="no_paper_url" v-if="paperImage.length == 0">
      暂无答题卡
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, watch, onMounted, onBeforeUnmount, nextTick } from 'vue';
import { throttle, debounce } from 'lodash';
import { editSamplingPoint } from '@/api/analysis';

// 定义类型接口
interface PaperImageItem {
  url: string;
  page: number;
  [key: string]: any;
}

interface DrawDataItem {
  x: number | string;
  y: number | string;
  model?: number;
  score: number | string;
  fullScore: number | string;
  name: string;
  drawLineData?: string; // JSON string
  [key: string]: any;
}

interface Position {
  x: number;
  y: number;
  page: number;
  index: number;
}

interface ImageInfo {
  index: number;
  url: string;
  height: number;
  width: number;
  page: number;
}

// Props
const props = defineProps<{
  drawData: DrawDataItem[];
  // isSetPoint: boolean;
  // usedCardType: number;
  paperImage: PaperImageItem[];
}>();

// Emits
const emit = defineEmits<{
  (e: 'EditSamplingPointSuccess'): void;
}>();

// 响应式数据
const mainContainer = ref<HTMLDivElement | null>(null);
const paperCanvas = ref<HTMLCanvasElement | null>(null);

const canvasInfo = reactive({
  width: 0,
  height: 0
});

const state = reactive({
  image: null as HTMLImageElement | null,
  isDragging: false,
  dragStart: { x: 0, y: 0 },
  zoomRate: 1, // 图片的缩放比例
  scale: 1, // 放大缩小比例
  position: { x: 0, y: 0 }, // 初始 canvas 图片位置
  paperImgInfo: {
    width: 0,
    height: 0
  },
  canvas: null as HTMLCanvasElement | null,
  paperCtx: null as CanvasRenderingContext2D | null,
  dpr: window.devicePixelRatio || 1,
  minScale: 0.3, // 最小缩放值
  maxScale: 3, // 最大缩放值
  loadedImages: [] as HTMLImageElement[], // 存储已加载的图片
  imageList: [] as ImageInfo[], // 图片存储信息
  isDrawing: false, // 用于采分点设置状态
});

let debouncedLoadImage: (() => void) | null = null;

// 监听 paperImage
watch(
  () => props.paperImage,
  () => {
    console.log("地址变化了", props.paperImage);
    canvasInfo.width = 0; // 初始重置为0
    if (debouncedLoadImage) debouncedLoadImage();
  },
  { deep: true }
);

// 监听 drawData
watch(
  () => props.drawData,
  () => {
    console.log("边框数据更新了", props.drawData);
    if (debouncedLoadImage) debouncedLoadImage();
  },
  { deep: true }
);

// 初始化防抖函数
const initDebouncedLoadImage = () => {
  debouncedLoadImage = debounce(() => {
    loadImage();
  }, 100);
};

// 生命周期
onMounted(() => {
  initDebouncedLoadImage();
  state.canvas = paperCanvas.value;
  if (state.canvas) {
    state.paperCtx = state.canvas.getContext('2d');
  }
  window.addEventListener('resize', handleResize);
});

onBeforeUnmount(() => {
  window.removeEventListener('resize', handleResize);
  if (debouncedLoadImage) {
    debouncedLoadImage.cancel();
  }
});

// 方法

// 中心化画布
const centerCanvas = () => {
  if (!mainContainer.value) return;
  const { width, height } = mainContainer.value.getBoundingClientRect();
  state.position.x = (width - canvasInfo.width) / 2;
  state.position.y = ((height - canvasInfo.height) / 3) * 1;
  if (state.canvas) {
    state.canvas.style.left = `${state.position.x}px`;
    state.canvas.style.top = `${state.position.y}px`;
  }
};

// 加载图片
const loadImage = () => {
  // 清空之前加载的图片
  state.loadedImages = [];
  state.imageList = []; // 图片长宽信息
  
  console.log("加载图片打印图片地址", props.paperImage);
  let imgList = props.paperImage;
  
  if (!imgList || imgList.length === 0) {
    return;
  }

  // 创建一个promise数组来处理所有图片的加载
  const imagePromises = imgList.map((imgItem, index) => {
    return new Promise<HTMLImageElement>((resolve, reject) => {
      const img = new Image();
      img.src = imgItem.url;
      img.onload = () => {
        if (index === 0) {
          canvasInfo.height = img.height;
        } else {
          canvasInfo.height += img.height;
        }
        canvasInfo.width = Math.max(canvasInfo.width, img.width);
        
        let objImg: ImageInfo = {
          index: index,
          url: imgItem.url,
          height: img.height,
          width: img.width,
          page: imgItem.page
        };
        state.imageList.push(objImg);
        
        // 保存加载的图片
        state.loadedImages[index] = img;
        console.log("打印加载的图片", state.imageList);

        state.paperImgInfo.width = img.width; // 获取宽
        state.paperImgInfo.height = img.height; // 获取高
        resolve(img);
      };
      img.onerror = () => {
        console.error("图片加载失败", imgItem.url);
        reject(new Error('Failed to load image'));
      };
    });
  });

  Promise.all(imagePromises).then(images => {
    console.log("打印图片的高度", canvasInfo.width, canvasInfo.height);
    // 图片加载完成后，绘制画布
    drawCanvas();
  }).catch(error => {
    console.error("图片加载错误", error);
  });
};

// 绘制画布 负责绘制画布和图片
const drawCanvas = () => {
  if (!state.loadedImages.length || !state.paperCtx || !state.canvas) return;
  
  if (!mainContainer.value) return;
  const { width, height } = mainContainer.value.getBoundingClientRect();
  
  // 设置 canvas 的宽度和高度
  const maxWidth = width - 20;
  const maxHeight = height - 20;

  // 计算宽度和高度的缩放比例
  const widthScale = maxWidth / canvasInfo.width;
  const heightScale = maxHeight / canvasInfo.height;

  // 选择较小的缩放比例以确保整个图像都能显示
  state.zoomRate = widthScale; // 以宽为准

  // 如果计算出的缩放比例小于等于0，使用默认值
  if (state.zoomRate <= 0) {
    state.zoomRate = 1;
  }
  console.log("打印图片的缩放比例", state.zoomRate);
  
  // 应用缩放比例
  state.canvas.width = canvasInfo.width * state.zoomRate * state.scale;
  state.canvas.height = canvasInfo.height * state.zoomRate * state.scale;

  console.log("打印图片的高度", canvasInfo.width, canvasInfo.height);
  console.log("打印canvas的宽高", state.canvas.width, state.canvas.height);

  // 设置 canvas 的位置
  state.position.x = (width - state.canvas.width) / 2;
  state.position.y = ((height - canvasInfo.height) / 3) * 1;
  if (state.position.y < 0) {
    state.position.y = 0;
  }
  console.log("打印图片的坐标位置", state.position);
  
  state.canvas.style.left = `${state.position.x}px`;
  state.canvas.style.top = `${state.position.y}px`;
  
  let y = 0; // 初始化 y 坐标为 0
  // 绘制所有图片
  state.loadedImages.forEach((img) => {
    const startY = y * state.zoomRate * state.scale;
    state.paperCtx?.drawImage(
      img,
      0, 0,
      img.width, img.height,
      0, startY,
      img.width * state.zoomRate * state.scale, img.height * state.zoomRate * state.scale
    );
    y += img.height;
  });
  
  setTimeout(() => {
    redrawCanvas();
  }, 100);
};

// 加载画布图片 边框
const redrawCanvas = () => {
  if (!state.paperCtx) return;

  state.paperCtx.strokeStyle = 'red';
  state.paperCtx.lineWidth = 2;

  for (let i = 0; i < props.drawData.length; i++) {
    let item = props.drawData[i];
    console.log("打印边框数据", item);
    
    // 确保数值类型正确
    const itemX = typeof item.x === 'string' ? parseFloat(item.x) : item.x;
    const itemY = typeof item.y === 'string' ? parseFloat(item.y) : item.y;
    
    let point = {
      x: (itemX - 20) * state.zoomRate * state.scale,
      y: (itemY - 20) * state.zoomRate * state.scale,
      w: 80 * state.zoomRate * state.scale,
      h: 80 * state.zoomRate * state.scale,
    };
    
    state.paperCtx.strokeStyle = 'red';
    state.paperCtx.lineWidth = 2;
    
    // 绘制优秀答案 //0:普通   1：优秀答案   2：典型错误
    const modelImage = new Image();
    if (item.model == 1) {
      // 注意：在 Vite/Webpack 中，require 可能需要替换为 import 或 new URL()
      // 这里假设构建工具能处理 require，或者你需要预先导入这些图片
      modelImage.src = require('../assets/tool/model_1.png');
    }
    if (item.model == 2) {
      modelImage.src = require('../assets/tool/model_2.png');
    }
    
    if (item.model === 1 || item.model === 2) {
      modelImage.onload = () => {
        if (state.paperCtx) {
          state.paperCtx.drawImage(modelImage, 0, 0, 50 * state.zoomRate * state.scale, 50 * state.zoomRate * state.scale);
        }
      };
    }

    // 加载小图标
    const iconImage = new Image();
    const scoreNum = typeof item.score === 'string' ? parseFloat(item.score) : item.score;
    const fullScoreNum = typeof item.fullScore === 'string' ? parseFloat(item.fullScore) : item.fullScore;

    if (scoreNum == fullScoreNum) {
      // 等于满分
      iconImage.src = require('../assets/icon/icon_all_right.png');
    } else if (scoreNum == 0) {
      // 全错
      iconImage.src = require('../assets/icon/icon_all_wrong.png');
    } else {
      // 半对
      iconImage.src = require('../assets/icon/icon_half_right.png');
    }

    iconImage.onload = () => {
      if (state.paperCtx) {
        state.paperCtx.drawImage(iconImage, point.x, point.y, point.w, point.h);
      }
    };

    // 根据缩放比例动态调整字体大小
    const baseFontSize = 14; // 基础字体大小
    const scoreFontSize = 24; // 分数字体大小
    const scaledBaseFontSize = Math.max(12, baseFontSize * state.zoomRate * state.scale); // 最小12px
    const scaledScoreFontSize = Math.max(16, scoreFontSize * state.zoomRate * state.scale); // 最小16px

    // 绘制题目名称
    state.paperCtx.font = `${scaledBaseFontSize}px Arial`;
    state.paperCtx.fillStyle = 'blue';
    state.paperCtx.textAlign = 'center';
    state.paperCtx.textBaseline = 'middle';
    state.paperCtx.fillText(item.name, point.x + 10, point.y);

    // 绘制分数
    state.paperCtx.font = `${scaledScoreFontSize}px Arial`;
    state.paperCtx.fillStyle = '#D81E06';
    state.paperCtx.textAlign = 'center';
    state.paperCtx.textBaseline = 'middle';
    state.paperCtx.fillText(String(item.score), point.x + 75 * state.zoomRate * state.scale, point.y + 40 * state.zoomRate * state.scale);

    // 绘制标注信息
    if (item.drawLineData) {
      // 有标注信息 加载标注
      console.log("打印point", point);
      try {
        const drawLineData = JSON.parse(item.drawLineData);
        console.log("打印drawLineData", drawLineData);

        for (var j = 0; j < drawLineData.length; j++) {
          var drawItem = drawLineData[j];
          console.log("打印drawItem", drawItem);
          
          // 扣分点 加分点 标记// 1：文字 (扣分留痕 显示扣分信息)  2：划线  3：波浪线   4:画笔 5:评语
          if (drawItem.drawType == 1) {
            const fontSize = Math.max(12, 40 * state.zoomRate * state.scale); // 最小字体12px，基础字体16px
            state.paperCtx.font = `${fontSize}px Arial`; // 让文字大小跟随缩放
            state.paperCtx.fillStyle = '#D81E06';
            state.paperCtx.textAlign = 'center';
            state.paperCtx.textBaseline = 'middle';
            if (drawItem.type == 'reduce') {
              state.paperCtx.fillText('-' + drawItem.score, (drawItem.x) * state.zoomRate * state.scale, (drawItem.y) * state.zoomRate * state.scale);
            }
            if (drawItem.type == 'bonus') {
              state.paperCtx.fillText('+' + drawItem.score, (drawItem.x) * state.zoomRate * state.scale, (drawItem.y) * state.zoomRate * state.scale);
            }
          } else if (drawItem.drawType == 2) {
            // 绘制横线
            DrawHorizontalLine((drawItem.x) * state.zoomRate * state.scale, (drawItem.y) * state.zoomRate * state.scale, (drawItem.endX) * state.zoomRate * state.scale, (drawItem.endY) * state.zoomRate * state.scale);
          } else if (drawItem.drawType == 3) {
            // 绘制波浪线
            let startX = parseFloat(((drawItem.x) * state.zoomRate * state.scale).toFixed(2));
            let startY = parseFloat(((drawItem.y) * state.zoomRate * state.scale).toFixed(2));
            let endX = parseFloat(((drawItem.endX) * state.zoomRate * state.scale).toFixed(2));
            let endY = parseFloat(((drawItem.endY) * state.zoomRate * state.scale).toFixed(2));
            DrawWaveLine(startX, startY, endX, endY);
          } else if (drawItem.drawType == 4) {
            // 绘制画笔数据
            DrawPenLine(drawItem);
          } else if (drawItem.drawType == 5) {
            // 绘制评语
            let startX = parseFloat(((drawItem.x) * state.zoomRate * state.scale).toFixed(2));
            let startY = parseFloat(((drawItem.y) * state.zoomRate * state.scale).toFixed(2));
            DrawText(startX, startY, drawItem.text);
          }
        }
      } catch (e) {
        console.error("解析 drawLineData 失败", e);
      }
    }
  }
};

// 转成整数
const GetInteger = (value: any): number => {
  // 如果值为空、undefined 或 null，返回 0
  if (value === null || value === undefined || value === '') {
    return 0;
  }
  // 如果已经是数字，直接处理
  if (typeof value === 'number') {
    // 检查是否为 NaN
    if (isNaN(value)) {
      return 0;
    }
    // 使用 Math.round 四舍五入取整
    return Math.round(value);
  }
  // 如果是字符串，先尝试转换为数字
  if (typeof value === 'string') {
    // 去除首尾空格
    value = value.trim();
    // 如果是空字符串，返回 0
    if (value === '') {
      return 0;
    }
    // 转换为数字
    const num = Number(value);
    // 检查是否为有效数字
    if (isNaN(num)) {
      return 0;
    }
    // 四舍五入取整
    return Math.round(num);
  }
  // 其他情况，尝试转换为数字后取整
  const num = Number(value);
  return isNaN(num) ? 0 : Math.round(num);
};

// 画横线
const DrawHorizontalLine = (x1: number, y1: number, x2: number, y2: number) => {
  if (!state.paperCtx) return;
  console.log("画横线起始坐标点", x1, y1, x2, y2);
  state.paperCtx.strokeStyle = 'red'; // 设置红色
  state.paperCtx.lineWidth = 4; // 线条宽度
  state.paperCtx.beginPath();
  state.paperCtx.moveTo(x1, y1);
  state.paperCtx.lineTo(x2, y2);
  state.paperCtx.stroke();
};

// 画波浪线
const DrawWaveLine = (startX: number, startY: number, endX: number, endY: number) => {
  if (!state.paperCtx) return;
  const amplitude = 2; // 波浪的宽度
  const frequency = 0.8; // 振幅 越大越密集
  // 计算中间点
  const dx = endX - startX;
  const dy = endY - startY;

  state.paperCtx.strokeStyle = 'red'; // 设置红色
  state.paperCtx.lineWidth = 4; // 线条宽度
  state.paperCtx.beginPath();
  state.paperCtx.moveTo(startX, startY); // 绘制第一个点
  
  // 绘制波浪线
  if (dx !== 0) {
      for (let x = startX; x <= endX; x += 1) {
        const y = startY + dy * (x - startX) / dx + amplitude * Math.sin(frequency * (x - startX));
        state.paperCtx.lineTo(x, y);
      }
  } else {
      // 垂直线处理
      state.paperCtx.lineTo(endX, endY);
  }
  
  state.paperCtx.stroke();
};

// 绘制画笔数据
const DrawPenLine = (data: any) => {
  if (!state.paperCtx) return;
  let linelist = data.drawlineData;
  if (linelist && linelist.length > 0) {
    state.paperCtx.strokeStyle = 'red'; // 设置红色
    state.paperCtx.lineWidth = 4; // 线条宽度
    // 开始绘制
    state.paperCtx.beginPath();
    // 绘制路径
    for (let i = 0; i < linelist.length; i++) {
      let x = parseFloat(((linelist[i].x) * state.zoomRate * state.scale).toFixed(2));
      let y = parseFloat(((linelist[i].y) * state.zoomRate * state.scale).toFixed(2));
      state.paperCtx.lineTo(x, y);
    }
    state.paperCtx.stroke();
    state.paperCtx.closePath();
  }
};

// 绘制文字
const DrawText = (startX: number, startY: number, text: string) => {
  if (!state.paperCtx) return;
  // 设置字体样式
  state.paperCtx.font = '16px Arial';
  state.paperCtx.fillStyle = 'red';
  state.paperCtx.textAlign = 'left';
  // 绘制文字
  state.paperCtx.fillText(text, startX, startY);
};

// 设置鼠标复位
const mouseReset = () => {
  if (!state.canvas) return;
  state.canvas.onmouseup = null;
  state.canvas.onmousedown = null;
  state.canvas.onmousemove = null;
  state.canvas.onmousemove = () => {
    if (state.canvas) state.canvas.style.cursor = 'pointer';
  }; // 鼠标改为手
};

// 设置采分点
const SetSamplingPoint = (item: any) => {
  console.log("设置采分点", item);
  console.log("打印paperImage", props.paperImage);
  console.log("打印this.imageList", state.imageList);
  
  if (!state.canvas) return;

  state.canvas.onmousedown = null; // 清空鼠标按下事件
  state.isDrawing = false;
  
  state.canvas.onmousedown = (e: MouseEvent) => {
    console.log("鼠标按下了", e);
    console.log("设置采分点", item);
    console.log("打印this.scale", state.scale);
    console.log("缩放的比例", state.zoomRate);

    if (e.button === 0) {
      console.log("e.offsetX", e.offsetX);
      console.log("e.offsetY", e.offsetY);
      const offsetX = Math.round(e.offsetX / state.scale / state.zoomRate);
      const offsetY = Math.round(e.offsetY / state.scale / state.zoomRate);
      
      let position: Position = {
        x: offsetX,
        y: offsetY,
        page: props.paperImage[0]?.page || 0,
        index: 0, // 默认第一个图片的位置
      }; // 默认的位置
      console.log("打印位置", position);

      // 这里需要判断高度是在哪个页块区
      let imgHeight = 0;
      let page = state.imageList[0]?.page || 0; // 默认第一个
      
      for (let i = 0; i < state.imageList.length; i++) {
        // 累加当前图片之前的总高度
        const previousHeight = imgHeight;
        imgHeight += state.imageList[i].height; // 这里不需要计算缩放 因为offsetX已经是处理过缩放后的数据了
        console.log("打印当前累计的高度", imgHeight);
        console.log("打印previousHeight高度", previousHeight);
        
        // 判断点击位置是否在当前图片区域内
        if (offsetY >= previousHeight && offsetY < imgHeight) {
          page = state.imageList[i].page;
          // 计算相对于当前图片的Y坐标
          const relativeY = Math.round(offsetY - previousHeight);
          // X坐标保持不变（如果需要相对X坐标也可以计算）因为图片是竖向累加的 所以图片x坐标保持不变
          const relativeX = Math.round(offsetX);
          position = {
            x: relativeX,
            y: relativeY,
            page: page,
            index: i,
          };
          break;
        }
      }
      position.page = page;
      console.log("打印当前采分点所在的页码", page);
      console.log("打印计算后相对坐标的位置", position);
      console.log("打印缩放值", state.scale);
      
      if (state.paperCtx) {
          state.paperCtx.strokeStyle = 'red';
          state.paperCtx.lineWidth = 1;
      }

      console.log("打印item", item);
      if (item == undefined) {
        mouseReset();
      } else {
        let params = {
          id: item.id, // id
          examSubjectId: item.examSubjectId, // 试卷科目id
          answerPaintingId: item.answerPaintingId, //
          name: item.name, // 采分点名称
          position: JSON.stringify(position), // 采分点坐标
        };
        editSamplingPoint(params).then(res => {
          if (res.code === 200) {
            console.log("获取编辑采分点位置", res);
            emit('EditSamplingPointSuccess');
            // 成功后可以选择是否重置鼠标状态，根据业务需求
            // mouseReset(); 
          }
        });
      }
    }
  };
  
  state.canvas.onmousemove = () => {
    if (state.canvas) state.canvas.style.cursor = 'crosshair';
  };
};

// 适合屏幕
const fitScreen = () => {
  console.log("调用适合屏幕方法了");
  state.scale = 1;
  loadImage();
};

// 鼠标按下事件
const onMouseDown = (event: MouseEvent) => {
  // 如果正在设置采分点，可能不希望触发拖拽，或者需要更复杂的逻辑判断
  // 这里保留原逻辑，假设拖拽优先级高，或者由外部控制
  state.isDragging = true;
  state.dragStart.x = event.clientX - state.position.x;
  state.dragStart.y = event.clientY - state.position.y;
};

// 鼠标移动事件
const onMouseMove = (event: MouseEvent) => {
  if (state.isDragging) {
    state.position.x = event.clientX - state.dragStart.x;
    state.position.y = event.clientY - state.dragStart.y;
    if (state.canvas) {
      state.canvas.style.left = `${state.position.x}px`;
      state.canvas.style.top = `${state.position.y}px`;
    }
  }
};

// 鼠标抬起事件
const onMouseUp = () => {
  state.isDragging = false;
};

// 鼠标滚轮事件  放大或者缩小
const onWheel = (event: WheelEvent) => {
  event.preventDefault();
  const delta = event.deltaY < 0 ? 1 : -1;
  const newScale = state.scale + delta * 0.1;
  state.scale = Math.max(state.minScale, Math.min(state.maxScale, newScale));
  console.log("打印缩放值", state.scale);
  console.log("打印定位", state.position);

  // 只缩放画布，不重新加载图片
  // this.scaleCanvas();
  loadImage(); // 原代码是重新加载，如果性能允许可以保留，否则建议优化为只重绘
};

// 处理窗口大小变化
const handleResize = throttle(() => {
  // 可以在这里添加重新计算布局的逻辑
  // 例如: loadImage(); 或者 drawCanvas();
}, 500);

// 暴露方法给父组件
defineExpose({
  fitScreen,
  SetSamplingPoint,
  mouseReset
});

</script>

<style lang="scss" scoped>
#paperCanvas {
  position: absolute;
  cursor: pointer;
  // border:1px solid red;
}

.main_container {
  // position: relative;
  // width: 100%;
  // height: 100%;
  overflow: hidden;
  display: flex;
}

.no_paper_url {
  margin: auto;
  color: #666;
}
</style>