<template>
  <div class="w-full max-w-1200px mx-auto p-4 flex flex-col h-[85vh] box-border">
    <div
      class="relative mb-6 p-8 border-2 border-dashed rounded-xl transition-all duration-300 group"
      :class="[
        isDragOver
          ? 'border-primary bg-primary-50 scale-[1.01]'
          : 'border-gray-300 bg-white hover:border-primary-300',
        uploading ? 'opacity-80 pointer-events-none' : ''
      ]"
      @dragover.prevent="isDragOver = true"
      @dragleave.prevent="isDragOver = false"
      @drop.prevent="handleDrop"
    >
      <div class="flex flex-col items-center justify-center gap-4 text-center">
        <div class="p-4 rounded-full bg-gray-50 group-hover:bg-white transition-colors">
          <el-icon
            class="text-5xl text-gray-400 group-hover:text-primary transition-colors duration-300"
            ><UploadFilled
          /></el-icon>
        </div>

        <div class="text-gray-500">
          <p class="text-lg font-medium mb-1">拖拽文件到此处，或点击下方按钮</p>
          <p class="text-xs text-gray-400">{{ uploadHintText }}</p>
        </div>

        <div class="flex gap-4 mt-2">
          <el-button
            type="primary"
            size="large"
            round
            :loading="uploading"
            @click="handleFileUploadClick"
            class="!px-8 shadow-md hover:shadow-lg transition-shadow"
          >
            <el-icon class="mr-2"><Document /></el-icon>
            {{ uploading ? '上传中...' : '选择文件' }}
          </el-button>

          <el-button
            v-if="showFolderButton"
            type="success"
            size="large"
            round
            plain
            :loading="uploading"
            @click="handleFolderUploadClick"
            class="!px-8 shadow-md hover:shadow-lg transition-shadow"
          >
            <el-icon class="mr-2"><Folder /></el-icon>
            文件夹上传
          </el-button>
        </div>
      </div>

      <input
        ref="fileInput"
        type="file"
        class="hidden"
        :multiple="true"
        accept="*"
        :webkitdirectory="isFolderMode"
        :directory="isFolderMode"
        @change="handleFileChange"
      />
    </div>

    <div
      v-if="uploadList.length > 0"
      class="flex-1 overflow-hidden flex flex-col bg-white rounded-xl shadow-sm border border-gray-100"
    >
      <div class="p-4 border-b border-gray-100 flex justify-between items-center bg-gray-50/50">
        <h3 class="font-bold text-gray-700 flex items-center gap-2">
          <el-icon><List /></el-icon> 上传列表
          <span
            class="text-xs font-normal text-gray-400 bg-white px-2 py-0.5 rounded-full border border-gray-200"
          >
            {{ uploadList.length }} 项
          </span>
        </h3>
        <el-button v-if="uploading" link type="danger" @click="cancelAll">全部取消</el-button>
      </div>

      <div class="flex-1 overflow-y-auto custom-scrollbar p-2">
        <el-table :data="uploadList" style="width: 100%" :show-header="true" class="custom-table">
          <el-table-column label="名称" min-width="250">
            <template #default="{ row }">
              <div class="flex items-center gap-3">
                <div
                  class="w-10 h-10 rounded-lg flex items-center justify-center bg-gray-50 text-xl shrink-0"
                >
                  <el-icon v-if="row.type === 'folder'" class="text-yellow-500"><Folder /></el-icon>
                  <el-icon v-else class="text-blue-500"><Document /></el-icon>
                </div>
                <div class="flex flex-col overflow-hidden">
                  <span class="truncate font-medium text-gray-700" :title="row.name">{{
                    row.name
                  }}</span>
                  <span class="text-xs text-gray-400">{{ formatSize(null, null, row.size) }}</span>
                </div>
              </div>
            </template>
          </el-table-column>

          <el-table-column label="状态" width="300">
            <template #default="{ row }">
              <div class="pr-6">
                <div class="flex justify-between text-xs mb-1">
                  <span :class="getStatusColor(row.status)">{{ getStatusText(row.status) }}</span>
                  <span class="text-gray-400">{{ row.progress }}%</span>
                </div>
                <el-progress
                  :percentage="row.progress"
                  :status="getProgressStatus(row.status)"
                  :stroke-width="6"
                  :show-text="false"
                  class="!m-0"
                />
              </div>
            </template>
          </el-table-column>

          <el-table-column label="操作" width="100" align="center">
            <template #default="{ row }">
              <el-button
                v-if="row.status === 'uploading' || row.status === 'wait'"
                circle
                size="small"
                type="danger"
                plain
                @click.stop="handleCancelUpload(row)"
              >
                <el-icon><Close /></el-icon>
              </el-button>

              <el-icon v-else-if="row.status === 'success'" class="text-green-500 text-lg"
                ><CircleCheckFilled
              /></el-icon>
              <el-icon v-else-if="row.status === 'error'" class="text-red-500 text-lg"
                ><CircleCloseFilled
              /></el-icon>
              <span v-else-if="row.status === 'cancelled'" class="text-xs text-gray-400"
                >已取消</span
              >
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, nextTick } from 'vue'
import axios from 'axios'
import { ElMessage, ElNotification } from 'element-plus'
import {
  UploadFilled,
  Folder,
  Document,
  Close,
  CircleCheckFilled,
  CircleCloseFilled,
  List
} from '@element-plus/icons-vue'

// --- Props 定义 ---
const props = defineProps({
  deviceId: { type: String, default: '' },
  allowFolderUpload: { type: Boolean, default: true },
  showFolderButton: { type: Boolean, default: true },
  maxFolderSize: { type: Number, default: 300 }, // MB
  uploadUrl: {
    type: String,
    default: import.meta.env.VITE_BASE_URL + '/admin-api/rq/file/upload'
  }
})

// --- Events ---
const emit = defineEmits(['uploadSuccess', 'uploadError', 'uploadComplete'])

// --- State ---
const fileInput = ref(null)
const uploading = ref(false)
const uploadList = ref([])
const isFolderMode = ref(false)
const isDragOver = ref(false)
const uploadControllers = ref(new Map()) // 存储 AbortController 用于取消 axios 请求

// --- Computed ---
const uploadHintText = computed(() => {
  return props.showFolderButton
    ? '支持单个文件 (Max 50MB) 或整个文件夹上传 (Max 500MB)'
    : '单个文件大小不能超过 50MB'
})

// --- Helpers ---
const getProgressStatus = (status) => {
  const map = { success: 'success', error: 'exception', uploading: '', wait: 'warning' }
  return map[status] || ''
}

const getStatusColor = (status) => {
  const map = {
    success: 'text-green-500',
    error: 'text-red-500',
    uploading: 'text-primary',
    wait: 'text-gray-400',
    cancelled: 'text-gray-400'
  }
  return map[status]
}

const getStatusText = (status) => {
  const map = {
    success: '上传成功',
    error: '上传失败',
    uploading: '正在上传...',
    wait: '等待中',
    cancelled: '已取消'
  }
  return map[status]
}

const formatSize = (row, column, bytes) => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

const calculateFolderSize = (files) => {
  return files.reduce((acc, file) => acc + file.size, 0)
}

// --- Actions ---

// 点击上传文件
const handleFileUploadClick = () => {
  if (uploading.value) return
  isFolderMode.value = false
  triggerInput()
}

// 点击上传文件夹
const handleFolderUploadClick = () => {
  if (uploading.value) return
  if (!props.allowFolderUpload) {
    ElMessage.warning('当前不允许上传文件夹')
    return
  }
  isFolderMode.value = true
  triggerInput()
}

const triggerInput = () => {
  if (fileInput.value) fileInput.value.value = ''
  nextTick(() => fileInput.value.click())
}

// 拖拽处理 (默认作为普通文件处理，浏览器对于拖拽文件夹有安全限制，这里简化处理)
const handleDrop = (e) => {
  isDragOver.value = false
  if (uploading.value) return

  const files = Array.from(e.dataTransfer.files)
  if (files.length === 0) return

  // 拖拽模式默认为文件模式处理
  isFolderMode.value = false
  processFiles(files)
}

// Input Change 处理
const handleFileChange = (e) => {
  const files = Array.from(e.target.files)
  if (files.length === 0) return
  e.target.value = '' // Reset input
  processFiles(files)
}

// 统一文件处理逻辑
const processFiles = async (files) => {
  // 判断是否包含文件夹路径 (通过 input webkitdirectory 获取的文件会有 webkitRelativePath)
  const hasRelativePath =
    isFolderMode.value &&
    files.some((f) => f.webkitRelativePath && f.webkitRelativePath.includes('/'))

  if (hasRelativePath) {
    // --- 文件夹模式 ---
    const folderMap = new Map()

    files.forEach((file) => {
      const path = file.webkitRelativePath
      const rootFolder = path.substring(0, path.indexOf('/'))
      if (!folderMap.has(rootFolder)) {
        folderMap.set(rootFolder, [])
      }
      folderMap.get(rootFolder).push(file)
    })

    // 校验大小并加入列表
    for (const [folderName, folderFiles] of folderMap) {
      const size = calculateFolderSize(folderFiles)
      if (size / 1024 / 1024 > props.maxFolderSize) {
        ElNotification({
          title: '超限警告',
          message: `文件夹 "${folderName}" 超过 ${props.maxFolderSize}MB`,
          type: 'warning'
        })
        continue
      }

      addToUploadList({
        name: folderName,
        size: size,
        type: 'folder',
        files: folderFiles
      })
    }
  } else {
    // --- 普通文件模式 ---
    files.forEach((file) => {
      addToUploadList({
        name: file.name,
        size: file.size,
        type: 'file',
        files: [file]
      })
    })
  }

  await startUploadQueue()
}

const addToUploadList = (item) => {
  uploadList.value.push({
    uid: Date.now() + Math.random().toString(36).substr(2, 9),
    progress: 0,
    status: 'wait',
    ...item
  })
}

// --- Upload Logic (Axios) ---
const startUploadQueue = async () => {
  if (uploading.value) return // 避免重复触发
  uploading.value = true

  // 获取所有等待中的任务
  const pendingItems = uploadList.value.filter((item) => item.status === 'wait')

  // 并发上传控制（这里简化为全部并发，实际生产环境可能需要 p-limit）
  const promises = pendingItems.map((item) => uploadSingleItem(item))

  await Promise.allSettled(promises)

  // 检查是否全部结束
  checkAllComplete()
}

const uploadSingleItem = async (item) => {
  const index = uploadList.value.findIndex((x) => x.uid === item.uid)
  if (index === -1 || item.status === 'cancelled') return

  // 更新状态
  uploadList.value[index].status = 'uploading'

  // 构建 FormData
  const formData = new FormData()
  item.files.forEach((file) => {
    // 如果是文件夹上传，保留相对路径，否则使用文件名
    const filename =
      item.type === 'folder' && file.webkitRelativePath ? file.webkitRelativePath : file.name
    formData.append('files', file, filename)
  })

  if (item.type === 'folder') {
    formData.append('isFolder', 'true')
    formData.append('folderPath', item.name)
  }

  // 创建 CancelToken
  const controller = new AbortController()
  uploadControllers.value.set(item.uid, controller)

  try {
    const response = await axios.post(props.uploadUrl, formData, {
      headers: {
        'tenant-id': 1,
        'device-id': props.deviceId,
        'Content-Type': 'multipart/form-data'
      },
      signal: controller.signal,
      onUploadProgress: (progressEvent) => {
        if (progressEvent.total) {
          const percent = Math.round((progressEvent.loaded / progressEvent.total) * 100)
          // 保持响应式更新
          if (uploadList.value[index]) {
            uploadList.value[index].progress = percent
          }
        }
      }
    })

    // 成功处理
    if (uploadList.value[index]) {
      uploadList.value[index].status = 'success'
      uploadList.value[index].progress = 100
      emit('uploadSuccess', { uid: item.uid, name: item.name, response: response.data })
    }
  } catch (error) {
    if (axios.isCancel(error)) {
      if (uploadList.value[index]) uploadList.value[index].status = 'cancelled'
    } else {
      console.error('Upload Error:', error)
      if (uploadList.value[index]) uploadList.value[index].status = 'error'
      emit('uploadError', { uid: item.uid, name: item.name, error })
    }
  } finally {
    uploadControllers.value.delete(item.uid)
  }
}

const handleCancelUpload = (item) => {
  const controller = uploadControllers.value.get(item.uid)
  if (controller) {
    controller.abort()
  } else {
    // 如果还没开始上传（在wait状态），直接标记取消
    const index = uploadList.value.findIndex((x) => x.uid === item.uid)
    if (index !== -1) uploadList.value[index].status = 'cancelled'
  }
}

const cancelAll = () => {
  uploadList.value.forEach((item) => {
    if (item.status === 'uploading' || item.status === 'wait') {
      handleCancelUpload(item)
    }
  })
}

const checkAllComplete = () => {
  const hasPending = uploadList.value.some((item) => ['wait', 'uploading'].includes(item.status))
  if (!hasPending) {
    uploading.value = false
    emit('uploadComplete')
  }
}
</script>

<style scoped>
/* 自定义滚动条样式 */
.custom-scrollbar::-webkit-scrollbar {
  width: 6px;
}

.custom-scrollbar::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 4px;
}

.custom-scrollbar::-webkit-scrollbar-thumb {
  background: #d1d5db;
  border-radius: 4px;
}

.custom-scrollbar::-webkit-scrollbar-thumb:hover {
  background: #9ca3af;
}

/* 覆盖 Element 表格的一些默认样式以适配 UnoCSS 风格 */
:deep(.custom-table .el-table__inner-wrapper::before) {
  display: none; /* 移除表格底部边框 */
}

:deep(.custom-table .el-table__cell) {
  border-bottom: 1px solid #f3f4f6;
}

:deep(.el-progress-bar__inner) {
  transition: width 0.3s ease;
}
</style>
