<template>
  <el-dialog
    title="电子签名"
    :visible.sync="visible"
    width="49%"
    :show-close="true"
    @close="handleClose"
    @opened="initCanvas"
    qappend-to-body
  >
    <el-form label-width="80px">
      <el-form-item label="签名区域">
        <div style="text-align: right">
          <el-button type="primary" @click="undo"> 撤销 </el-button>
          <el-button type="primary" @click="clear"> 清除 </el-button>
        </div>
      </el-form-item>
    </el-form>
    <div class="canvas-container">
      <canvas
        ref="signatureCanvas"
        class="signature-canvas"
        @mousedown="startDraw"
        @mousemove="drawing"
        @mouseup="stopDraw"
        @mouseleave="stopDraw"
        @touchstart.prevent="handleTouchStart"
        @touchmove.prevent="handleTouchMove"
        @touchend.prevent="stopDraw"
      ></canvas>
    </div>
    <div slot="footer">
      <el-button type="primary" @click="uploadLocalFile">
        上传本地文件
      </el-button>
      <el-button type="primary" @click="submit"> 上传 </el-button>
      <el-button @click="handleClose">取消</el-button>
    </div>
    <input
      ref="fileInput"
      type="file"
      accept="image/*"
      class="file-input"
      @change="handleFileChange"
    />
  </el-dialog>
</template>

<script>
export default {
  name: "ESignatureDialog",
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      ctx: null,
      isDrawing: false,
      lastX: 0,
      lastY: 0,
      history: [],
      signatureData: null,
      canvasInited: false,
    };
  },
  watch: {
    visible(newVal) {
      if (newVal) {
        this.$nextTick(() => {
          this.initCanvas();
        });
      } else {
        this.clearCanvas();
      }
    },
  },
  methods: {
    initCanvas() {
      const canvas = this.$refs.signatureCanvas;
      if (!canvas) return;

      // 获取 canvas 容器的实际尺寸
      const container = canvas.parentElement;
      const rect = container.getBoundingClientRect();

      // 设置 canvas 实际像素尺寸
      canvas.width = rect.width;
      canvas.height = rect.height;

      // 获取 2D 上下文
      this.ctx = canvas.getContext("2d");

      // 设置画笔样式
      this.ctx.strokeStyle = "#000000";
      this.ctx.lineWidth = 2;
      this.ctx.lineCap = "round";
      this.ctx.lineJoin = "round";

      // 清除画布
      this.ctx.clearRect(0, 0, canvas.width, canvas.height);

      // 保存初始状态
      this.history = [];
      this.saveState();

      this.canvasInited = true;
    },

    saveState() {
      const canvas = this.$refs.signatureCanvas;
      if (canvas && this.ctx) {
        this.history.push(canvas.toDataURL());
        // 限制历史记录数量
        if (this.history.length > 20) {
          this.history.shift();
        }
      }
    },

    startDraw(e) {
      if (!this.ctx) return;

      this.isDrawing = true;
      const pos = this.getPosition(e);
      this.lastX = pos.x;
      this.lastY = pos.y;

      // 开始新路径
      this.ctx.beginPath();
      this.ctx.moveTo(this.lastX, this.lastY);
    },

    drawing(e) {
      if (!this.isDrawing || !this.ctx) return;

      e.preventDefault();

      const pos = this.getPosition(e);

      this.ctx.lineTo(pos.x, pos.y);
      this.ctx.stroke();

      this.lastX = pos.x;
      this.lastY = pos.y;
    },

    stopDraw() {
      if (this.isDrawing) {
        this.isDrawing = false;
        this.saveState();
      }
    },

    getPosition(e) {
      const canvas = this.$refs.signatureCanvas;
      const rect = canvas.getBoundingClientRect();

      let clientX, clientY;

      if (e.touches && e.touches.length > 0) {
        clientX = e.touches[0].clientX;
        clientY = e.touches[0].clientY;
      } else {
        clientX = e.clientX;
        clientY = e.clientY;
      }

      return {
        x: clientX - rect.left,
        y: clientY - rect.top,
      };
    },

    handleTouchStart(e) {
      if (e.touches.length === 1) {
        this.startDraw(e);
      }
    },

    handleTouchMove(e) {
      if (e.touches.length === 1) {
        this.drawing(e);
      }
    },

    undo() {
      if (this.history.length > 1 && this.ctx) {
        this.history.pop();
        const lastState = this.history[this.history.length - 1];
        const img = new Image();
        img.onload = () => {
          const canvas = this.$refs.signatureCanvas;
          this.ctx.clearRect(0, 0, canvas.width, canvas.height);
          this.ctx.drawImage(img, 0, 0);
        };
        img.src = lastState;
      }
    },

    clear() {
      if (this.ctx) {
        const canvas = this.$refs.signatureCanvas;
        this.ctx.clearRect(0, 0, canvas.width, canvas.height);
        this.saveState();
      }
    },

    clearCanvas() {
      if (this.ctx) {
        const canvas = this.$refs.signatureCanvas;
        this.ctx.clearRect(0, 0, canvas.width, canvas.height);
      }
      this.history = [];
      this.signatureData = null;
      this.canvasInited = false;
    },

    uploadLocalFile() {
      this.$refs.fileInput.click();
    },

    handleFileChange(e) {
      const file = e.target.files[0];
      if (file && this.ctx) {
        const reader = new FileReader();
        reader.onload = (event) => {
          const img = new Image();
          img.onload = () => {
            const canvas = this.$refs.signatureCanvas;

            // 清除画布
            this.ctx.clearRect(0, 0, canvas.width, canvas.height);

            // 计算缩放比例，保持图片比例
            const scale = Math.min(
              canvas.width / img.width,
              canvas.height / img.height,
              1
            );
            const x = (canvas.width - img.width * scale) / 2;
            const y = (canvas.height - img.height * scale) / 2;

            this.ctx.drawImage(
              img,
              x,
              y,
              img.width * scale,
              img.height * scale
            );
            this.saveState();
          };
          img.src = event.target.result;
        };
        reader.readAsDataURL(file);
      }
      // 清空 input 值，允许重复选择同一文件
      e.target.value = "";
    },

    submit() {
      const canvas = this.$refs.signatureCanvas;
      if (!canvas || !this.ctx) return;

      // 检查是否有签名内容
      const imageData = this.ctx.getImageData(
        0,
        0,
        canvas.width,
        canvas.height
      );
      let hasContent = false;
      for (let i = 3; i < imageData.data.length; i += 4) {
        if (imageData.data[i] !== 0) {
          hasContent = true;
          break;
        }
      }

      if (!hasContent) {
        this.$message.warning("请先进行签名");
        return;
      }

      this.signatureData = canvas.toDataURL("image/png");
      this.$message.success("签名上传成功");
      this.$emit("submit", this.signatureData);
      this.handleClose();
    },

    handleClose() {
      this.$emit("update:visible", false);
    },
  },
};
</script>

<style lang="scss" scoped>
.canvas-container {
  width: 100%;
  height: 300px;
  border: 2px dashed #00c4b6;
  border-radius: 4px;
  overflow: hidden;
  background-color: #fff;

  .signature-canvas {
    width: 100%;
    height: 100%;
    cursor: crosshair;
    display: block;
    touch-action: none;
  }
}

.file-input {
  display: none;
}
</style>
