<template>
  <el-dialog
    v-model="visible"
    title="图片区域选择"
    fullscreen
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    append-to-body
    class="select-img-area-dialog"
    @open="handleOpen"
    @close="handleClose"
  >
    <div class="select-img-area-container">
      <!-- 左侧图片展示区域 -->
      <div class="left-panel">
        <div class="image-head">
          <!-- 图片菜单 -->
          <div class="image-menu">
            <el-button
              v-for="(img, index) in imgList"
              :key="index"
              :type="currentImageIndex === index ? 'primary' : 'default'"
              @click="switchImage(index)"
            >
              {{ index + 1 }}
            </el-button>
          </div>
          <div>
            <el-button @click="onSelectFullArea">选择整图</el-button>
          </div>
        </div>

        <!-- 图片展示区域 -->
        <div class="image-container">
          <Cropper :src="currentImage" @crop="handleCrop" />
        </div>
      </div>

      <!-- 右侧预览区域 -->
      <div class="right-panel">
        <div class="preview-title">框选区域预览</div>

        <!-- 预览区域 -->
        <div class="preview-container">
          <div
            v-for="(area, index) in coverAreas"
            :key="index"
            class="preview-item"
          >
            <div class="preview-image-wrapper">
              <img :src="area.splitUrl" :alt="index" />
              <el-button
                type="danger"
                size="small"
                circle
                class="delete-btn"
                @click="deleteCoverArea(index)"
              >
                <el-icon><Delete /></el-icon>
              </el-button>
            </div>
            <!-- <div class="area-info">
              区域 {{ area.i + 1 }}: ({{ area.x }}, {{ area.y }})
              {{ area.w }}×{{ area.h }}
            </div> -->
          </div>
        </div>

        <!-- 底部按钮 -->
        <div class="bottom-buttons">
          <el-button type="danger" @click="clearAll">清除</el-button>
          <el-button type="primary" @click="save">保存</el-button>
          <el-button @click="close">退出</el-button>
        </div>
      </div>
    </div>
  </el-dialog>
</template>

<script setup lang="ts">
  import { ref, computed } from 'vue';
  import { Delete } from '@element-plus/icons-vue';
  import { ElMessage } from 'element-plus';
  import type { CoverArea } from '@/api/types/common';
  import Cropper from './Cropper.vue';

  defineOptions({
    name: 'SelectImgArea',
  });

  const props = withDefaults(
    defineProps<{
      imgList: string[];
      modelValue: CoverArea[];
    }>(),
    {
      imgList: () => [],
      modelValue: () => [],
    }
  );

  interface CoverAreaItem extends CoverArea {
    splitUrl: string;
  }

  const emit = defineEmits(['update:modelValue', 'change', 'close']);

  // 弹窗控制
  const visible = ref(false);

  // 图片相关
  const currentImageIndex = ref(0);
  const coverAreas = ref<CoverAreaItem[]>([]);

  // 计算当前图片
  const currentImage = computed(() => {
    return props.imgList[currentImageIndex.value] || '';
  });

  // 处理裁剪事件
  async function handleCrop(data: {
    x: number;
    y: number;
    width: number;
    height: number;
  }) {
    const { x, y, width, height } = data;
    const newArea: CoverAreaItem = {
      i: currentImageIndex.value,
      x,
      y,
      w: width,
      h: height,
      splitUrl: '',
    };
    newArea.splitUrl = await generatePreview(newArea);

    // 添加新的框选区域
    coverAreas.value.push(newArea);
  }

  // 生成预览图
  async function generatePreview(area: CoverAreaItem) {
    try {
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      const img = new Image();

      // 设置 crossOrigin 属性以避免 CORS 污染
      img.crossOrigin = 'anonymous';
      img.src = props.imgList[area.i];

      await new Promise((resolve, reject) => {
        img.onload = resolve;
        img.onerror = reject;
      });

      canvas.width = area.w * img.width;
      canvas.height = area.h * img.height;

      // 使用drawImage的9参数版本直接绘制指定区域
      // drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
      ctx?.drawImage(
        img,
        area.x * img.width,
        area.y * img.height,
        area.w * img.width,
        area.h * img.height,
        0,
        0,
        area.w * img.width,
        area.h * img.height
      );

      const blob = await new Promise<Blob | null>((resolve) => {
        canvas.toBlob(resolve, 'image/png');
      });

      if (!blob) {
        throw new Error('Failed to create blob from canvas');
      }

      return URL.createObjectURL(blob);
    } catch (error) {
      console.warn(
        'Failed to generate preview with canvas, falling back to original image:',
        error
      );
      // 如果 canvas 导出失败，返回原图片 URL 作为备选方案
      return '';
    }
  }

  const onSelectFullArea = async () => {
    const hasFullArea = coverAreas.value.some(
      (area) =>
        area.i === currentImageIndex.value &&
        area.x === 0 &&
        area.y === 0 &&
        area.w === 1 &&
        area.h === 1
    );
    if (hasFullArea) {
      ElMessage({
        message: '已添加全图框选区域',
        type: 'warning',
      });
      return;
    }
    // 添加新的框选区域
    coverAreas.value.push({
      i: currentImageIndex.value,
      x: 0,
      y: 0,
      w: 1,
      h: 1,
      splitUrl: currentImage.value,
    });
  };

  // 切换图片
  const switchImage = async (index: number) => {
    currentImageIndex.value = index;
  };

  // 删除框选区域
  const deleteCoverArea = (index: number) => {
    coverAreas.value.splice(index, 1);
    // 重新分配索引
    coverAreas.value.forEach((area, i) => {
      area.i = i;
    });
  };

  // 清除所有框选区域
  const clearAll = () => {
    coverAreas.value = [];
  };

  // 关闭弹窗
  const close = () => {
    visible.value = false;
    emit('close');
  };

  // 保存
  const save = () => {
    const areas = coverAreas.value.map((area) => {
      if (area.x === 0 && area.y === 0 && area.w === 1 && area.h === 1) {
        return {
          i: area.i,
        };
      }
      return {
        i: area.i,
        x: area.x,
        y: area.y,
        w: area.w,
        h: area.h,
      };
    });
    emit('update:modelValue', areas);
    emit('change', areas);
    close();
  };

  // 打开弹窗
  const open = () => {
    visible.value = true;
  };

  // 弹窗打开事件
  const handleOpen = async () => {
    const areas = props.modelValue || [];
    for (const area of areas) {
      if (Object.prototype.hasOwnProperty.call(area, 'x')) {
        const splitUrl = await generatePreview(area);
        coverAreas.value.push({
          ...area,
          splitUrl,
        });
      } else {
        coverAreas.value.push({
          ...area,
          x: 0,
          y: 0,
          w: 1,
          h: 1,
          splitUrl: props.imgList[area.i],
        });
      }
    }
    currentImageIndex.value = 0;
  };

  // 弹窗关闭事件
  const handleClose = () => {
    coverAreas.value = [];
  };

  // 暴露方法
  defineExpose({
    open,
    close,
  });
</script>

<style lang="scss">
  .select-img-area-dialog {
    .el-dialog__header {
      display: none;
    }
    .el-dialog__body {
      padding: 0;
    }
  }
</style>

<style lang="scss" scoped>
  .select-img-area-container {
    display: flex;
    height: 100vh;
    gap: 20px;
    padding: 15px 20px;
  }

  .left-panel {
    flex: 2;
    display: flex;
    flex-direction: column;
    .image-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-bottom: 10px;
    }

    .image-menu {
      flex: 2;
      display: flex;
      flex-wrap: wrap;
    }

    .image-container {
      flex: 1;
      border: 1px solid #dcdfe6;
      border-radius: 4px;
      overflow: hidden;
      background: #f5f7fa;
      min-height: 400px;
      display: flex;
      align-items: center;
      justify-content: center;

      img {
        max-width: 100%;
        max-height: 100%;
        width: auto;
        height: auto;
        display: block;
      }

      :deep(cropper-canvas) {
        height: 100%;
        width: 100%;
      }
    }
  }

  .right-panel {
    width: 400px;
    flex-grow: 0;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    padding: 16px;

    .preview-title {
      font-size: 16px;
      font-weight: 500;
      margin-bottom: 16px;
      color: #303133;
    }

    .preview-container {
      flex: 1;
      overflow-y: auto;

      .preview-item {
        margin-bottom: 16px;

        .preview-image-wrapper {
          position: relative;
          display: inline-block;
          border: 1px solid #dcdfe6;
          border-radius: 4px;
          overflow: hidden;

          img {
            display: block;
            width: 100%;
            height: auto;
          }

          .delete-btn {
            position: absolute;
            top: 4px;
            right: 4px;
            width: 24px;
            height: 24px;
            line-height: 24px;
            text-align: center;

            .el-icon {
              margin: 0;
            }
          }
        }

        .area-info {
          margin-top: 8px;
          font-size: 12px;
          color: #606266;
        }
      }
    }

    .bottom-buttons {
      display: flex;
      gap: 12px;
      justify-content: flex-end;
      margin-top: 16px;
      padding-top: 16px;
      border-top: 1px solid #ebeef5;

      .el-button {
        margin: 0;
        flex: 2;
      }
    }
  }
</style>
