<template>
  <view class="attachment-block">
    <view class="form-item clickable-item" @click="handleChooseFiles">
      <view class="form-icon">{{ icon }}</view>
      <text class="form-label">{{ title }}</text>
      <text class="arrow">›</text>
    </view>

    <view class="files-list" v-if="files.length">
      <view
        class="file-item"
        v-for="(file, index) in files"
        :key="file.path + index"
        @click="previewFile(file)"
      >
        <text class="file-icon">{{ getFileIcon(file.name) }}</text>
        <view class="file-info">
          <text class="file-name">{{ file.name }}</text>
          <text class="file-size" v-if="file.size > 0">{{ formatFileSize(file.size) }}</text>
        </view>
        <view class="remove-btn" @click.stop="removeFile(index)">✕</view>
      </view>
    </view>
  </view>
</template>

<script setup>
import { computed } from 'vue';
import { batchUploadFilesToQiniu } from '@/utils/qiniu.js';

const props = defineProps({
  modelValue: {
    type: Array,
    default: () => []
  },
  maxCount: {
    type: Number,
    default: 5
  },
  title: {
    type: String,
    default: '添加文件'
  },
  icon: {
    type: String,
    default: '📄'
  },
  extensions: {
    type: Array,
    default: () => ['.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.txt', '.zip', '.rar', '.jpg', '.png']
  }
});

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

const files = computed({
  get: () => props.modelValue,
  set: (val) => {
    emit('update:modelValue', val);
    emit('change', val);
  }
});

const handleChooseFiles = async () => {
  const remainingCount = props.maxCount - files.value.length;
  if (remainingCount <= 0) {
    uni.showToast({
      title: `最多只能添加${props.maxCount}个文件`,
      icon: 'none'
    });
    return;
  }

  try {
    // #ifdef H5 || MP-WEIXIN || APP-PLUS
    await chooseFilesWithUni(remainingCount);
    // #endif

    // #ifndef H5 || MP-WEIXIN || APP-PLUS
    await chooseFilesNative(remainingCount);
    // #endif
  } catch (error) {
    console.error('选择文件失败:', error);
    uni.showToast({
      title: error?.message || '选择文件失败',
      icon: 'none'
    });
  }
};

const chooseFilesWithUni = (remainingCount) => {
  return new Promise((resolve, reject) => {
    uni.chooseFile({
      count: remainingCount,
      extension: props.extensions,
      success: async (res) => {
        try {
          await uploadFiles(res.tempFiles.map(file => ({
            path: file.path,
            name: file.name
          })));
          resolve();
        } catch (error) {
          reject(error);
        }
      },
      fail: async () => {
        try {
          await chooseFilesNative(remainingCount);
          resolve();
        } catch (nativeError) {
          reject(nativeError);
        }
      }
    });
  });
};

const chooseFilesNative = async (remainingCount) => {
  if (typeof plus === 'undefined') {
    uni.showToast({
      title: '当前环境不支持文件选择',
      icon: 'none'
    });
    throw new Error('native file picker not available');
  }

  return new Promise((resolve, reject) => {
    try {
      const Intent = plus.android.importClass('android.content.Intent');
      const main = plus.android.runtimeMainActivity();
      const intent = new Intent(Intent.ACTION_GET_CONTENT);
      intent.setType('*/*');
      intent.addCategory(Intent.CATEGORY_OPENABLE);
      intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

      const originalOnActivityResult = main.onActivityResult;
      main.startActivityForResult(intent, 1001);

      main.onActivityResult = async (requestCode, resultCode, data) => {
        if (requestCode === 1001) {
          if (resultCode === -1 && data) {
            try {
              const filesToUpload = extractFilesFromIntent(data, main, remainingCount);
              if (filesToUpload.length) {
                await uploadFiles(filesToUpload);
              }
              cleanup();
              resolve();
            } catch (error) {
              cleanup();
              reject(error);
            }
          } else {
            cleanup();
            reject(new Error('用户取消选择'));
          }
        } else {
          cleanup();
          reject(new Error('无效的请求'));
        }
      };

      const cleanup = () => {
        if (originalOnActivityResult) {
          main.onActivityResult = originalOnActivityResult;
        }
      };
    } catch (error) {
      reject(error);
    }
  });
};

const extractFilesFromIntent = (data, main, remainingCount) => {
  const clipData = data.getClipData();
  const filesToUpload = [];

  const getFileName = (uri) => {
    try {
      const cursor = main.getContentResolver().query(uri, null, null, null, null);
      if (cursor && cursor.moveToFirst()) {
        const nameIndex = cursor.getColumnIndex('_display_name');
        if (nameIndex !== -1) {
          const fileName = cursor.getString(nameIndex);
          cursor.close();
          return fileName;
        }
        cursor.close();
      }
    } catch (e) {
      console.error('获取文件名失败:', e);
    }
    return `file_${Date.now()}`;
  };

  if (clipData) {
    const count = clipData.getItemCount();
    for (let i = 0; i < count && filesToUpload.length < remainingCount; i++) {
      const item = clipData.getItemAt(i);
      const uri = item.getUri();
      const uriString = uri.toString();
      const fileName = getFileName(uri);
      filesToUpload.push({
        name: fileName,
        path: uriString,
        size: 0
      });
    }
  } else {
    const uri = data.getData();
    if (uri) {
      const uriString = uri.toString();
      const fileName = getFileName(uri);
      filesToUpload.push({
        name: fileName,
        path: uriString,
        size: 0
      });
    }
  }

  return filesToUpload;
};

const uploadFiles = async (fileList) => {
  if (!fileList.length) return;

  try {
    uni.showLoading({
      title: '上传中...',
      mask: true
    });

    const uploadResults = await batchUploadFilesToQiniu(fileList);
    const newFiles = uploadResults.map(result => ({
      name: result.name,
      path: result.url,
      size: result.size || 0
    }));

    files.value = [...files.value, ...newFiles];
    uni.showToast({
      title: `成功添加${newFiles.length}个文件`,
      icon: 'success'
    });
  } catch (error) {
    console.error('上传文件失败:', error);
    uni.showToast({
      title: error?.message || '上传文件失败',
      icon: 'none'
    });
    throw error;
  } finally {
    uni.hideLoading();
  }
};

const removeFile = (index) => {
  const next = [...files.value];
  next.splice(index, 1);
  files.value = next;
};

const getFileIcon = (fileName) => {
  if (!fileName) return '📄';
  const ext = fileName.split('.').pop().toLowerCase();
  const iconMap = {
    pdf: '📕',
    doc: '📘',
    docx: '📘',
    xls: '📗',
    xlsx: '📗',
    ppt: '📙',
    pptx: '📙',
    txt: '📄',
    zip: '📦',
    rar: '📦',
    jpg: '🖼️',
    jpeg: '🖼️',
    png: '🖼️',
    gif: '🖼️'
  };
  return iconMap[ext] || '📄';
};

const formatFileSize = (bytes) => {
  if (!bytes || bytes === 0) return '';
  const k = 1024;
  const sizes = ['B', 'KB', 'MB', 'GB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
};

const previewFile = (file) => {
  if (!file?.path) {
    uni.showToast({
      title: '文件路径不存在',
      icon: 'none'
    });
    return;
  }

  const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
  const ext = (file.name || '').split('.').pop().toLowerCase();

  if (imageExts.includes(ext)) {
    uni.previewImage({
      urls: [file.path],
      current: file.path
    });
    return;
  }

  // #ifdef H5
  window.open(file.path, '_blank');
  // #endif

  // #ifdef APP-PLUS
  plus.runtime.openURL(file.path);
  // #endif

  // #ifndef H5 || APP-PLUS
  uni.showToast({
    title: '点击下载文件',
    icon: 'none'
  });
  uni.downloadFile({
    url: file.path,
    success: (res) => {
      if (res.statusCode === 200) {
        uni.openDocument({
          filePath: res.tempFilePath,
          success: () => {
            console.log('打开文档成功');
          },
          fail: (err) => {
            console.error('打开文档失败:', err);
            uni.showToast({
              title: '无法打开此文件',
              icon: 'none'
            });
          }
        });
      }
    },
    fail: (err) => {
      console.error('下载文件失败:', err);
      uni.showToast({
        title: '下载文件失败',
        icon: 'none'
      });
    }
  });
  // #endif
};
</script>

<style scoped lang="scss">
.attachment-block {
  margin-bottom: 12px;
}

.form-item {
  display: flex;
  align-items: center;
  padding: 16px;
  background-color: #fff;
  border-radius: 8px;
  gap: 12px;
}

.clickable-item {
  cursor: pointer;

  &:active {
    background-color: #f5f5f5;
  }
}

.form-icon {
  font-size: 20px;
  flex-shrink: 0;
}

.form-label {
  flex: 1;
  font-size: 15px;
  color: #333;
}

.arrow {
  font-size: 20px;
  color: #999;
  flex-shrink: 0;
}

.files-list {
  margin-top: 12px;
}

.file-item {
  display: flex;
  align-items: center;
  padding: 12px;
  background-color: #fff;
  border-radius: 8px;
  margin-bottom: 8px;
  gap: 12px;

  &:active {
    background-color: #f5f5f5;
  }
}

.file-icon {
  font-size: 24px;
  flex-shrink: 0;
}

.file-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.file-name {
  font-size: 14px;
  color: #333;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
}

.file-size {
  font-size: 12px;
  color: #999;
}

.remove-btn {
  width: 24px;
  height: 24px;
  background-color: rgba(0, 0, 0, 0.6);
  color: #fff;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  cursor: pointer;
}
</style>

