<template>
  <div>
    <div class="flex flex-wrap">
      <template v-if="limit == 1">
        <div
          class="rounded cursor-pointer overflow-hidden relative border border-solid border-color image-wrap mr-[10px]"
          :class="{ 'rounded-full': type == 'avatar' }"
          :style="style"
        >
          <div class="w-full h-full relative" v-if="imagesData && imagesData.length > 0 && imagesData[0] != ''">
            <div class="w-full h-full flex items-center justify-center">
              <el-image class="w-full h-full" :src="imagesData[0].indexOf('data:image') != -1 ? imagesData[0] : img(imagesData[0])"></el-image>
            </div>
            <!-- 悬停操作层 -->
            <div class="absolute z-[1] flex items-center justify-center w-full h-full inset-0 bg-black bg-opacity-60 operation">
              <div class="index-badge">1</div>
            
              <span class="op-text mr-[10px]" @click.stop="previewImage(imagesData, 0)">预览</span>
              <span class="op-text op-delete" @click.stop="removeImage">删除</span>
            </div>
          </div>
          <div class="w-full h-full flex items-center justify-center flex-col content-wrap" v-else @click="openDialog">
            <icon name="element Plus" size="20px" color="var(--el-text-color-secondary)" />
            <div class="leading-none text-xs mt-[10px] text-secondary">{{ imageText || '上传图片' }}</div>
          </div>
        </div>
      </template>
      <template v-else>
        <div class="flex flex-wrap" ref="imgListRef">
          <template v-for="(item, index) in imagesData" :key="item + index">
            <div
              v-if="item && item != ''"
              class="rounded cursor-pointer overflow-hidden relative border border-solid border-color image-wrap mr-[10px] mb-[10px]"
              :style="style"
            >
              <div class="w-full h-full relative">
                <div class="w-full h-full flex items-center justify-center">
                  <el-image :src="img(item)" fit="contain"></el-image>
                </div>
                <!-- 悬停操作层 -->
                <div class="absolute z-[1] flex flex-col items-center justify-center w-full h-full inset-0 bg-black bg-opacity-60 operation">
                  <div class="index-badge">{{ index + 1 }}</div>
                  <div class="flex items-center justify-center mb-[6px]">
                    <span class="op-text mr-[10px]" @click.stop="previewImage(imagesData, index)">预览</span>
                    <span class="op-text op-delete" @click.stop="removeImage(index)">删除</span>
                  </div>
                  <div class="flex items-center justify-center gap-[8px]">
                    <el-icon
                      :size="16"
                      :style="{ color: Number(index) === 0 ? 'rgba(255,255,255,0.3)' : '#fff', cursor: Number(index) === 0 ? 'not-allowed' : 'pointer' }"
                      :title="'向左移动'"
                      @click.stop="Number(index) > 0 && moveImage(Number(index), Number(index) - 1)"
                    ><ArrowLeft /></el-icon>
                    <el-icon
                      :size="16"
                      :style="{ color: Number(index) === imagesData.length - 1 ? 'rgba(255,255,255,0.3)' : '#fff', cursor: Number(index) === imagesData.length - 1 ? 'not-allowed' : 'pointer' }"
                      :title="'向右移动'"
                      @click.stop="Number(index) < imagesData.length - 1 && moveImage(Number(index), Number(index) + 1)"
                    ><ArrowRight /></el-icon>
                  </div>
                </div>
              </div>
            </div>
          </template>
          <div
            class="rounded cursor-pointer overflow-hidden relative border border-solid border-color image-wrap mr-[10px] mb-[10px]"
            :style="style"
            v-if="imagesData.length < limit"
          >
            <div class="w-full h-full flex items-center justify-center flex-col content-wrap" @click="openDialog">
              <icon name="element Plus" size="20px" color="var(--el-text-color-secondary)" />
              <div class="leading-none text-xs mt-[10px] text-secondary">{{ imageText || '上传图片' }}</div>
            </div>
          </div>
        </div>
      </template>
    </div>
    <!-- 选择图片 -->
    <el-dialog
      v-model="dialogVisible"
      title="选择图片"
      width="1400"
      :close-on-click-modal="false"
      class="file-selector-dialog"
      :before-close="closeDialog"
    >
      <div class="dialog-bos">
        <!-- 工具栏 -->
        <div class="toolbar">
          <div class="toolbar-left">
            <el-upload
              ref="uploadRef"
              :action="uploadUrl"
              :headers="uploadHeaders"
              :before-upload="beforeUpload"
              :on-success="onUploadSuccess"
              :on-error="onUploadError"
              :show-file-list="false"
              :accept="getUploadFileAccept()"
            >
              <el-button type="primary">
                <el-icon><Plus /></el-icon>
                上传图片
              </el-button>
            </el-upload>
          </div>
          <div class="toolbar-right">
            <el-input v-model="queryParams.name" placeholder="请输入图片名称" style="width: 200px" clearable @input="handleSearch">
              <template #prefix>
                <el-icon><Search /></el-icon>
              </template>
            </el-input>
            <div class="view-toggle">
              <el-button :type="viewMode === 'grid' ? 'primary' : 'default'" size="small" @click="viewMode = 'grid'">
                <el-icon><Grid /></el-icon>
              </el-button>
              <el-button :type="viewMode === 'list' ? 'primary' : 'default'" size="small" @click="viewMode = 'list'">
                <el-icon><List /></el-icon>
              </el-button>
            </div>
          </div>
        </div>
        <div class="content-wrapper">
          <!-- 左侧分类导航 -->
          <div class="sidebar">
            <!-- 全部文件 -->
            <div @click="handleTreeNodeClick({ id: '' })" class="category-item" :class="{ active: queryParams.categoryId == '' }">
              <el-icon class="category-icon"><Folder /></el-icon>
              <span>全部图片</span>
              <el-dropdown trigger="click" @click.stop class="node-actions">
                <el-icon class="more-icon"><MoreFilled /></el-icon>
                <template #dropdown>
                  <el-dropdown-menu>
                    <el-dropdown-item @click="openClassify({}, 'add')" command="addRoot">添加分类</el-dropdown-item>
                  </el-dropdown-menu>
                </template>
              </el-dropdown>
            </div>
            <!-- 树形控件 -->
            <el-tree
              ref="categoryTreeRef"
              :data="filteredCategoryTree"
              :props="treeProps"
              :expand-on-click-node="false"
              :current-node-key="queryParams.categoryId"
              node-key="id"
              @node-click="handleTreeNodeClick"
              class="category-tree"
            >
              <template #default="{ data }">
                <div class="tree-node-content">
                  <el-icon class="category-icon"><Folder /></el-icon>
                  <span class="node-label">{{ data.name }}</span>
                  <el-dropdown trigger="click" @click.stop class="node-actions pr-[10px]">
                    <el-icon class="more-icon"><MoreFilled /></el-icon>
                    <template #dropdown>
                      <el-dropdown-menu>
                        <el-dropdown-item @click="openClassify(data, 'add')">添加分类</el-dropdown-item>
                        <el-dropdown-item @click="openClassify(data, 'edit')">编辑分类</el-dropdown-item>
                        <el-dropdown-item @click="closeClassify(data)">删除分类</el-dropdown-item>
                      </el-dropdown-menu>
                    </template>
                  </el-dropdown>
                </div>
              </template>
            </el-tree>
          </div>
          <!-- 右侧文件展示区 -->
          <div class="content-area">
            <!-- 网格视图 -->
            <div v-if="viewMode === 'grid'" class="file-grid">
              <div
                v-for="(file, index) in fileList"
                :key="index"
                class="file-item"
                :class="{
                  selected: selectedFiles.some((row: any) => row.id == file.id)
                }"
                @click="toggleFileSelection(file)"
              >
                <div class="file-wrapper">
                  <el-image :src="getImageUrl(file)" fit="cover" class="file-thumbnail" :preview-disabled="true" lazy>
                    <template #error>
                      <div class="file-error">
                        <el-icon size="24" color="#c0c4cc">
                          <Picture />
                        </el-icon>
                      </div>
                    </template>
                    <template #placeholder>
                      <div class="file-loading">
                        <el-icon size="24" color="#409eff">
                          <Loading />
                        </el-icon>
                      </div>
                    </template>
                  </el-image>
                  <div class="file-checkbox">
                    <el-checkbox :model-value="selectedFiles.some((row: any) => row.id == file.id)" />
                  </div>
                </div>
                <div class="file-info">
                  <div class="file-name">{{ file.name || file.originalName }}</div>
                  <div class="file-actions">
                    <el-button
                      link
                      size="small"
                      @click.stop="
                        previewImage(
                          fileList.map((row: any) => row.url),
                          index
                        )
                      "
                      >预览</el-button
                    >
                    <el-button link size="small" @click.stop="handleRename(file)">重命名</el-button>
                  </div>
                </div>
              </div>
            </div>
            <!-- 列表视图 -->
            <div v-else class="file-list">
              <!-- @selection-change="handleSelectionChange" -->
              <el-table height="600" v-loading="loading" :data="fileList" style="width: 100%">
                <!-- <el-table-column type="selection" width="55" /> -->
                <el-table-column label="预览" width="80">
                  <template #default="{ row }">
                    <el-image :src="getImageUrl(row)" style="width: 50px; height: 50px; border-radius: 4px" fit="cover" :preview-disabled="true" lazy>
                      <template #error>
                        <div class="list-image-error">
                          <el-icon size="20" color="#c0c4cc">
                            <Picture />
                          </el-icon>
                        </div>
                      </template>
                      <template #placeholder>
                        <div class="list-image-loading">
                          <el-icon size="20" color="#409eff">
                            <Loading />
                          </el-icon>
                        </div>
                      </template>
                    </el-image>
                  </template>
                </el-table-column>
                <el-table-column label="文件名" prop="name" min-width="200">
                  <template #default="{ row }">
                    {{ row.name || row.originalName }}
                  </template>
                </el-table-column>
                <el-table-column label="大小" width="100">
                  <template #default="{ row }">
                    {{ formatFileSize(row.size) }}
                  </template>
                </el-table-column>
                <el-table-column label="类型" prop="type" width="120" />
                <el-table-column label="上传时间" width="180">
                  <template #default="{ row }">
                    {{ formatTime(row.createTime) }}
                  </template>
                </el-table-column>
                <el-table-column label="操作" width="150" fixed="right">
                  <template #default="scope">
                    <el-button
                      link
                      @click="
                        previewImage(
                          fileList.map((row: any) => row.url),
                          scope.$index
                        )
                      "
                      >预览</el-button
                    >
                    <el-button link @click="handleRename(scope.row)">重命名</el-button>
                  </template>
                </el-table-column>
              </el-table>
            </div>
            <!-- 分页 -->
            <div class="pagination">
              <el-pagination
                v-model:current-page="queryParams.pageNum"
                v-model:page-size="queryParams.pageSize"
                :total="total"
                :page-sizes="[21, 28, 35, 42]"
                layout="total, sizes, prev, pager, next, jumper"
                @size-change="getList"
                @current-change="getList"
              />
            </div>
          </div>
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeDialog">取消</el-button>
          <el-button type="primary" @click="confirmSelection" :disabled="selectedFiles.length > 0 ? false : true">
            确认选择({{ selectedFiles.length }})
          </el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 添加编辑分类 -->
    <el-dialog v-model="classifyDialog.dialog" :title="classifyDialog.title" width="600">
      <el-form ref="categoryFormRef" :model="categoryForm" :rules="categoryRules" label-width="100px">
        <!-- 分类名称 -->
        <el-form-item label="分类名称" prop="name" required>
          <el-input v-model="categoryForm.name" placeholder="请输入分类名称" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="classifyDialog.dialog = false">取消</el-button>
          <el-button type="primary" @click="submitCategory" :loading="classifyDialog.loading">确定</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 重命名对话框 -->
    <el-dialog v-model="renameDialogVisible" title="重命名文件" width="400px" append-to-body :close-on-click-modal="false">
      <el-form ref="renameFormRef" :model="renameForm" label-width="80px">
        <el-form-item label="原文件名">
          <el-input v-model="renameForm.originalName" readonly />
        </el-form-item>
        <el-form-item
          label="新文件名"
          prop="name"
          :rules="[
            { required: true, message: '请输入新文件名', trigger: 'blur' },
            { min: 1, max: 100, message: '文件名长度在 1 到 100 个字符', trigger: 'blur' }
          ]"
        >
          <el-input v-model="renameForm.name" placeholder="请输入新文件名" />
        </el-form-item>
      </el-form>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="renameDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="submitRename">确定</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 图片放大 -->
    <el-image-viewer
      :url-list="previewImageList"
      v-if="imageViewer.show"
      @close="imageViewer.show = false"
      :initial-index="imageViewer.index"
      :zoom-rate="1"
    />
  </div>
</template>

<script lang="ts" setup>
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue';
import { img } from '@/utils/common';
import { listFileInfo, delFileInfo, addFileInfo, updateDownloadCount, updateFileInfo } from '@/api/file/info';
import { listFileCategoryTree, addFileCategory, updateFileCategory, delFileCategory } from '@/api/file/category';
import { globalHeaders } from '@/utils/request';
const props = defineProps({
  type: {
    type: String,
    default: 'image'
  },
  modelValue: {
    type: String || Array,
    default: ''
  },
  width: {
    type: String,
    default: '100px'
  },
  height: {
    type: String,
    default: '100px'
  },
  imageText: {
    type: String
  },
  limit: {
    type: Number,
    default: 1
  }
});
const imagesData = ref<any>([]);
const previewImageList = ref<any>([]);
watch(
  () => props.modelValue,
  () => {
    if (props.limit == 1) {
      imagesData.value = [props.modelValue];
    } else {
      if (Array.isArray(props.modelValue)) {
        imagesData.value = props.modelValue;
      } else {
        imagesData.value = props.modelValue.split(',');
        imagesData.value = imagesData.value.filter((item: any) => item !== '');
      }
    }
  },
  { immediate: true }
);

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

const dialogVisible = ref<any>(false);
const viewMode = ref<any>('grid');
// 图片列表
const loading = ref<any>(false);
const fileList = ref([]);
const total = ref(0);
const selectedFiles = ref([]);

// 查询参数
const queryParams = ref<any>({
  pageNum: 1,
  pageSize: 20,
  name: null,
  categoryId: '',
  categoryType: 1
});

// 分类相关数据
const filteredCategoryTree = ref<any>([]);
const categoryTreeRef = ref<any>(null);
const treeProps = {
  label: 'name',
  children: 'children'
};
const classifyDialog = ref<any>({
  dialog: false,
  title: '添加分类',
  loading: false
});
// 分类表单数据
const categoryFormRef = ref<any>(null);
const categoryForm = ref({
  id: null,
  name: '',
  code: '',
  parentId: null,
  type: 1,
  sort: 1,
  description: '',
  status: 0
});
// 分类表单验证规则
const categoryRules = ref<any>({
  name: [
    { required: true, message: '请输入分类名称', trigger: 'blur' },
    { min: 2, max: 50, message: '分类名称长度在 2 到 50 个字符', trigger: 'blur' }
  ]
});

// 重命名相关数据
const renameDialogVisible = ref(false);
const renameForm = ref({
  id: null,
  name: '',
  originalName: '',
  currentFile: null
});
const renameFormRef = ref();

// 上传配置
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + '/resource/oss/upload');
const uploadHeaders = ref(globalHeaders());
const uploadFileList = ref([]);

// 打开弹窗
const openDialog = () => {
  getCategoryTree();
  getList();
  selectedFiles.value = [];
  dialogVisible.value = true;
};

//关闭弹窗
const closeDialog = () => {
  dialogVisible.value = false;
};

//确定
const confirmSelection = () => {
  if (props.limit == 1) {
    emit('update:modelValue', selectedFiles.value[0].url);
    emit('change', selectedFiles.value[0]);
  } else {
    const result = selectedFiles.value.map((item: any) => item.url);
    let resultArray = [];
    let resultString = '';
    if (Array.isArray(props.modelValue)) {
      resultArray = [...result, ...imagesData.value];
      emit('update:modelValue', resultArray);
      emit('change', resultArray);
    } else {
      resultString = imagesData.value + ',' + result.join(',');
      emit('update:modelValue', resultString);
      emit('change', resultString);
    }
  }
  closeDialog();
};

// 搜索文件
const handleSearch = () => {
  queryParams.value.pageNum = 1;
  getList();
};

// 获取文件列表
const getList = async () => {
  try {
    loading.value = true;
    const response = (await listFileInfo(queryParams.value)) as any;
    const data = response?.data ?? response;
    if (data && data.rows) {
      fileList.value = data.rows as any[];
      total.value = data.total || 0;
    } else {
      fileList.value = [];
      total.value = 0;
    }
  } catch (error) {
    console.error('获取文件列表失败:', error);
    ElMessage.error('获取文件列表失败');
    fileList.value = [];
    total.value = 0;
  } finally {
    loading.value = false;
  }
};

const handleSelectionChange = (res: any) => {};
// 切换文件选择状态
const toggleFileSelection = (res: any) => {
  if (props.limit == 1) {
    selectedFiles.value = [res];
  } else {
    // 多选模式，实现切换逻辑
    const index = selectedFiles.value.findIndex((item: any) => item.id === res.id);
    // 计算当前总选择数量（已选文件 + 已上传图片）
    const currentTotalCount = selectedFiles.value.length + imagesData.value.length;
    if (index > -1) {
      // 如果已选中，则取消选中（删除）
      selectedFiles.value.splice(index, 1);
    } else {
      // 如果未选中，检查是否超过限制
      if (currentTotalCount >= props.limit) {
        ElMessage.warning(`最多只能选择 ${props.limit} 张图片`);
        return;
      }
      // 未超过限制，添加选中
      selectedFiles.value.push(res);
    }
  }
};

// 获取图片URL
const getImageUrl = (file) => {
  // 优先使用url字段
  if (file.url) {
    // 如果是完整的URL，直接返回
    if (file.url.startsWith('http://') || file.url.startsWith('https://')) {
      return file.url;
    }
    // 如果是相对路径，添加基础URL
    if (file.url.startsWith('/')) {
      return import.meta.env.VITE_APP_BASE_API + file.url;
    }
    return file.url;
  }

  // 备选方案：使用path字段
  if (file.path) {
    if (file.path.startsWith('http://') || file.path.startsWith('https://')) {
      return file.path;
    }
    if (file.path.startsWith('/')) {
      return import.meta.env.VITE_APP_BASE_API + file.path;
    }
    return file.path;
  }

  // 如果都没有，返回空字符串，触发错误处理
  return '';
};

// 获取分类树
const getCategoryTree = () => {
  listFileCategoryTree().then((res) => {
    if (res.code == 200) {
      if (res.data.length > 0) {
        res.data.forEach((item: any) => {
          if (item.type == 1 && item.code == 'IMAGE') {
            filteredCategoryTree.value = item.children;
          }
        });
      }
    }
  });
};

// 添加分类
const openClassify = (res: any, type: any) => {
  console.log(res, 'res');
  if (type == 'add') {
    classifyDialog.value.title = '添加分类';
    categoryForm.value.name = '';
    categoryForm.value.id = null;
    if (res.id) {
      categoryForm.value.parentId = res.id;
    } else {
      categoryForm.value.parentId = 1;
    }
  } else {
    classifyDialog.value.title = '编辑分类';
    categoryForm.value.name = res.name;
    categoryForm.value.id = res.id;
    categoryForm.value.parentId = null;
  }

  classifyDialog.value.dialog = true;
};

// 新增编辑分类
const submitCategory = async () => {
  try {
    await categoryFormRef.value?.validate();
    classifyDialog.value.loading = true;

    const categoryData = {
      ...categoryForm.value,
      tenantId: '000000'
    };

    if (categoryForm.value.id) {
      await updateFileCategory(categoryData);
    } else {
      await addFileCategory(categoryData);
    }

    ElMessage.success(categoryForm.value.id ? '更新成功' : '添加成功');
    classifyDialog.value.loading = false;
    getCategoryTree();
  } catch (error) {
    console.error('保存分类失败:', error);
    ElMessage.error('保存分类失败');
  } finally {
    classifyDialog.value.loading = false;
    classifyDialog.value.dialog = false;
  }
};

// 删除分类
const closeClassify = async (data: any) => {
  if (data.children && data.children.length > 0) {
    ElMessage.warning('该分类下有子分类，请先删除子分类');
    return;
  }
  try {
    await ElMessageBox.confirm(`确定要删除分类"${data.name}"吗？`, '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    } as any);
    await delFileCategory(data.id);
    ElMessage.success('删除成功');
    getCategoryTree();
  } catch (error) {
    if (error !== 'cancel') {
      console.error('删除分类失败:', error);
      ElMessage.error('删除分类失败');
    }
  }
};

// 树节点点击事件
const handleTreeNodeClick = (res: any) => {
  queryParams.value.categoryId = res.id;
  if (res.id == '') {
    categoryTreeRef.value.setCurrentKey(null);
  }
  handleSearch();
};

// 图片放大
const imageViewer = reactive({
  show: false,
  index: 0
});

const previewImage = (list: any, index: any) => {
  previewImageList.value = list;
  imageViewer.index = index ? index : 0;
  imageViewer.show = true;
};

/**
 * 移动图片位置
 * @param fromIndex 原位置
 * @param toIndex 目标位置
 */
const moveImage = (fromIndex: number, toIndex: number) => {
  const list = [...imagesData.value];
  const [item] = list.splice(fromIndex, 1);
  list.splice(toIndex, 0, item);
  if (Array.isArray(props.modelValue)) {
    emit('update:modelValue', list);
    emit('change', list);
  } else {
    emit('update:modelValue', list.join(','));
    emit('change', list.join(','));
  }
};

/**
 * 删除图片
 * @param index
 */
const removeImage = (index?: any) => {
  if (props.limit == 1) {
    emit('update:modelValue', '');
    emit('change', '');
  } else {
    const list = [...imagesData.value];
    list.splice(index, 1);
    if (Array.isArray(props.modelValue)) {
      emit('update:modelValue', list);
      emit('change', list);
    } else {
      emit('update:modelValue', list.join(','));
      emit('change', list.join(','));
    }
  }
};

// 重命名文件
const handleRename = (file: any) => {
  renameForm.value = {
    id: file.id,
    name: '',
    originalName: file.name || file.originalName || '',
    currentFile: file // 保存完整的文件信息
  };
  renameDialogVisible.value = true;
};

// 提交重命名
const submitRename = async () => {
  try {
    await renameFormRef.value?.validate();

    if (!renameForm.value.name.trim()) {
      ElMessage.error('请输入新文件名');
      return;
    }

    if (renameForm.value.name === renameForm.value.originalName) {
      ElMessage.warning('新文件名与原文件名相同');
      return;
    }

    // 调用重命名API
    const file = renameForm.value.currentFile;
    await updateFileInfo({
      id: renameForm.value.id,
      name: renameForm.value.name.trim(),
      originalName: file.originalName,
      path: file.path,
      url: file.url,
      size: file.size,
      type: file.type,
      extension: file.extension,
      categoryId: file.categoryId,
      description: file.description
    });

    ElMessage.success('重命名成功');
    renameDialogVisible.value = false;

    // 刷新文件列表
    handleSearch();

    console.log('重命名文件:', {
      id: renameForm.value.id,
      oldName: renameForm.value.originalName,
      newName: renameForm.value.name.trim()
    });
  } catch (error) {
    console.error('重命名失败:', error);
    ElMessage.error('重命名失败');
  }
};

// 格式化文件大小
const formatFileSize = (size) => {
  if (!size) return '0 B';
  const units = ['B', 'KB', 'MB', 'GB'];
  let index = 0;
  let fileSize = size;
  while (fileSize >= 1024 && index < units.length - 1) {
    fileSize /= 1024;
    index++;
  }
  return fileSize.toFixed(2) + ' ' + units[index];
};

// 格式化时间
const formatTime = (time) => {
  if (!time) return '';
  return new Date(time).toLocaleString();
};

// 上传前检查
const beforeUpload = (file) => {
  // 获取准确的MIME类型
  const actualMimeType = getFileMimeType(file);
  const fileName = file.name || '';
  const extension = fileName.split('.').pop()?.toLowerCase();

  let isValidType = false;
  let fileTypeText = '';

  isValidType = actualMimeType.startsWith('image/') || ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(extension);
  fileTypeText = '图片';

  if (!isValidType) {
    ElMessage.error(`只能上传${fileTypeText}文件! 检测到的文件类型: ${actualMimeType}`);
    return false;
  }

  // 检查文件大小 (50MB)
  const isLtSize = file.size / 1024 / 1024 < 50;
  if (!isLtSize) {
    ElMessage.error('上传文件大小不能超过 50MB!');
    return false;
  }

  // 非图片文件或非图片分类，直接上传
  return true;
};

// 上传成功
const onUploadSuccess = (response, file) => {
  if (response.code === 200) {
    // 获取文件MIME类型和扩展名
    const mimeType = getFileMimeType(file);
    const fileName = file.name || '';
    const extension = fileName.split('.').pop()?.toLowerCase() || '';
    const datas = {
      categoryId: queryParams.value.categoryId,
      categoryType: 1,
      description: '',
      downloadCount: 0,
      extension: extension,
      isPublic: 1,
      name: file.name,
      originalName: file.name,
      ossId: response.data?.ossId || '',
      path: response.data?.url || '',
      size: file.size,
      status: 0,
      type: mimeType,
      uploadStatus: 1,
      url: response.data?.url || '',
      viewCount: 0
    };
    addFileInfo(datas).then((res) => {
      if (res.code == 200) {
        ElMessage.success('文件上传成功');
        handleSearch();
      }
    });
  } else {
    ElMessage.error('上传失败：' + response.msg);
  }
};

// 上传失败
const onUploadError = (error) => {
  console.error('上传失败:', error);
  ElMessage.error('上传失败');
};

// 获取上传文件接受类型
const getUploadFileAccept = () => {
  return '.jpg,.jpeg,.png,.gif,.bmp,.webp';
};

// 获取文件MIME类型
const getFileMimeType = (file) => {
  // 优先使用浏览器检测的MIME类型
  if (file.type) {
    return file.type;
  }

  // 如果浏览器无法检测，根据文件扩展名推断
  const fileName = file.name || '';
  const extension = fileName.split('.').pop()?.toLowerCase();

  const mimeTypeMap = {
    // 图片类型
    'jpg': 'image/jpeg',
    'jpeg': 'image/jpeg',
    'png': 'image/png',
    'gif': 'image/gif',
    'bmp': 'image/bmp',
    'webp': 'image/webp',
    'svg': 'image/svg+xml',

    // 视频类型
    'mp4': 'video/mp4',
    'avi': 'video/x-msvideo',
    'mov': 'video/quicktime',
    'wmv': 'video/x-ms-wmv',
    'flv': 'video/x-flv',
    'mkv': 'video/x-matroska',
    'webm': 'video/webm',

    // 音频类型
    'mp3': 'audio/mpeg',
    'wav': 'audio/wav',
    'flac': 'audio/flac',
    'aac': 'audio/aac',
    'ogg': 'audio/ogg',
    'm4a': 'audio/mp4',

    // 文档类型
    'pdf': 'application/pdf',
    'doc': 'application/msword',
    'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    'xls': 'application/vnd.ms-excel',
    'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    'ppt': 'application/vnd.ms-powerpoint',
    'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
    'txt': 'text/plain',

    // 压缩文件
    'zip': 'application/zip',
    'rar': 'application/vnd.rar',
    '7z': 'application/x-7z-compressed',
    'tar': 'application/x-tar',
    'gz': 'application/gzip',

    // 其他常见类型
    'json': 'application/json',
    'xml': 'application/xml',
    'csv': 'text/csv',
    'html': 'text/html',
    'css': 'text/css',
    'js': 'application/javascript'
  };

  return mimeTypeMap[extension] || 'application/octet-stream';
};

const style = computed(() => {
  return {
    width: props.width,
    height: props.height
  };
});
</script>

<style lang="scss" scoped>
.image-wrap {
  .operation {
    display: none;
  }

  &:hover {
    .operation {
      display: flex;
    }
  }

  /* 序号角标（仅悬停展示，位于左上角） */
  .index-badge {
    position: absolute;
    top: 4px;
    left: 4px;
    z-index: 2;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 3px;
    background: rgba(0, 0, 0, 0.75);
    color: #fff;
    font-size: 11px;
    line-height: 18px;
    text-align: center;
    font-weight: 600;
    pointer-events: none;
  }

  /* 悬停操作文字按钮 */
  .op-text {
    color: #fff;
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    user-select: none;

    &:hover {
      opacity: 0.85;
    }
  }

  .op-delete {
    color: #ff7875;

    &:hover {
      color: #f56c6c;
    }
  }
}
.border-color {
  border-color: #e5e7eb;
}

.dialog-bos {
  height: 750px;
  background: #f5f7fa;
  padding: 10px;
  border-radius: 0 0 8px 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  margin-left: 0px !important;
  display: flex;
  flex-direction: column;
  .toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
    padding: 16px 20px;
    background: white;
    .toolbar-left {
      display: flex;
      align-items: center;
      gap: 12px;
    }
    .toolbar-right {
      display: flex;
      align-items: center;
      gap: 12px;
      .view-toggle {
        display: flex;
        gap: 0;
      }
    }
  }
  .content-wrapper {
    display: flex;
    gap: 20px;
    height: 0;
    flex: 1;
    .sidebar {
      width: 280px;
      background: white;
      border-radius: 8px;
      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
      overflow: auto;
      display: flex;
      flex-direction: column;
      height: 100%;
      padding: 10px;
      .category-item {
        display: flex;
        align-items: center;
        padding: 0px 15px;
        border-radius: 6px;
        cursor: pointer;
        margin-bottom: 8px;
        background: #f5f7fa;
        transition: background-color 0.3s;
        height: 40px;
        .category-icon {
          margin-right: 10px;
          font-size: 18px;
        }
        &.active {
          background: #409eff;
          color: white;
          .more-icon {
            color: rgba(255, 255, 255, 0.8);
            &:hover {
              color: white;
              background: rgba(255, 255, 255, 0.2);
            }
          }
        }
      }
      /* 树形控件样式 */
      .category-tree {
        background: transparent;
        :deep(.el-tree-node__content) {
          height: 40px;
          border-radius: 6px;
          margin-bottom: 4px;
          background: #f5f7fa;
          transition: background-color 0.3s;
        }
        :deep(.el-tree-node__content:hover) {
          background: #ebeef5;
        }
        :deep(.el-tree-node.is-current > .el-tree-node__content) {
          background: #409eff;
          color: white;
          .more-icon {
            color: rgba(255, 255, 255, 0.8);
            &:hover {
              color: white;
              background: rgba(255, 255, 255, 0.2);
            }
          }
        }
        :deep(.el-tree-node.is-current > .el-tree-node__content:hover) {
          background: #66b1ff;
        }
      }
      .tree-node-content {
        display: flex;
        align-items: center;
        width: 100%;
        padding: 0 5px;
        .category-icon {
          margin-right: 8px;
          font-size: 16px;
        }
        .node-label {
          flex: 1;
          font-size: 14px;
        }
      }
      .node-actions {
        margin-left: auto;
        .more-icon {
          font-size: 16px;
          color: #909399;
          cursor: pointer;
          transition: color 0.3s;
          border-radius: 2px;
          &:hover {
            color: #409eff;
            background: rgba(64, 158, 255, 0.1);
          }
        }
      }
    }

    .content-area {
      flex: 1;
      display: flex;
      flex-direction: column;
      height: 100%;
      overflow: hidden;
      .file-grid {
        display: flex;
        flex-wrap: wrap;
        gap: 15px 10px;
        padding: 10px;
        flex: 1;
        overflow-y: auto;
        min-height: 0;
        .file-item {
          flex: 0 0 calc((100% - 30px) / 4);
          overflow: hidden;
          position: relative;
          cursor: pointer;
          border: 1px solid #ebeef5;
          border-radius: 8px;
          box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
          transition:
            transform 0.3s ease,
            box-shadow 0.3s ease;
          height: 223px;
          &:hover {
            transform: translateY(-5px);
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
          }
          &.selected {
            border: 2px solid #409eff;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
          }
          .file-wrapper {
            position: relative;
            width: 100%;
            height: 150px; /* Fixed height for grid view */
            overflow: hidden;
            .file-thumbnail {
              width: 100%;
              height: 100%;
              object-fit: cover;
              .file-error {
                display: flex;
                justify-content: center;
                align-items: center;
                width: 100%;
                height: 100%;
                background: #f5f7fa;
                color: #c0c4cc;
              }

              .file-loading {
                display: flex;
                justify-content: center;
                align-items: center;
                width: 100%;
                height: 100%;
                background: #f0f9ff;
                color: #409eff;
              }
            }
            .file-checkbox {
              position: absolute;
              top: 8px;
              right: 8px;
              z-index: 10;
            }
          }
          .file-info {
            padding: 5px 5px 10px 5px;
            background: #f5f7fa;
            border-top: 1px solid #ebeef5;
            border-radius: 0 0 8px 8px;
            .file-name {
              font-size: 14px;
              color: #303133;
              overflow: hidden;
              text-overflow: ellipsis;
              white-space: nowrap;
              margin-bottom: 5px;
            }
            .file-actions {
              display: flex;
              justify-content: space-around;
              gap: 8px;
            }
          }
        }
      }
    }

    .pagination {
      display: flex;
      justify-content: center;
      padding: 10px;
      background: white;
      flex-shrink: 0;
    }
  }
}
</style>
