<template>
  <el-dialog
    v-model="visible"
    title="裁剪图片（固定尺寸：1200x800）"
    width="95%"
    top="2vh"
    append-to-body
    :close-on-click-modal="false"
    @close="handleClose"
  >
    <!-- 裁剪容器 -->
    <div class="crop-container">
      <img ref="cropImage" :src="imageUrl" alt="待裁剪图片" />
    </div>

    <!-- 弹窗底部按钮 -->
    <template #footer>
      <el-button @click="visible = false">取消</el-button>
      <el-button type="primary" @click="handleConfirmCrop">确认裁剪</el-button>
    </template>
  </el-dialog>
</template>

<script setup>
import { ref, watch, nextTick, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.min.css'

// 接收父组件传值
const props = defineProps({
  // 是否显示弹窗
  visible: {
    type: Boolean,
    default: false
  },
  // 待裁剪图片的URL（base64或远程地址）
  imageUrl: {
    type: String,
    default: ''
  },
  // 裁剪宽高比（默认1200/800=3:2）
  aspectRatio: {
    type: Number,
    default: 1200 / 800
  },
  // 最终输出的宽度
  outputWidth: {
    type: Number,
    default: 1200
  },
  // 最终输出的高度
  outputHeight: {
    type: Number,
    default: 800
  }
})

// 向父组件传值
const emit = defineEmits([
  'close', // 弹窗关闭
  'confirm', // 裁剪确认（返回blob和base64）
  'error' // 裁剪失败
])

// 裁剪相关变量
const cropImage = ref(null)
const cropperInstance = ref(null)

// 监听弹窗显示状态，初始化/销毁裁剪器
watch(
  () => props.visible,
  (newVal) => {
    if (newVal && props.imageUrl) {
      nextTick(() => {
        setTimeout(initCropper, 200) // 延迟确保DOM加载完成
      })
    } else {
      destroyCropper()
    }
  },
  { immediate: true }
)

// 初始化裁剪器
const initCropper = () => {
  // 先销毁旧实例
  destroyCropper()

  if (!cropImage.value || !props.imageUrl) return

  // 确保图片加载完成
  cropImage.value.onload = () => {
    try {
      cropperInstance.value = new Cropper(cropImage.value, {
        aspectRatio: props.aspectRatio, // 宽高比
        viewMode: 0, // 允许裁剪框超出容器，解决画面过小
        dragMode: 'move', // 拖动模式：移动图片
        autoCropArea: 0.8, // 初始裁剪区域占80%
        cropBoxResizable: false, // 禁止调整裁剪框大小
        cropBoxMovable: true, // 允许移动裁剪框
        background: false, // 关闭背景网格
        center: true, // 裁剪框居中
        zoomOnWheel: true, // 允许滚轮缩放
        autoCrop: true, // 自动裁剪
        responsive: true, // 响应式
        restore: false, // 禁止恢复
        checkOrientation: false // 关闭方向检查
      })

      // 强制放大图片，解决显示过小问题
      setTimeout(() => {
        if (cropperInstance.value) {
          try {
            const containerData = cropperInstance.value.getContainerData()
            const imageData = cropperInstance.value.getImageData()
            const scale = containerData.width / imageData.width * 0.9
            cropperInstance.value.zoomTo(scale)
          } catch (e) {
            cropperInstance.value.zoomTo(1.2) // 降级放大
          }
        }
      }, 300)
    } catch (e) {
      ElMessage.error('裁剪器初始化失败：' + e.message)
      emit('error', e)
    }
  }
}

// 销毁裁剪器
const destroyCropper = () => {
  if (cropperInstance.value) {
    cropperInstance.value.destroy()
    cropperInstance.value = null
  }
}

// 确认裁剪
const handleConfirmCrop = () => {
  if (!cropperInstance.value) {
    ElMessage.error('裁剪器未初始化，请重试')
    return
  }

  try {
    // 获取裁剪后的canvas
    const canvas = cropperInstance.value.getCroppedCanvas({
      width: props.outputWidth,
      height: props.outputHeight,
      imageSmoothingQuality: 'high' // 高清裁剪
    })

    // 转为blob（用于上传）和base64（用于预览）
    canvas.toBlob((blob) => {
      if (blob) {
        const base64 = canvas.toDataURL('image/png', 0.9)
        emit('confirm', { blob, base64 }) // 向父组件返回结果
        visible.value = false // 关闭弹窗
      } else {
        ElMessage.error('图片裁剪失败')
        emit('error', new Error('canvas转blob失败'))
      }
    }, 'image/png', 0.9)
  } catch (e) {
    ElMessage.error('裁剪失败：' + e.message)
    emit('error', e)
  }
}

// 弹窗关闭时的处理
const handleClose = () => {
  destroyCropper()
  emit('close')
}

// 组件卸载时销毁裁剪器
onUnmounted(() => {
  destroyCropper()
})
</script>

<style scoped lang="scss">
.crop-container {
  width: 100%;
  height: 700px; // 足够大的裁剪区域
  overflow: hidden;
  margin: 0 auto;

  img {
    display: block;
    max-width: none !important;
    max-height: none !important;
  }
}

// 裁剪器样式穿透
:deep(.cropper-container) {
  width: 100% !important;
  height: 100% !important;
}

:deep(.cropper-crop-box) {
  border: 2px solid #409eff;
}

:deep(.cropper-view-box) {
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.5);
}

:deep(.el-dialog__body) {
  padding: 20px !important;
  height: 750px;
  overflow: hidden;
}
</style>