<template>
  <view class="file-picker-wrapper">
    <!-- 只读模式：仅展示文件列表 -->
    <view v-if="readonly" class="file-list readonly-list">
      <view v-for="(file, index) in value" :key="index" class="file-item readonly-item" @click="previewFile(file)">
        <image v-if="isImage(file)" :src="file.url || file.path" mode="aspectFill" class="file-thumb" />
        <view v-else class="file-icon">
          <text class="iconfont icon-file">📄</text>
        </view>
        <text class="file-name">{{ file.name }}</text>
      </view>
      <view v-if="!value.length" class="empty-text">暂无文件</view>
    </view>

    <!-- 非只读模式：完整功能 -->
    <view v-else>
      <view class="upload-area">
        <uni-file-picker ref="filePicker" v-bind="$attrs" :limit="999" :show-file-list="false" :auto-upload="false"
          mode="grid" @select="handleSelect" @fail="handleFail" @error="handleError">
          <cwg-icon name="icon_add" class="upload-icon" :size="24" />
        </uni-file-picker>
      </view>
    </view>
  </view>
</template>

<script setup>
import { computed, ref, watch } from 'vue'
import config from '@/config'
import { userToken } from '@/composables/config'

// 定义 props
const props = defineProps({
  // 支持 v-model 的文件列表
  value: {
    type: Array,
    default: () => []
  },
  // 只读模式
  readonly: {
    type: Boolean,
    default: false
  },
  // 最大文件数量
  limit: {
    type: Number,
    default: 5
  },
  // 文件类型限制（image/video/all）
  fileMediatype: {
    type: String,
    default: 'all'
  },
  // 上传地址（必填）
  action: {
    type: String,
    default: ''
  },
  // 上传URL（优先使用）
  uploadUrl: {
    type: String,
    default: '/custom/bank/upload'
  },
  // 上传请求头
  uploadHeaders: {
    type: Object,
    default: () => ({})
  },
  // 上传字段名
  uploadName: {
    type: String,
    default: 'file'
  },
  // 上传额外数据
  uploadData: {
    type: Object,
    default: () => ({})
  },
  // 响应数据处理函数
  responseHandler: {
    type: Function,
    default: (res) => {
      try {
        const data = typeof res === 'string' ? JSON.parse(res) : res
        return {
          success: data.code === 200,
          path: data.data?.path || data.data,
          message: data.msg || '上传成功',
          data: data
        }
      } catch (e) {
        return {
          success: false,
          path: null,
          message: '解析响应失败',
          data: null
        }
      }
    }
  }
})

// 定义 emits
const emit = defineEmits([
  'input',
  'update:value',
  'change',
  'delete',
  'success',
  'fail',
  'error',
  'progress'
])

// 响应式数据
const innerFileList = ref([])      // 内部文件列表
const uploadProgress = ref({})     // 存储每个文件的上传进度 { fileIndex: progress }
const isUploading = ref(false)     // 是否正在上传

// 计算属性
const remainingLimit = computed(() => {
  return Math.max(0, props.limit - innerFileList.value.length)
})

// 监听外部 value 变化
watch(
  () => props.value,
  (newVal) => {
    innerFileList.value = [...newVal]
  },
  { immediate: true, deep: true }
)

// 监听内部文件列表变化，同步到外部
watch(
  innerFileList,
  (newVal) => {
    emit('input', newVal)
    emit('update:value', newVal)
    emit('change', newVal)
  },
  { deep: true }
)

// 方法
// 判断是否为图片
const isImage = (file) => {
  const type = file.type || file.fileType
  if (type) return type.startsWith('image/')
  const ext = (file.name || '').split('.').pop().toLowerCase()
  return ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'].includes(ext)
}

// 预览文件
const previewFile = (file) => {
  if (isImage(file)) {
    const urls = innerFileList.value
      .filter(f => isImage(f))
      .map(f => f.url || f.path)
    const current = file.url || file.path
    uni.previewImage({ urls, current })
  } else {
    if (file.url) {
      // #ifdef H5
      window.open(file.url)
      // #endif
      // #ifdef APP-PLUS
      plus.runtime.openURL(file.url)
      // #endif
      // #ifdef MP-WEIXIN
      uni.downloadFile({
        url: file.url,
        success: (res) => uni.openDocument({ filePath: res.tempFilePath })
      })
      // #endif
    } else {
      uni.showToast({ title: '暂无法预览此文件', icon: 'none' })
    }
  }
}

// 删除文件
const deleteFile = (index) => {
  const deleted = innerFileList.value[index]
  innerFileList.value.splice(index, 1)
  emit('delete', deleted, index)
}

// 处理文件选择
const handleSelect = async (res) => {
  const { tempFiles } = res
  // 正常新增模式：检查数量限制
  const availableSlots = props.limit - innerFileList.value.length
  const toAddFiles = tempFiles.slice(0, availableSlots)
  if (toAddFiles.length < tempFiles.length) {
    uni.showToast({
      title: `最多选择${props.limit}个文件，超出部分已忽略`,
      icon: 'none'
    })
  }

  isUploading.value = true
  try {
    for (let i = 0; i < toAddFiles.length; i++) {
      const file = toAddFiles[i]
      const fileIndex = innerFileList.value.length + i
      await uploadFile(file, fileIndex)
    }
  } finally {
    isUploading.value = false
  }
}
const filePicker = ref(null)
// 上传文件
const uploadFile = (fileItem, fileIndex) => {
  return new Promise((resolve, reject) => {
    // 构建上传URL
    const uploadUrl = props.action || (config.Host80 + props.uploadUrl)

    // 构建上传参数
    const task = uni.uploadFile({
      url: uploadUrl,
      filePath: fileItem.path,
      name: props.uploadName,
      header: {
        'Access-Token': userToken.value,
        ...props.uploadHeaders
      },
      formData: props.uploadData,
      success: (res) => {

        const result = props.responseHandler(res.data)
        if (result.success) {
          // 构造文件对象
          const uploadedFile = {
            url: config.Host80 + result.path,
            path: result.path,
            name: fileItem.name,
            size: fileItem.size,
            type: fileItem.type,
            response: result.data
          }
          innerFileList.value.push(uploadedFile)
          emit('success', uploadedFile, res)
          resolve(uploadedFile)
        } else {
          uni.showToast({ title: result.message || '上传失败', icon: 'error' })
          emit('fail', new Error(result.message), fileItem)
          reject(new Error(result.message))
        }
      },
      fail: (err) => {
        // 清除进度
        delete uploadProgress.value[fileIndex]

        console.error('上传失败:', err)
        uni.showToast({ title: '网络错误，请重试', icon: 'error' })
        emit('fail', err, fileItem)
        reject(err)
      }
    })

    // 监听上传进度
    task.onProgressUpdate((progress) => {
      uploadProgress.value[fileIndex] = progress.progress
      emit('progress', progress, fileItem, fileIndex)
    })
  })
}



// 处理失败事件（来自 uni-file-picker）
const handleFail = (err) => {
  emit('fail', err)
}

// 处理错误事件（来自 uni-file-picker）
const handleError = (err) => {
  emit('error', err)
}

// 格式化文件大小
const formatFileSize = (bytes) => {
  if (!bytes) return ''
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(1024))
  return (bytes / Math.pow(1024, i)).toFixed(2) + sizes[i]
}

// 暴露方法（可选，与原组件保持一致，未暴露任何方法）
// defineExpose({})
</script>

<style scoped>
.file-picker-wrapper {
  width: 100%;
}

.file-list {
  margin-bottom: 20rpx;
}

.file-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: #f8f8f8;
  border-radius: 12rpx;
  padding: 16rpx 20rpx;
  margin-bottom: 16rpx;
}

.file-info {
  display: flex;
  align-items: center;
  flex: 1;
  gap: 20rpx;
}

.file-thumb {
  width: 80rpx;
  height: 80rpx;
  border-radius: 8rpx;
  background: #e0e0e0;
}

.file-icon {
  width: 80rpx;
  height: 80rpx;
  background: #e0e0e0;
  border-radius: 8rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.file-detail {
  flex: 1;
  overflow: hidden;
}

.file-name {
  font-size: 28rpx;
  color: #333;
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.file-size {
  font-size: 24rpx;
  color: #999;
  margin-top: 8rpx;
  display: block;
}

.file-actions {
  display: flex;
  gap: 16rpx;
}

.action-btn {
  padding: 0 20rpx;
  height: 56rpx;
  line-height: 56rpx;
  font-size: 24rpx;
}

.readonly-item {
  cursor: pointer;
  transition: opacity 0.2s;
}

.readonly-item:active {
  opacity: 0.7;
}

.empty-text {
  text-align: center;
  color: #999;
  font-size: 28rpx;
  padding: 40rpx 0;
}

.upload-area {
  margin-top: 20rpx;
}

.upload-btn {
  width: 100%;
  background: #007aff;
  color: #fff;
  border-radius: 8rpx;
}

/* 上传进度条样式 */
.upload-progress {
  position: relative;
  width: 100%;
  height: 8rpx;
  background-color: #f0f0f0;
  border-radius: 4rpx;
  margin-top: 8rpx;
  overflow: hidden;

  .progress-bar {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    background-color: #007aff;
    border-radius: 4rpx;
    transition: width 0.3s ease;
  }

  .progress-text {
    position: absolute;
    top: 0;
    right: 0;
    font-size: 20rpx;
    color: #666;
    line-height: 8rpx;
  }
}
</style>