<template>
  <el-dialog
    v-model="visible"
    title="图片裁剪"
    width="90%"
    :close-on-click-modal="false"
    custom-class="image-crop-dialog"
    @close="handleClose"
  >
    <div class="image-editor-container">
      <!-- 主编辑区域 -->
      <div class="editor-main">
        <!-- 图片预览区域 -->
        <div class="image-preview-area">
          <div class="preview-container" style="position: relative; display: inline-block;">
            <img
              ref="cropImageRef"
              :src="imageUrl"
              class="crop-image"
              @load="onImageLoad"
              @error="onImageError"
              style="max-width: 100%; max-height: 500px; display: block;"
            />
            <!-- 裁剪框 -->
            <div
              v-if="showCropBox"
              class="crop-box"
              :style="{
                left: cropForm.x + 'px',
                top: cropForm.y + 'px',
                width: cropForm.width + 'px',
                height: cropForm.height + 'px'
              }"
              @mousedown="startDrag"
            >
              <!-- 裁剪句柄 -->
              <div class="crop-handle crop-handle-nw" @mousedown="startResize('nw', $event)"></div>
              <div class="crop-handle crop-handle-ne" @mousedown="startResize('ne', $event)"></div>
              <div class="crop-handle crop-handle-sw" @mousedown="startResize('sw', $event)"></div>
              <div class="crop-handle crop-handle-se" @mousedown="startResize('se', $event)"></div>
            </div>
          </div>
        </div>

        <!-- 工具栏 -->
        <div class="editor-toolbar">
          <el-button-group>
            <el-button @click="resetCrop">
              <el-icon><Refresh /></el-icon>
              重置
            </el-button>
            <el-button @click="rotateLeft">
              <el-icon><RefreshLeft /></el-icon>
              左转
            </el-button>
            <el-button @click="rotateRight">
              <el-icon><RefreshRight /></el-icon>
              右转
            </el-button>
          </el-button-group>
        </div>
      </div>

      <!-- 右侧设置面板 -->
      <div class="editor-sidebar">
        <div class="size-panel">
          <h4>裁剪设置</h4>
          
          <!-- 预设尺寸 -->
          <div class="preset-sizes">
            <h5>预设尺寸</h5>
            <div class="preset-buttons">
              <el-button size="small" @click="applyPresetSize(300, 300)">正方形</el-button>
              <el-button size="small" @click="applyPresetSize(400, 300)">横版</el-button>
              <el-button size="small" @click="applyPresetSize(300, 400)">竖版</el-button>
              <el-button size="small" @click="applyPresetSize(800, 400)">轮播图</el-button>
              <el-button size="small" @click="applyPresetSize(200, 200)">头像</el-button>
            </div>
          </div>

          <!-- 自定义尺寸 -->
          <div class="custom-size">
            <h5>自定义尺寸</h5>
            <el-form :model="cropSizeForm" label-width="60px" size="small">
              <el-form-item label="宽度">
                <el-input-number
                  v-model="cropSizeForm.width"
                  :min="50"
                  :max="2000"
                  @change="applyCropSize"
                />
                <span class="unit">px</span>
              </el-form-item>
              <el-form-item label="高度">
                <el-input-number
                  v-model="cropSizeForm.height"
                  :min="50"
                  :max="2000"
                  @change="applyCropSize"
                />
                <span class="unit">px</span>
              </el-form-item>
              <el-form-item>
                <el-checkbox v-model="cropSizeForm.maintainAspectRatio">
                  保持宽高比
                </el-checkbox>
              </el-form-item>
            </el-form>
          </div>

          <!-- 裁剪信息 -->
          <div class="crop-settings">
            <h5>裁剪信息</h5>
            <el-form :model="cropForm" label-width="60px" size="small">
              <el-form-item label="X">
                <el-input-number v-model="cropForm.x" :min="0" @change="updateCropBox" />
              </el-form-item>
              <el-form-item label="Y">
                <el-input-number v-model="cropForm.y" :min="0" @change="updateCropBox" />
              </el-form-item>
              <el-form-item label="宽">
                <el-input-number v-model="cropForm.width" :min="1" @change="updateCropBox" />
              </el-form-item>
              <el-form-item label="高">
                <el-input-number v-model="cropForm.height" :min="1" @change="updateCropBox" />
              </el-form-item>
            </el-form>
          </div>

          <!-- 原始图片信息 -->
          <div class="image-info-panel">
            <h5>原始图片</h5>
            <div class="info-item">
              <span class="label">尺寸:</span>
              <span class="value">{{ originalSize.width }} × {{ originalSize.height }}</span>
            </div>
            <div class="info-item" v-if="file">
              <span class="label">文件名:</span>
              <span class="value">{{ file.name }}</span>
            </div>
            <div class="info-item" v-if="file">
              <span class="label">文件大小:</span>
              <span class="value">{{ formatFileSize(file.size) }}</span>
            </div>
          </div>
        </div>
      </div>
    </div>

    <template #footer>
      <div class="dialog-footer">
        <el-button @click="handleCancel">取消</el-button>
        <el-button type="primary" @click="handleConfirm" :loading="loading">
          <el-icon><Check /></el-icon>
          确认裁剪
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue';
import { ElMessage } from 'element-plus';
import { Check, Refresh, RefreshLeft, RefreshRight } from '@element-plus/icons-vue';

// Props
interface Props {
  modelValue: boolean;
  file?: File | null;
  imageUrl?: string;
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: false,
  file: null,
  imageUrl: ''
});

// Emits
interface Emits {
  (e: 'update:modelValue', value: boolean): void;
  (e: 'confirm', croppedFile: File): void;
  (e: 'cancel'): void;
}

const emit = defineEmits<Emits>();

// 响应式数据
const loading = ref(false);
const cropImageRef = ref();
const originalSize = ref({ width: 0, height: 0 });
const showCropBox = ref(false);
const isDragging = ref(false);
const isResizing = ref(false);
const resizeDirection = ref('');

// 尺寸表单
const cropSizeForm = ref({
  width: 300,
  height: 300,
  maintainAspectRatio: true
});

// 剪切表单
const cropForm = ref({
  x: 0,
  y: 0,
  width: 0,
  height: 0
});

// 计算属性
const visible = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
});

// 格式化文件大小
const formatFileSize = (size: number) => {
  if (!size) return '0 B';
  const units = ['B', 'KB', 'MB', 'GB'];
  let index = 0;
  let fileSize = size;
  while (fileSize >= 1024 && index < units.length - 1) {
    fileSize /= 1024;
    index++;
  }
  return fileSize.toFixed(2) + ' ' + units[index];
};

// 图片加载完成
const onImageLoad = () => {
  const img = cropImageRef.value;
  if (img) {
    originalSize.value = {
      width: img.naturalWidth,
      height: img.naturalHeight
    };
    
    // 初始化裁剪框
    const containerWidth = img.clientWidth;
    const containerHeight = img.clientHeight;
    const initialSize = Math.min(containerWidth, containerHeight) * 0.6;
    
    cropForm.value = {
      x: (containerWidth - initialSize) / 2,
      y: (containerHeight - initialSize) / 2,
      width: initialSize,
      height: initialSize
    };
    
    showCropBox.value = true;
    console.log('图片加载完成，原始尺寸:', originalSize.value, '裁剪框:', cropForm.value);
  }
};

// 图片加载错误
const onImageError = () => {
  ElMessage.error('图片加载失败');
};

// 应用预设尺寸
const applyPresetSize = (width: number, height: number) => {
  cropSizeForm.value.width = width;
  cropSizeForm.value.height = height;
  applyCropSize();
};

// 应用裁剪尺寸
const applyCropSize = () => {
  if (!showCropBox.value) return;
  
  const img = cropImageRef.value;
  if (!img) return;
  
  const scaleX = img.clientWidth / originalSize.value.width;
  const scaleY = img.clientHeight / originalSize.value.height;
  
  const newWidth = cropSizeForm.value.width * scaleX;
  const newHeight = cropSizeForm.value.height * scaleY;
  
  // 确保裁剪框不超出图片边界
  const maxX = img.clientWidth - newWidth;
  const maxY = img.clientHeight - newHeight;
  
  cropForm.value.width = Math.min(newWidth, img.clientWidth);
  cropForm.value.height = Math.min(newHeight, img.clientHeight);
  cropForm.value.x = Math.max(0, Math.min(cropForm.value.x, maxX));
  cropForm.value.y = Math.max(0, Math.min(cropForm.value.y, maxY));
};

// 更新裁剪框
const updateCropBox = () => {
  // 裁剪框位置和尺寸已通过v-model绑定，这里可以添加额外的验证逻辑
};

// 开始拖拽
const startDrag = (e: MouseEvent) => {
  e.preventDefault();
  isDragging.value = true;
  
  const startX = e.clientX - cropForm.value.x;
  const startY = e.clientY - cropForm.value.y;
  
  const onMouseMove = (e: MouseEvent) => {
    if (!isDragging.value) return;
    
    const img = cropImageRef.value;
    if (!img) return;
    
    const newX = e.clientX - startX;
    const newY = e.clientY - startY;
    
    // 限制在图片范围内
    const maxX = img.clientWidth - cropForm.value.width;
    const maxY = img.clientHeight - cropForm.value.height;
    
    cropForm.value.x = Math.max(0, Math.min(newX, maxX));
    cropForm.value.y = Math.max(0, Math.min(newY, maxY));
  };
  
  const onMouseUp = () => {
    isDragging.value = false;
    document.removeEventListener('mousemove', onMouseMove);
    document.removeEventListener('mouseup', onMouseUp);
  };
  
  document.addEventListener('mousemove', onMouseMove);
  document.addEventListener('mouseup', onMouseUp);
};

// 开始调整大小
const startResize = (direction: string, e: MouseEvent) => {
  e.preventDefault();
  e.stopPropagation();
  
  isResizing.value = true;
  resizeDirection.value = direction;
  
  const startX = e.clientX;
  const startY = e.clientY;
  const startCrop = { ...cropForm.value };
  
  const onMouseMove = (e: MouseEvent) => {
    if (!isResizing.value) return;
    
    const img = cropImageRef.value;
    if (!img) return;
    
    const deltaX = e.clientX - startX;
    const deltaY = e.clientY - startY;
    
    let newX = startCrop.x;
    let newY = startCrop.y;
    let newWidth = startCrop.width;
    let newHeight = startCrop.height;
    
    switch (direction) {
      case 'nw':
        newX = startCrop.x + deltaX;
        newY = startCrop.y + deltaY;
        newWidth = startCrop.width - deltaX;
        newHeight = startCrop.height - deltaY;
        break;
      case 'ne':
        newY = startCrop.y + deltaY;
        newWidth = startCrop.width + deltaX;
        newHeight = startCrop.height - deltaY;
        break;
      case 'sw':
        newX = startCrop.x + deltaX;
        newWidth = startCrop.width - deltaX;
        newHeight = startCrop.height + deltaY;
        break;
      case 'se':
        newWidth = startCrop.width + deltaX;
        newHeight = startCrop.height + deltaY;
        break;
    }
    
    // 保持宽高比
    if (cropSizeForm.value.maintainAspectRatio) {
      const aspectRatio = cropSizeForm.value.width / cropSizeForm.value.height;
      if (Math.abs(deltaX) > Math.abs(deltaY)) {
        newHeight = newWidth / aspectRatio;
      } else {
        newWidth = newHeight * aspectRatio;
      }
    }
    
    // 限制最小尺寸
    newWidth = Math.max(20, newWidth);
    newHeight = Math.max(20, newHeight);
    
    // 限制在图片范围内
    newX = Math.max(0, Math.min(newX, img.clientWidth - newWidth));
    newY = Math.max(0, Math.min(newY, img.clientHeight - newHeight));
    newWidth = Math.min(newWidth, img.clientWidth - newX);
    newHeight = Math.min(newHeight, img.clientHeight - newY);
    
    cropForm.value.x = newX;
    cropForm.value.y = newY;
    cropForm.value.width = newWidth;
    cropForm.value.height = newHeight;
  };
  
  const onMouseUp = () => {
    isResizing.value = false;
    resizeDirection.value = '';
    document.removeEventListener('mousemove', onMouseMove);
    document.removeEventListener('mouseup', onMouseUp);
  };
  
  document.addEventListener('mousemove', onMouseMove);
  document.addEventListener('mouseup', onMouseUp);
};

// 重置裁剪
const resetCrop = () => {
  const img = cropImageRef.value;
  if (img) {
    const containerWidth = img.clientWidth;
    const containerHeight = img.clientHeight;
    const initialSize = Math.min(containerWidth, containerHeight) * 0.6;
    
    cropForm.value = {
      x: (containerWidth - initialSize) / 2,
      y: (containerHeight - initialSize) / 2,
      width: initialSize,
      height: initialSize
    };
  }
};

// 左旋转
const rotateLeft = () => {
  ElMessage.info('旋转功能开发中...');
};

// 右旋转
const rotateRight = () => {
  ElMessage.info('旋转功能开发中...');
};

// 处理取消
const handleCancel = () => {
  visible.value = false;
  emit('cancel');
};

// 处理关闭
const handleClose = () => {
  showCropBox.value = false;
  emit('cancel');
};

// 处理确认
const handleConfirm = async () => {
  if (!props.file || !showCropBox.value) {
    ElMessage.error('请先选择裁剪区域');
    return;
  }
  
  try {
    loading.value = true;
    
    // 创建canvas进行裁剪
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    const img = cropImageRef.value;
    
    if (!img || !ctx) {
      throw new Error('无法创建画布或获取图片');
    }
    
    // 计算实际裁剪区域（基于原始图片尺寸）
    const scaleX = originalSize.value.width / img.clientWidth;
    const scaleY = originalSize.value.height / img.clientHeight;
    
    const cropX = cropForm.value.x * scaleX;
    const cropY = cropForm.value.y * scaleY;
    const cropWidth = cropForm.value.width * scaleX;
    const cropHeight = cropForm.value.height * scaleY;
    
    // 设置canvas尺寸
    canvas.width = cropWidth;
    canvas.height = cropHeight;
    
    // 创建新的Image对象来绘制
    const image = new Image();
    image.onload = () => {
      // 绘制裁剪后的图片
      ctx.drawImage(
        image,
        cropX, cropY, cropWidth, cropHeight,
        0, 0, cropWidth, cropHeight
      );
      
      // 转换为Blob
      canvas.toBlob((blob) => {
        if (blob) {
          // 创建新的File对象
          const croppedFile = new File(
            [blob],
            `cropped_${props.file!.name}`,
            { type: props.file!.type }
          );
          
          console.log('裁剪完成，新文件大小:', (croppedFile.size / 1024 / 1024).toFixed(2), 'MB');
          
          // 发射确认事件
          emit('confirm', croppedFile);
          visible.value = false;
        } else {
          throw new Error('裁剪失败');
        }
      }, props.file!.type, 0.9);
    };
    
    image.onerror = () => {
      throw new Error('图片加载失败');
    };
    
    image.src = props.imageUrl;
    
  } catch (error) {
    console.error('裁剪失败:', error);
    const errorMessage = error instanceof Error ? error.message : String(error);
    ElMessage.error('裁剪失败: ' + errorMessage);
  } finally {
    loading.value = false;
  }
};

// 监听文件变化，重置状态
watch(() => props.file, () => {
  showCropBox.value = false;
  cropSizeForm.value = {
    width: 300,
    height: 300,
    maintainAspectRatio: true
  };
});
</script>

<style scoped>
/* 图片裁剪对话框样式 */
.image-crop-dialog :deep(.el-dialog__body) {
  padding: 20px;
  height: 80vh;
  overflow: visible;
}

.image-editor-container {
  display: flex;
  height: 100%;
  gap: 20px;
}

.editor-main {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.image-preview-area {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f5f7fa;
  border-radius: 6px;
  margin-bottom: 15px;
}

.preview-container {
  display: flex;
  align-items: center;
  justify-content: center;
  background: white;
}

.crop-image {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.crop-box {
  position: absolute;
  border: 2px solid #409eff;
  background: rgba(64, 158, 255, 0.1);
  cursor: move;
}

.crop-handle {
  position: absolute;
  width: 8px;
  height: 8px;
  background: #409eff;
  border: 1px solid white;
  border-radius: 50%;
}

.crop-handle-nw {
  top: -4px;
  left: -4px;
  cursor: nw-resize;
}

.crop-handle-ne {
  top: -4px;
  right: -4px;
  cursor: ne-resize;
}

.crop-handle-sw {
  bottom: -4px;
  left: -4px;
  cursor: sw-resize;
}

.crop-handle-se {
  bottom: -4px;
  right: -4px;
  cursor: se-resize;
}

.editor-toolbar {
  display: flex;
  justify-content: center;
  padding: 10px 0;
}

.editor-sidebar {
  width: 300px;
  background: #fafafa;
  border-radius: 6px;
  padding: 15px;
  overflow-y: auto;
}

.size-panel h4 {
  margin: 0 0 15px 0;
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

.size-panel h5 {
  margin: 15px 0 10px 0;
  font-size: 14px;
  font-weight: 500;
  color: #606266;
}

.preset-sizes {
  margin-bottom: 20px;
}

.preset-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.custom-size {
  margin-bottom: 20px;
}

.unit {
  margin-left: 8px;
  color: #909399;
}

.crop-settings {
  margin-bottom: 20px;
  padding-top: 15px;
  border-top: 1px solid #ebeef5;
}

.image-info-panel {
  padding-top: 15px;
  border-top: 1px solid #ebeef5;
}

.info-item {
  display: flex;
  justify-content: space-between;
  margin-bottom: 8px;
  font-size: 12px;
}

.info-item .label {
  color: #909399;
}

.info-item .value {
  color: #303133;
  font-weight: 500;
}

.dialog-footer {
  text-align: right;
}
</style>
