<!-- 文件上传 -->
<script setup lang="ts">
import type { FileItem } from '@/stores/modules/files';
import { useFileDialog } from '@vueuse/core';
import { ElMessage } from 'element-plus';
import Popover from '@/components/Popover/index.vue';
import SvgIcon from '@/components/SvgIcon/index.vue';
import { useFilesStore } from '@/stores/modules/files';

const filesStore = useFilesStore();

// 文件大小限制 3MB
const MAX_FILE_SIZE = 3 * 1024 * 1024;

/* 弹出面板 开始 */
const popoverStyle = ref({
  padding: '4px',
  height: 'fit-content',
  background: 'var(--el-bg-color, #fff)',
  border: '1px solid var(--el-border-color-light)',
  borderRadius: '8px',
  boxShadow: '0 2px 12px 0 rgba(0, 0, 0, 0.1)',
});
const popoverRef = ref();
/* 弹出面板 结束 */

const { reset, open, onChange } = useFileDialog({
  // 允许图片和文件
  accept: 'image/*,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  directory: false, // 是否允许选择文件夹
  multiple: true, // 是否允许多选
});

// 压缩图片
function compressImage(file: File, maxWidth = 1024, maxHeight = 1024, quality = 0.8): Promise<Blob> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      const img = new Image();
      img.onload = () => {
        const canvas = document.createElement('canvas');
        let width = img.width;
        let height = img.height;

        // 计算缩放比例
        if (width > maxWidth || height > maxHeight) {
          const ratio = Math.min(maxWidth / width, maxHeight / height);
          width = width * ratio;
          height = height * ratio;
        }

        canvas.width = width;
        canvas.height = height;

        const ctx = canvas.getContext('2d')!;
        ctx.drawImage(img, 0, 0, width, height);

        // 转换为 Blob
        canvas.toBlob(
          (blob) => {
            if (blob) {
              resolve(blob);
            } else {
              reject(new Error('压缩失败'));
            }
          },
          file.type,
          quality
        );
      };
      img.onerror = reject;
      img.src = e.target?.result as string;
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

// 将 Blob 转换为 base64
function blobToBase64(blob: Blob): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      resolve(reader.result as string);
    };
    reader.onerror = reject;
    reader.readAsDataURL(blob);
  });
}

onChange(async (files) => {
  if (!files)
    return;

  const arr = [] as FileItem[];

  for (let i = 0; i < files!.length; i++) {
    const file = files![i];

    // 验证文件大小
    if (file.size > MAX_FILE_SIZE) {
      ElMessage.error(`文件 ${file.name} 超过 3MB 限制，已跳过`);
      continue;
    }

    const isImage = file.type.startsWith('image/');

    // 压缩并转换为base64
    let base64 = '';
    let previewUrl = '';
    if (isImage) {
      try {
        // 先压缩图片
        const compressedBlob = await compressImage(file, 1024, 1024, 0.8);
        // 再转换为 base64
        base64 = await blobToBase64(compressedBlob);
        // 使用压缩后的图片作为预览
        previewUrl = base64;

        // 计算压缩比例
        const originalSize = (file.size / 1024).toFixed(2);
        const compressedSize = (compressedBlob.size / 1024).toFixed(2);
        console.log(`图片压缩: ${file.name} - 原始: ${originalSize}KB, 压缩后: ${compressedSize}KB`);
      } catch (error) {
        console.error('压缩图片失败:', error);
        ElMessage.error(`${file.name} 压缩失败`);
        continue;
      }
    }

    arr.push({
      uid: crypto.randomUUID(), // 不写 uid,文件列表展示不出来,elx 1.2.0 bug 待修复
      name: file.name,
      fileSize: file.size,
      file,
      maxWidth: '200px',
      showDelIcon: true, // 显示删除图标
      imgPreview: isImage, // 图片才显示预览
      imgVariant: 'square', // 图片预览的形状
      url: isImage ? previewUrl : undefined, // 使用压缩后的 base64 作为预览地址
      isUploaded: true, // 直接标记为已完成
      base64: isImage ? base64 : undefined, // 保存压缩后的base64
    });
  }

  if (arr.length > 0) {
    filesStore.setFilesList([...filesStore.filesList, ...arr]);
    ElMessage.success(`已添加 ${arr.length} 个文件`);
  }

  // 重置文件选择器
  nextTick(() => reset());
});

function handleUploadFiles() {
  open();
  popoverRef.value.hide();
}
</script>

<template>
  <div class="files-select">
    <Popover
      ref="popoverRef"
      placement="top-start"
      :offset="[4, 0]"
      popover-class="popover-content"
      :popover-style="popoverStyle"
      trigger="clickTarget"
    >
      <template #trigger>
        <div
          class="flex items-center gap-4px p-10px rounded-10px cursor-pointer font-size-14px border-1px border-[rgba(0,0,0,0.08)] border-solid hover:bg-[rgba(0,0,0,.04)]"
        >
          <el-icon>
            <Paperclip />
          </el-icon>
        </div>
      </template>

      <div class="popover-content-box">
        <div
          class="popover-content-item flex items-center gap-4px p-10px rounded-10px cursor-pointer font-size-14px hover:bg-[rgba(0,0,0,.04)]"
          @click="handleUploadFiles"
        >
          <el-icon>
            <Upload />
          </el-icon>
          <div class="font-size-14px">
            上传文件或图片
          </div>
        </div>

        <Popover
          placement="right-end"
          :offset="[8, 4]"
          popover-class="popover-content"
          :popover-style="popoverStyle"
          trigger="hover"
          :hover-delay="100"
        >
          <template #trigger>
            <div
              class="popover-content-item flex items-center gap-4px p-10px rounded-10px cursor-pointer font-size-14px hover:bg-[rgba(0,0,0,.04)]"
            >
              <SvgIcon name="code" size="16" />
              <div class="font-size-14px">
                上传代码
              </div>

              <el-icon class="ml-auto">
                <ArrowRight />
              </el-icon>
            </div>
          </template>

          <div class="popover-content-box">
            <div
              class="popover-content-item flex items-center gap-4px p-10px rounded-10px cursor-pointer font-size-14px hover:bg-[rgba(0,0,0,.04)]"
              @click="
                () => {
                  ElMessage.warning('暂未开放');
                }
              "
            >
              代码文件
            </div>

            <div
              class="popover-content-item flex items-center gap-4px p-10px rounded-10px cursor-pointer font-size-14px hover:bg-[rgba(0,0,0,.04)]"
              @click="
                () => {
                  ElMessage.warning('暂未开放');
                }
              "
            >
              代码文件夹
            </div>
          </div>
        </Popover>
      </div>
    </Popover>
  </div>
</template>

<style scoped lang="scss"></style>
