<template>
  <!-- Cover 模式 - 封面图片上传 -->
  <div v-if="!asDialog && listType === 'cover'" class="upload-cover-container">
    <!-- 已上传的封面 -->
    <div v-if="props.coverUrl" class="cover-image-wrapper">
      <img 
        :src="FILE_DOWNLOAD_URL + props.coverUrl" 
        class="cover-image"
        :class="coverImageClass"
        @load="handleCoverImageLoad"
      />
      <div class="cover-actions">
        <el-button
          type="danger"
          size="small"
          circle
          :icon="Delete"
          @click="handleRemoveCover"
          class="delete-btn"
        />
      </div>
    </div>
    
    <!-- 上传区域 -->
    <div
      v-else
      class="upload-cover-area"
      :class="{ 'is-dragover': isDragover, 'is-disabled': uploading }"
      @click="handleClickUpload"
      @drop.prevent="handleDrop"
      @dragover.prevent="handleDragOver"
      @dragleave.prevent="handleDragLeave"
    >
      <el-icon v-if="!uploading" class="upload-cover-icon"><Plus /></el-icon>
      <div v-if="uploading" class="uploading-mask">
        <el-icon class="is-loading"><Loading /></el-icon>
        <div>上传中...</div>
      </div>
      <div v-if="!uploading && tip" class="upload-cover-tip">{{ tip }}</div>
    </div>

    <!-- 隐藏的文件输入框 -->
    <input
      ref="fileInputRef"
      type="file"
      :accept="accept"
      :multiple="false"
      @change="handleFileSelect"
      style="display: none"
    />
  </div>

  <!-- 默认模式 -->
  <div v-else-if="!asDialog" class="upload-container">
    <div 
      class="upload-area"
      :class="{ 'is-dragover': isDragover, 'is-disabled': uploading }"
      @click="handleClickUpload"
      @drop.prevent="handleDrop"
      @dragover.prevent="handleDragOver"
      @dragleave.prevent="handleDragLeave"
    >
      <div class="upload-icon">📁</div>
      <div class="upload-text">
        将文件拖到此处，或<span class="link-text">点击上传</span>
      </div>
      <div class="upload-tip">
        {{ tip || `支持 ${accept || '所有'} 格式，单个文件不超过 ${maxSize}MB` }}
      </div>
    </div>

    <!-- 隐藏的文件输入框 -->
    <input
      ref="fileInputRef"
      type="file"
      :accept="accept"
      :multiple="multiple"
      @change="handleFileSelect"
      style="display: none"
    />

    <!-- 文件列表 -->
    <div v-if="selectedFiles.length > 0" class="file-list">
        <div v-for="(file, index) in selectedFiles" :key="index" class="file-item">
          <!-- 文件预览 -->
          <div class="file-preview">
            <img 
              v-if="isImageFile(file)" 
              :src="getFilePreviewUrl(file)" 
              class="preview-image"
              @click="showImagePreview(file)"
            />
            <div v-else class="preview-icon">
              <span class="file-type-icon">{{ getFileTypeIcon(file) }}</span>
            </div>
          </div>
          
          <!-- 文件信息 -->
          <div class="file-info">
            <span class="file-name">{{ file.name }}</span>
            <span class="file-size">{{ formatFileSize(file.size) }}</span>
          </div>
          
          <!-- 操作按钮 -->
          <div class="file-actions">
            <el-button 
              type="text" 
              size="small" 
              @click="previewFile(file)"
              :disabled="uploading"
            >
              预览
            </el-button>
            <el-button 
              type="text" 
              size="small" 
              @click="removeFile(index)"
              :disabled="uploading"
            >
              删除
            </el-button>
          </div>
        </div>
      </div>

    <!-- 上传按钮 -->
    <div v-if="selectedFiles.length > 0" class="upload-actions">
      <el-button 
        type="primary" 
        @click="handleUpload" 
        :loading="uploading" 
        :disabled="selectedFiles.length === 0"
      >
        {{ uploading ? '上传中...' : '确定上传' }}
      </el-button>
    </div>
  </div>

  <el-dialog
    v-else
    v-model="visible"
    :title="title"
    width="600px"
    :close-on-click-modal="false"
    @close="handleClose"
  >
    <div class="upload-container">
      <div 
        class="upload-area"
        :class="{ 'is-dragover': isDragover, 'is-disabled': uploading }"
        @click="handleClickUpload"
        @drop.prevent="handleDrop"
        @dragover.prevent="handleDragOver"
        @dragleave.prevent="handleDragLeave"
      >
        <div class="upload-icon">📁</div>
        <div class="upload-text">
          将文件拖到此处，或<span class="link-text">点击上传</span>
        </div>
        <div class="upload-tip">
          {{ tip || `支持 ${accept || '所有'} 格式，单个文件不超过 ${maxSize}MB` }}
        </div>
      </div>

      <!-- 隐藏的文件输入框 -->
      <input
        ref="fileInputRef"
        type="file"
        :accept="accept"
        :multiple="multiple"
        @change="handleFileSelect"
        style="display: none"
      />

      <!-- 文件列表 -->
      <div v-if="selectedFiles.length > 0" class="file-list">
        <div v-for="(file, index) in selectedFiles" :key="index" class="file-item">
          <!-- 文件预览 -->
          <div class="file-preview">
            <img 
              v-if="isImageFile(file)" 
              :src="getFilePreviewUrl(file)" 
              class="preview-image"
              @click="showImagePreview(file)"
            />
            <div v-else class="preview-icon">
              <span class="file-type-icon">{{ getFileTypeIcon(file) }}</span>
            </div>
          </div>
          
          <!-- 文件信息 -->
          <div class="file-info">
            <span class="file-name">{{ file.name }}</span>
            <span class="file-size">{{ formatFileSize(file.size) }}</span>
          </div>
          
          <!-- 操作按钮 -->
          <div class="file-actions">
            <el-button 
              type="text" 
              size="small" 
              @click="previewFile(file)"
              :disabled="uploading"
            >
              预览
            </el-button>
            <el-button 
              type="text" 
              size="small" 
              @click="removeFile(index)"
              :disabled="uploading"
            >
              删除
            </el-button>
          </div>
        </div>
      </div>
    </div>

    <template #footer>
      <el-button @click="handleClose" :disabled="uploading">取消</el-button>
      <el-button 
        type="primary" 
        @click="handleUpload" 
        :loading="uploading" 
        :disabled="selectedFiles.length === 0"
      >
        {{ uploading ? '上传中...' : '确定上传' }}
      </el-button>
    </template>
  </el-dialog>

  <!-- 图片预览对话框 -->
  <el-dialog
    v-model="imagePreviewVisible"
    title="图片预览"
    width="80%"
    :close-on-click-modal="false"
  >
    <div class="image-preview-container">
      <img :src="previewImageUrl" class="preview-large-image" />
    </div>
  </el-dialog>

  <!-- 文件预览对话框 -->
  <el-dialog
    v-model="filePreviewVisible"
    title="文件预览"
    width="80%"
    :close-on-click-modal="false"
  >
    <div class="file-preview-container">
      <div v-if="previewFileType === 'image'" class="image-preview">
        <img :src="previewFileUrl" class="preview-large-image" />
      </div>
      <div v-else-if="previewFileType === 'text'" class="text-preview">
        <pre>{{ previewTextContent }}</pre>
      </div>
      <div v-else class="unsupported-preview">
        <div class="preview-icon-large">
          <span class="file-type-icon-large">{{ currentPreviewFile ? getFileTypeIcon(currentPreviewFile) : '📄' }}</span>
        </div>
        <p>该文件类型不支持预览</p>
        <p>文件名：{{ currentPreviewFile?.name }}</p>
        <p>文件大小：{{ currentPreviewFile ? formatFileSize(currentPreviewFile.size) : '' }}</p>
      </div>
    </div>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue';
import { ElDialog, ElButton, ElMessage, ElIcon } from 'element-plus';
import { Plus, Delete, Loading } from '@element-plus/icons-vue';
import { fileApi } from '@/apis/system/file';
import { FILE_DOWNLOAD_URL } from '@/config';
import type { SysFile } from '@/types';

interface Props {
  modelValue?: boolean;
  title?: string;
  accept?: string;
  maxSize?: number; // MB
  multiple?: boolean;
  module?: string;
  businessId?: string;
  tip?: string;
  asDialog?: boolean; // 是否作为弹窗使用
  listType?: 'default' | 'cover'; // 列表类型：default-默认, cover-封面
  coverUrl?: string; // 封面图片URL（用于cover模式）
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: false,
  title: '上传文件',
  accept: '',
  maxSize: 10,
  multiple: false,
  module: 'common',
  tip: '',
  asDialog: true,
  listType: 'default',
  coverUrl: ''
});

const emit = defineEmits<{
  'update:modelValue': [value: boolean];
  'update:coverUrl': [url: string];
  'success': [files: SysFile[]];
  'error': [error: any];
  'remove': [];
}>();

const fileInputRef = ref<HTMLInputElement>();
const selectedFiles = ref<File[]>([]);
const uploading = ref(false);
const isDragover = ref(false);

const visible = computed({
  get: () => props.asDialog ? props.modelValue : false,
  set: (val) => props.asDialog ? emit('update:modelValue', val) : undefined
});

// cover图片的宽高比类
const coverImageClass = ref('');

// 处理封面图片加载
function handleCoverImageLoad(event: Event) {
  const img = event.target as HTMLImageElement;
  const width = img.naturalWidth;
  const height = img.naturalHeight;
  
  // 如果宽度大于高度，横向图片，设置width: 100%
  if (width > height) {
    coverImageClass.value = 'cover-image-horizontal';
  } else {
    // 纵向图片，设置height: 100%
    coverImageClass.value = 'cover-image-vertical';
  }
}

// 预览相关
const imagePreviewVisible = ref(false);
const filePreviewVisible = ref(false);
const previewImageUrl = ref('');
const previewFileUrl = ref('');
const previewFileType = ref('');
const previewTextContent = ref('');
const currentPreviewFile = ref<File | null>(null);

// 点击上传区域
function handleClickUpload() {
  if (uploading.value) return;
  fileInputRef.value?.click();
}

// 文件选择
function handleFileSelect(event: Event) {
  const input = event.target as HTMLInputElement;
  if (input.files && input.files.length > 0) {
    addFiles(Array.from(input.files));
    // 清空 input，允许重复选择同一文件
    input.value = '';
    
    // cover模式下选择文件后立即上传
    if (props.listType === 'cover') {
      handleUpload();
    }
  }
}

// 拖拽相关
function handleDragOver() {
  isDragover.value = true;
}

function handleDragLeave() {
  isDragover.value = false;
}

function handleDrop(event: DragEvent) {
  isDragover.value = false;
  if (uploading.value) return;
  
  const files = event.dataTransfer?.files;
  if (files && files.length > 0) {
    addFiles(Array.from(files));
  }
}

// 添加文件
function addFiles(files: File[]) {
  files.forEach(file => {
    // 验证文件大小
    if (file.size / 1024 / 1024 > props.maxSize) {
      ElMessage.error(`文件 ${file.name} 大小超过 ${props.maxSize}MB`);
      return;
    }
    
    // 验证文件类型
    if (props.accept && !isValidFileType(file, props.accept)) {
      ElMessage.error(`文件 ${file.name} 类型不符合要求`);
      return;
    }
    
    // 检查是否重复
    if (selectedFiles.value.some(f => f.name === file.name && f.size === file.size)) {
      ElMessage.warning(`文件 ${file.name} 已添加`);
      return;
    }
    
    // 如果不允许多选，清空之前的文件
    if (!props.multiple) {
      selectedFiles.value = [file];
    } else {
      selectedFiles.value.push(file);
    }
  });
}

// 验证文件类型
function isValidFileType(file: File, accept: string): boolean {
  if (!accept) return true;
  
  const acceptTypes = accept.split(',').map(t => t.trim());
  return acceptTypes.some(type => {
    if (type.startsWith('.')) {
      return file.name.toLowerCase().endsWith(type.toLowerCase());
    } else if (type.endsWith('/*')) {
      return file.type.startsWith(type.replace('/*', ''));
    } else {
      return file.type === type;
    }
  });
}

// 移除文件
function removeFile(index: number) {
  selectedFiles.value.splice(index, 1);
}

// 格式化文件大小
function formatFileSize(bytes: number): string {
  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 (bytes / Math.pow(k, i)).toFixed(2) + ' ' + sizes[i];
}

// 判断是否为图片文件
function isImageFile(file: File): boolean {
  return file.type.startsWith('image/');
}

// 获取文件预览URL
function getFilePreviewUrl(file: File): string {
  return URL.createObjectURL(file);
}

// 获取文件类型图标
function getFileTypeIcon(file: File): string {
  const extension = file.name.split('.').pop()?.toLowerCase();
  const iconMap: Record<string, string> = {
    'pdf': '📄',
    'doc': '📝',
    'docx': '📝',
    'txt': '📄',
    'zip': '📦',
    'rar': '📦',
    'mp4': '🎬',
    'avi': '🎬',
    'mp3': '🎵',
    'wav': '🎵',
    'xls': '📊',
    'xlsx': '📊',
    'ppt': '📊',
    'pptx': '📊'
  };
  return iconMap[extension || ''] || '📄';
}

// 显示图片预览
function showImagePreview(file: File) {
  previewImageUrl.value = getFilePreviewUrl(file);
  imagePreviewVisible.value = true;
}

// 预览文件
async function previewFile(file: File) {
  currentPreviewFile.value = file;
  previewFileUrl.value = getFilePreviewUrl(file);
  
  if (isImageFile(file)) {
    previewFileType.value = 'image';
  } else if (file.type.startsWith('text/')) {
    previewFileType.value = 'text';
    try {
      previewTextContent.value = await file.text();
    } catch (error) {
      previewTextContent.value = '无法读取文件内容';
    }
  } else {
    previewFileType.value = 'unsupported';
  }
  
  filePreviewVisible.value = true;
}

// 上传文件
async function handleUpload() {
  if (selectedFiles.value.length === 0) {
    ElMessage.warning('请选择文件');
    return;
  }
  
  uploading.value = true;
  const uploadedFilesList: SysFile[] = [];
  
  try {
    // 逐个上传文件
    for (const file of selectedFiles.value) {
      const result = await fileApi.uploadFile({
        file: file,
        module: props.module,
        businessId: props.businessId
      });
      
      if (result.code === 200 && result.data) {
        uploadedFilesList.push(result.data);
        
        // cover模式下不显示成功提示
        if (props.listType !== 'cover') {
          ElMessage.success(`${file.name} 上传成功`);
        }
      } else {
        ElMessage.error(`${file.name} 上传失败: ${result.message}`);
      }
    }
    
    // 所有文件上传完成
    if (uploadedFilesList.length > 0) {
      emit('success', uploadedFilesList);
      
      // cover模式下更新coverUrl（只返回fileID，不拼接URL）
      if (props.listType === 'cover' && uploadedFilesList[0]) {
        emit('update:coverUrl', uploadedFilesList[0].fileID || '');
      }
    }
  } catch (error: any) {
    console.error('上传失败:', error);
    ElMessage.error('上传失败: ' + (error.message || '未知错误'));
    emit('error', error);
  } finally {
    uploading.value = false;
    
    // cover模式下清空选择的文件
    if (props.listType === 'cover') {
      selectedFiles.value = [];
    } else if (uploadedFilesList.length > 0) {
      // 其他模式上传完成后关闭对话框
      handleClose();
    }
  }
}

// 删除封面
function handleRemoveCover() {
  emit('update:coverUrl', '');
  coverImageClass.value = '';
  emit('remove');
}

// 关闭对话框
function handleClose() {
  if (props.asDialog) {
    visible.value = false;
  }
  selectedFiles.value = [];
  isDragover.value = false;
  uploading.value = false;
}

// 打开对话框
function open() {
  if (props.asDialog) {
    visible.value = true;
  }
}

defineExpose({
  open
});
</script>

<style lang="scss" scoped>
.upload-container {
  padding: 20px 0;
}

.upload-area {
  border: 2px dashed #dcdfe6;
  border-radius: 8px;
  padding: 60px 20px;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s;
  background: #fafafa;
  
  &:hover {
    border-color: #409eff;
    background: #f0f9ff;
  }
  
  &.is-dragover {
    border-color: #409eff;
    background: #e6f7ff;
  }
  
  &.is-disabled {
    cursor: not-allowed;
    opacity: 0.6;
  }
}

.upload-icon {
  font-size: 67px;
  margin-bottom: 16px;
  display: block;
}

.upload-text {
  color: #606266;
  font-size: 14px;
  margin-bottom: 8px;
  
  .link-text {
    color: #409eff;
    margin-left: 4px;
  }
}

.upload-tip {
  color: #909399;
  font-size: 12px;
}

.file-list {
  margin-top: 20px;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  overflow: hidden;
}

.file-item {
  display: flex;
  align-items: center;
  padding: 12px 16px;
  border-bottom: 1px solid #ebeef5;
  transition: background 0.2s;
  
  &:last-child {
    border-bottom: none;
  }
  
  &:hover {
    background: #f5f7fa;
  }
}

.file-name {
  flex: 1;
  color: #606266;
  font-size: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-right: 12px;
}

.file-size {
  color: #909399;
  font-size: 12px;
  margin-right: 12px;
}

.file-preview {
  width: 60px;
  height: 60px;
  margin-right: 12px;
  border-radius: 4px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f5f7fa;
  flex-shrink: 0;
  
  .preview-image {
    width: 100%;
    height: 100%;
    object-fit: cover;
    cursor: pointer;
    
    &:hover {
      opacity: 0.8;
    }
  }
  
  .preview-icon {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    
    .file-type-icon {
      font-size: 24px;
    }
  }
}

.file-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  
  .file-name {
    color: #606266;
    font-size: 14px;
    margin-bottom: 4px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  
  .file-size {
    color: #909399;
    font-size: 12px;
  }
}

.file-actions {
  display: flex;
  gap: 8px;
  margin-left: 12px;
}

.image-preview-container {
  text-align: center;
  padding: 20px;
  
  .preview-large-image {
    max-width: 100%;
    max-height: 70vh;
    border-radius: 4px;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  }
}

.file-preview-container {
  min-height: 300px;
  
  .image-preview {
    text-align: center;
    padding: 20px;
    
    .preview-large-image {
      max-width: 100%;
      max-height: 70vh;
      border-radius: 4px;
      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
    }
  }
  
  .text-preview {
    pre {
      background: #f5f7fa;
      padding: 16px;
      border-radius: 4px;
      max-height: 60vh;
      overflow: auto;
      white-space: pre-wrap;
      word-wrap: break-word;
      font-family: 'Courier New', monospace;
      font-size: 14px;
      line-height: 1.5;
    }
  }
  
  .unsupported-preview {
    text-align: center;
    padding: 40px;
    
    .preview-icon-large {
      margin-bottom: 16px;
      
      .file-type-icon-large {
        font-size: 64px;
      }
    }
    
    p {
      margin: 8px 0;
      color: #606266;
      font-size: 14px;
    }
  }
}

.upload-actions {
  margin-top: 16px;
  text-align: center;
}

/* Cover模式样式 */
.upload-cover-container {
  display: inline-block;
}

.cover-image-wrapper {
  position: relative;
  width: 200px;
  height: 150px;
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f5f7fa;
  
  &:hover .cover-actions {
    opacity: 1;
  }
}

.cover-image {
  display: block;
  object-fit: contain;
  max-width: 100%;
  max-height: 100%;
  
  &.cover-image-horizontal {
    width: 100%;
    height: auto;
  }
  
  &.cover-image-vertical {
    height: 100%;
    width: auto;
  }
}

.cover-actions {
  position: absolute;
  top: 8px;
  right: 8px;
  opacity: 0;
  transition: opacity 0.3s;
  
  .delete-btn {
    background: rgba(0, 0, 0, 0.6);
    border: none;
    
    &:hover {
      background: rgba(0, 0, 0, 0.8);
    }
  }
}

.upload-cover-area {
  width: 200px;
  height: 150px;
  border: 2px dashed #dcdfe6;
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  background: #fafafa;
  transition: all 0.3s;
  position: relative;
  
  &:hover {
    border-color: #409eff;
    background: #f0f9ff;
  }
  
  &.is-dragover {
    border-color: #409eff;
    background: #e6f7ff;
  }
  
  &.is-disabled {
    cursor: not-allowed;
    opacity: 0.6;
  }
}

.upload-cover-icon {
  font-size: 32px;
  color: #8c939d;
  margin-bottom: 8px;
}

.upload-cover-tip {
  font-size: 12px;
  color: #909399;
  text-align: center;
  padding: 0 10px;
  margin-top: 8px;
}

.uploading-mask {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.9);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  
  .el-icon {
    font-size: 32px;
    color: #409eff;
    margin-bottom: 8px;
  }
  
  div {
    font-size: 14px;
    color: #606266;
  }
}
</style>
