<template>
  <div class="upload-wrapper">
    <!-- 上传按钮 -->
    <label for="fileInput" class="upload-button">
      <el-icon><UploadFilled /></el-icon>
      <span>{{ label }}</span>
    </label>
    <input type="file" id="fileInput" multiple accept=".pdf,.docx,.xls,.xlsx,.ppt,.pptx" @change="handleFileSelect" />

    <!-- 总体进度条 -->
    <div class="progress-container" v-show="showProgress">
      <div class="progress-info">
        <span>正在上传文件...</span>
        <span>{{ progressPercent }}%</span>
      </div>
      <div class="progress-bar">
        <div
          class="progress-bar-fill"
          :class="{ completed: isCompleted }"
          :style="{ width: `${progressPercent}%` }"
        ></div>
      </div>
    </div>

    <!-- 文件列表 -->
    <div class="file-list" v-if="fileList.length > 0">
      <div v-for="file in fileList" :key="file.fileId" class="file-item">
        <div class="file-info">
          <img :src="FILE_TYPE_ICON[file.fileType as keyof typeof FILE_TYPE_ICON]" />
          <span class="file-name">{{ file.fileName }}</span>
        </div>
        <el-icon class="delete-button" @click="removeFile(file.fileId)"><Delete /></el-icon>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
  import { ref, computed, nextTick, watch } from 'vue';
  import { UploadFilled, Delete } from '@element-plus/icons-vue';
  import { ElMessage, ElMessageBox } from 'element-plus';
  import { FILE_TYPE_ICON } from '../constant';
  import type { FileItem } from '../types';
  const props = defineProps<{
    label: string;
    fileList?: FileItem[];
  }>();

  // 常量定义
  const MAX_SIZE = 5 * 1024 * 1024; // 5MB

  // 响应式状态
  const fileList = ref<FileItem[]>([]);
  const tempFiles = ref<File[]>([]);
  const showProgress = ref(false);
  const isCompleted = ref(false);
  const progress = ref(0);

  // 计算属性
  const progressPercent = computed(() => {
    return Math.round(progress.value);
  });

  // 检查文件是否已存在
  const isFileAlreadyUploaded = (newFile: File): boolean => {
    return fileList.value.some((item) => {
      return item.file?.name === newFile.name && item.file.size === newFile.size && item.file?.type === newFile.type;
    });
  };

  // 获取文件类型
  const getFileType = (file: File): string => {
    const fileType = file.type;

    // 转换为系统中已有的四种类型
    if (fileType.includes('pdf')) return 'pdf';
    if (fileType.includes('word') || fileType.includes('msword') || fileType.includes('wordprocessingml'))
      return 'word';
    if (fileType.includes('excel') || fileType.includes('spreadsheetml') || fileType.includes('ms-excel'))
      return 'excel';
    if (fileType.includes('powerpoint') || fileType.includes('presentationml') || fileType.includes('ms-powerpoint'))
      return 'ppt';

    // 默认返回
    return 'pdf';
  };

  // 方法
  const handleFileSelect = (event: Event) => {
    const input = event.target as HTMLInputElement;
    if (!input.files || input.files.length === 0) return;

    const files = Array.from(input.files);
    let validFiles = 0;
    tempFiles.value = [];

    files.forEach((file) => {
      if (!isValidFileType(file)) {
        ElMessage.error(`${file.name} 不是允许的文件类型`);
        return;
      }

      if (file.size > MAX_SIZE) {
        ElMessage.error(`${file.name} 文件过大`);
        return;
      }

      // 检查是否已经上传过相同的文件
      if (isFileAlreadyUploaded(file)) {
        ElMessage.warning(`${file.name} 已经上传过了`);
        return;
      }

      // 保存到临时文件数组中，而不是立即添加到UI
      tempFiles.value.push(file);
      validFiles++;
    });

    progress.value = 0;

    // 显示进度条
    if (validFiles > 0) {
      showProgress.value = true;
      isCompleted.value = false;

      // 确保DOM更新后再开始动画
      nextTick(() => {
        simulateFileUpload();
      });
    }

    // 清空input以便再次选择相同文件
    input.value = '';
  };

  const isValidFileType = (file: File): boolean => {
    const allowedTypes = [
      'application/pdf',
      'application/msword',
      'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
      'application/vnd.ms-excel',
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      'application/vnd.ms-powerpoint',
      'application/vnd.openxmlformats-officedocument.presentationml.presentation',
    ];
    return allowedTypes.includes(file.type);
  };

  const addFileToUI = (file: File) => {
    const fileId = Date.now() + Math.floor(Math.random() * 1000);
    const fileType = getFileType(file);
    const fileSize = file.size;
    const fileName = file.name;

    fileList.value.unshift({
      fileId: fileId,
      file: file,
      fileType: fileType,
      fileName: fileName,
      fileSize: `${Math.round(fileSize / 1024)}KB`,
    });
  };

  const removeFile = (id: number) => {
    ElMessageBox.confirm('确定删除该文件吗？', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
    }).then(() => {
      const index = fileList.value.findIndex((item) => item.fileId === id);
      if (index !== -1) {
        fileList.value.splice(index, 1);
      }
      ElMessage.success('文件删除成功');
    });
  };

  const simulateFileUpload = () => {
    // 设置初始进度为5%，让用户立即看到进度
    progress.value = 5;

    // 使用更快的速度模拟上传进度
    let targetProgress = 5;
    const totalDuration = 500; // 总上传时间，毫秒
    const interval = 200; // 更新间隔
    const steps = totalDuration / interval;
    const increment = 95 / steps; // 每步增加的百分比，从5%到100%

    const uploadInterval = setInterval(() => {
      targetProgress += increment;

      if (targetProgress >= 100) {
        progress.value = 100;
        clearInterval(uploadInterval);

        // 上传完成后再添加文件到UI
        setTimeout(() => {
          tempFiles.value.forEach((file) => {
            addFileToUI(file);
          });

          isCompleted.value = true;
          ElMessage.success('文件上传成功');
          emit('uploadSuccess', fileList.value);
          setTimeout(() => {
            showProgress.value = false;
          }, 500);
        }, 200);
      } else {
        progress.value = targetProgress;
      }
    }, interval);
  };
  const emit = defineEmits(['uploadSuccess']);
  watch(
    () => props.fileList,
    (newVal) => {
      fileList.value = newVal || [];
    },
    {
      immediate: true,
    },
  );
</script>

<style lang="scss" scoped>
  .upload-wrapper {
    display: flex;
    flex-direction: column;
    width: 100%;
  }

  .upload-button {
    @include flex-center;
    gap: 5cpx;
    width: 100cpx;
    border: 1px solid rgba($text-color, 0.15);
    color: $primary-color;
    font-size: 14cpx;
    border-radius: 2px;
    text-align: center;
    cursor: pointer;
    transition: all 0.3s ease-in-out;

    &:hover {
      background-color: $primary-color;
      color: $white-color;
    }
  }

  #fileInput {
    display: none;
  }

  .progress-container {
    margin-top: 16cpx;
  }

  .progress-info {
    display: flex;
    justify-content: space-between;
    font-size: 14cpx;
    color: #666;
  }

  .progress-bar {
    width: 100%;
    height: 8px;
    background-color: #e5e7eb;
    border-radius: 9999px;
    overflow: hidden;
  }

  .progress-bar-fill {
    height: 100%;
    background-color: $primary-color;
    border-radius: 9999px;
    transition: width 0.3s ease;

    &.completed {
      background-color: #10b981;
    }
  }

  .file-list {
    margin-top: 16cpx;
    display: flex;
    flex-wrap: wrap;
    gap: 8cpx;
  }

  .file-item {
    @include flex-center;
    justify-content: space-between;
    width: 100%;
    border: 1px solid #e5e7eb;
    border-radius: 6cpx;
    padding: 12cpx;
    transition: all 0.2s ease;

    &:hover {
      background-color: #f8fafc;
    }
  }

  .file-info {
    display: flex;
    align-items: center;
    gap: 8cpx;
    img {
      width: 20cpx;
    }
  }

  .file-name {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .delete-button {
    color: #ef4444;
    background: none;
    border: none;
    cursor: pointer;
  }
</style>
