<template>
  <FullWidthLayout :show-padding="false" class="material-list-layout">
    <div class="material-list-container">
    <!-- 左侧分组面板 - 仅混剪素材显示 -->
    <transition name="sidebar-slide">
      <div class="material-sidebar" v-show="activeCategory === 'MIX'">
        <!-- 分组列表 -->
        <div class="sidebar-section">
          <div class="sidebar-section__header">
            <span>分组</span>
            <a-button type="link" size="small" @click="handleOpenCreateGroupModal">
              <PlusOutlined />
            </a-button>
          </div>
          <div class="sidebar-group-list">
            <div
              v-for="group in groupList"
              :key="group.id"
              class="sidebar-group-item"
              :class="{ 'sidebar-group-item--active': selectedGroupId === group.id }"
              @click="handleSelectGroup(group)"
            >
              <div class="sidebar-group-item__content">
                <FolderOutlined class="sidebar-group-item__icon" />
                <template v-if="editingGroupId !== group.id">
                  <span class="sidebar-group-item__name">{{ group.name }}</span>
                </template>
                <template v-else>
                  <a-input
                    v-model:value="editingGroupName"
                    size="small"
                    class="sidebar-group-item__edit-input"
                    @blur="handleSaveGroupName(group)"
                    @press-enter="handleSaveGroupName(group)"
                    @click.stop
                    autofocus
                  />
                </template>
              </div>
              <div class="sidebar-group-item__actions">
                <template v-if="editingGroupId !== group.id">
                  <span class="sidebar-group-item__count">{{ group.fileCount }}</span>
                  <EditOutlined
                    class="sidebar-group-item__action-btn"
                    @click.stop="handleEditGroup(group, $event)"
                  />
                  <DeleteOutlined
                    class="sidebar-group-item__action-btn sidebar-group-item__action-btn--danger"
                    @click.stop="handleDeleteGroup(group, $event)"
                  />
                </template>
              </div>
            </div>
          </div>
        </div>
      </div>
    </transition>

    <!-- 右侧内容区域 -->
    <div class="material-content">
      <!-- 顶部工具栏 -->
      <div class="material-toolbar">
        <!-- 分类切换器 -->
        <div class="category-switcher">
          <div
            class="category-switcher__item"
            :class="{ 'category-switcher__item--active': activeCategory === 'MIX' }"
            @click="handleCategoryChange('MIX')"
          >
            <VideoCameraOutlined class="category-switcher__icon" />
            <span>混剪素材</span>
          </div>
          <div
            class="category-switcher__item"
            :class="{ 'category-switcher__item--active': activeCategory === 'DIGITAL_HUMAN' }"
            @click="handleCategoryChange('DIGITAL_HUMAN')"
          >
            <UserOutlined class="category-switcher__icon" />
            <span>数字人素材</span>
          </div>
        </div>

        <!-- 搜索和操作区 -->
        <div class="toolbar-actions">
          <!-- 存储配额显示 -->
          <div class="storage-quota">
            <span class="storage-quota__label">存储空间</span>
            <span class="storage-quota__value">{{ userStore.usedStorage.toFixed(2) }} / {{ userStore.totalStorage }} GB</span>
            <div class="storage-quota__bar">
              <div class="storage-quota__used" :style="{ width: `${Math.min((userStore.usedStorage / userStore.totalStorage) * 100, 100)}%` }"></div>
            </div>
          </div>
          <a-input
            v-model="searchKeyword"
            placeholder="搜索文件名..."
            class="search-input"
            allow-clear
            @press-enter="handleSearch"
          >
            <template #prefix>
              <SearchOutlined />
            </template>
          </a-input>
          <a-button type="primary" class="upload-btn" @click="handleOpenUploadModal">
            <UploadOutlined />
            上传
          </a-button>
        </div>
      </div>

      <!-- 批量操作栏 -->
      <transition name="fade-slide">
        <div class="batch-actions" v-if="selectedFileIds.length > 0">
          <div class="batch-actions__info">
            <CheckSquareOutlined />
            <span>已选择 <strong>{{ selectedFileIds.length }}</strong> 个文件</span>
          </div>
          <div class="batch-actions__btns">
            <a-button size="small" @click="selectedFileIds = []">取消选择</a-button>
            <a-button type="primary" danger size="small" @click="handleBatchDelete">
              <DeleteOutlined /> 删除
            </a-button>
          </div>
        </div>
      </transition>

      <!-- 文件列表 -->
      <div class="material-content__list">
        <a-spin :spinning="loading" tip="加载中..." class="loading-spinner">
          <template v-if="fileList.length > 0">
            <div class="material-grid">
              <div
                v-for="file in fileList"
                :key="file.id"
                :data-file-id="file.id"
                class="material-item"
                :class="{ 'material-item--selected': selectedFileIds.includes(file.id) }"
                @click="handleFileClick(file)"
              >
                <!-- 选择指示器 -->
                <div class="material-item__check">
                  <div class="check-circle" :class="{ 'check-circle--checked': selectedFileIds.includes(file.id) }">
                    <CheckOutlined v-if="selectedFileIds.includes(file.id)" />
                  </div>
                </div>

                <!-- 预览图 -->
                <div class="material-item__preview">
                  <img
                    v-if="file.coverBase64"
                    :src="file.coverBase64"
                    :alt="file.fileName"
                    @error="handleImageError"
                    loading="lazy"
                  />
                  <div v-else class="material-item__preview-placeholder">
                    <FileOutlined />
                  </div>
                  <div class="material-item__overlay">
                    <span class="material-item__type-tag">{{ getFileTypeText(file.fileName) }}</span>
                  </div>
                </div>

                <!-- 文件信息 -->
                <div class="material-item__info">
                  <div
                    class="material-item__name"
                    :title="file.displayName"
                    @click.stop="handleEditName(file)"
                  >
                    <template v-if="editingFileId !== file.id">
                      {{ file.displayName }}
                    </template>
                    <template v-else>
                      <a-input
                        ref="nameInputRef"
                        v-model:value="editingDisplayName"
                        size="small"
                        @blur="handleSaveName(file)"
                        @press-enter="handleSaveName(file)"
                        @click.stop
                        autofocus
                      />
                    </template>
                  </div>
                  <div class="material-item__meta">
                    <span>{{ formatFileSize(file.fileSize) }}</span>
                    <span class="meta-dot">·</span>
                    <span>{{ formatDate(file.createTime) }}</span>
                  </div>
                </div>
              </div>
            </div>
          </template>
          <div v-else class="empty-state">
            <div class="empty-state__icon">
              <FolderOpenOutlined />
            </div>
            <p class="empty-state__text">暂无素材</p>
            <a-button type="primary" @click="handleOpenUploadModal">
              <UploadOutlined /> 上传素材
            </a-button>
          </div>
        </a-spin>
      </div>

      <!-- 底部操作栏 -->
      <div class="material-footer">
        <div class="footer-left">
          <a-checkbox
            :checked="selectedFileIds.length === fileList.length && fileList.length > 0"
            :indeterminate="selectedFileIds.length > 0 && selectedFileIds.length < fileList.length"
            @change="handleSelectAll"
          >
            全选
          </a-checkbox>
          <span class="footer-count" v-if="pagination.total > 0">
            共 {{ pagination.total }} 个文件
          </span>
        </div>
        <a-pagination
          v-model:current="pagination.current"
          v-model:page-size="pagination.pageSize"
          :total="pagination.total"
          :show-size-changer="true"
          :show-quick-jumper="true"
          :show-total="false"
          size="small"
          @change="handlePageChange"
          @show-size-change="handlePageSizeChange"
        />
      </div>
    </div>

    <!-- 上传素材弹窗 -->
    <MaterialUploadModal
      v-model:visible="uploadModalVisible"
      :group-id="selectedGroupId"
      :uploading="uploadLoading"
      @confirm="handleFileUpload"
    />

    <!-- 新建分组弹窗 -->
    <a-modal
      v-model:visible="createGroupModalVisible"
      title="新建分组"
      @ok="handleCreateGroup"
      @cancel="createGroupModalVisible = false"
    >
      <a-form :model="createGroupForm" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
        <a-form-item label="分组名称" name="name" :rules="[{ required: true, message: '请输入分组名称' }]">
          <a-input v-model:value="createGroupForm.name" placeholder="请输入分组名称" />
        </a-form-item>
        <a-form-item label="分组描述">
          <a-textarea v-model:value="createGroupForm.description" placeholder="请输入分组描述（可选）" />
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
  </FullWidthLayout>
</template>

<script setup>
import { ref, reactive, onMounted, watch, nextTick } from 'vue';
import {
  UploadOutlined,
  SearchOutlined,
  FileOutlined,
  FolderOutlined,
  FolderOpenOutlined,
  PlusOutlined,
  EditOutlined,
  DeleteOutlined,
  VideoCameraOutlined,
  UserOutlined,
  CheckOutlined,
  CheckSquareOutlined
} from '@ant-design/icons-vue';
import { message, Modal } from 'ant-design-vue';
import MaterialUploadModal from '@/components/material/MaterialUploadModal.vue';
import MaterialService, { MaterialGroupService } from '@/api/material';
import { useUpload } from '@/composables/useUpload';
import FullWidthLayout from '@/layouts/components/FullWidthLayout.vue';
import { useUserStore } from '@/stores/user';

// 用户状态（获取存储配额）
const userStore = useUserStore()

// 状态管理
const loading = ref(false)
const activeCategory = ref('MIX')
const selectedGroupId = ref(null)
const groupList = ref([])
const fileList = ref([])
const totalFileCount = ref(0)
const searchKeyword = ref('')

// 模态框状态
const uploadModalVisible = ref(false)
const uploadLoading = ref(false)
const createGroupModalVisible = ref(false)

// 表单数据
const createGroupForm = reactive({
  name: '',
  description: '',
  category: 'MIX'
})

// 文件选择
const selectedFileIds = ref([])

// 编辑状态
const editingFileId = ref(null)
const editingDisplayName = ref('')
const nameInputRef = ref(null)
const editingGroupId = ref(null)
const editingGroupName = ref('')

// 分页
const pagination = reactive({
  current: 1,
  pageSize: 20,
  total: 0
})

// Hooks
const { upload } = useUpload()

// 方法
const handleCategoryChange = async (category) => {
  activeCategory.value = category
  selectedGroupId.value = null
  createGroupForm.category = category

  // 混剪素材需要加载分组，数字人素材不需要
  if (category === 'MIX') {
    await loadGroupList()
  } else {
    await loadFileList()
  }
}

const handleSelectGroup = (group) => {
  // 编辑中则先保存
  if (editingGroupId.value) {
    const currentGroup = groupList.value.find(g => g.id === editingGroupId.value)
    if (currentGroup) {
      handleSaveGroupName(currentGroup)
    }
  }

  // 已是选中状态则不处理
  if (selectedGroupId.value === group.id) return

  selectedGroupId.value = group.id
  loadFileList()
}

const handleEditGroup = async (group, event) => {
  event?.stopPropagation?.()
  editingGroupId.value = group.id
  editingGroupName.value = group.name
  await nextTick()
}

const handleSaveGroupName = async (group) => {
  const newName = editingGroupName.value.trim()

  if (!newName) {
    message.warning('分组名称不能为空')
    editingGroupId.value = null
    return
  }

  if (newName === group.name) {
    editingGroupId.value = null
    return
  }

  try {
    await MaterialGroupService.updateGroup({
      id: group.id,
      name: newName,
      description: group.description || '',
      sort: group.sort || 0,
      icon: group.icon || 'folder',
      parentId: group.parentId || 0
    })

    group.name = newName
    message.success('分组重命名成功')
  } catch (error) {
    console.error('分组重命名失败:', error)
    message.error('分组重命名失败，请重试')
  } finally {
    editingGroupId.value = null
  }
}

const handleDeleteGroup = async (group, event) => {
  event?.stopPropagation?.()

  const confirmed = await new Promise((resolve) => {
    Modal.confirm({
      title: '删除分组',
      content: `确定要删除分组「${group.name}」吗？删除后该分组下的所有文件将被移动到默认分组。此操作不可恢复。`,
      okText: '确认删除',
      cancelText: '取消',
      okType: 'danger',
      centered: true,
      class: 'delete-group-modal',
      onOk() {
        resolve(true)
      },
      onCancel() {
        resolve(false)
      },
    })
  })

  if (!confirmed) return

  try {
    loading.value = true
    await MaterialGroupService.deleteGroup(group.id)

    // 移除已删除的分组
    const index = groupList.value.findIndex(g => g.id === group.id)
    if (index > -1) {
      groupList.value.splice(index, 1)
    }

    // 重新选择分组
    if (selectedGroupId.value === group.id) {
      selectedGroupId.value = groupList.value.length > 0 ? groupList.value[0].id : null
      await loadFileList()
    }

    message.success('分组删除成功')
  } catch (error) {
    console.error('分组删除失败:', error)
    message.error('分组删除失败，请重试')
  } finally {
    loading.value = false
  }
}

const handleOpenCreateGroupModal = () => {
  createGroupForm.name = ''
  createGroupForm.description = ''
  createGroupForm.category = activeCategory.value
  createGroupModalVisible.value = true
}

const handleCreateGroup = async () => {
  try {
    await MaterialGroupService.createGroup(createGroupForm)
    message.success('分组创建成功')
    createGroupModalVisible.value = false
    await loadGroupList()
  } catch (error) {
    message.error('分组创建失败')
  }
}

const loadGroupList = async () => {
  try {
    const result = await MaterialGroupService.getGroupListByCategory(activeCategory.value)
    groupList.value = result.data || result || []
  } catch (error) {
    console.error('加载分组列表失败:', error)
    try {
      const allGroups = await MaterialGroupService.getGroupList()
      groupList.value = allGroups.data || allGroups || []
    } catch (fallbackError) {
      console.error('加载所有分组也失败:', fallbackError)
      return
    }
  }

  // 默认选中第一个分组
  if (groupList.value.length > 0 && selectedGroupId.value === null) {
    selectedGroupId.value = groupList.value[0].id
  }

  await loadFileList()
}

const loadFileList = async () => {
  loading.value = true
  try {
    // 根据分类选择不同的 fileCategory
    // 混剪素材用 video，数字人素材用 digital_human
    const fileCategory = activeCategory.value === 'DIGITAL_HUMAN' ? 'digital_human' : 'video'

    const params = {
      pageNo: pagination.current,
      pageSize: pagination.pageSize,
      fileCategory,
      fileName: searchKeyword.value || undefined,
      // 数字人素材不传 groupId
      groupId: activeCategory.value === 'DIGITAL_HUMAN' ? undefined : (selectedGroupId.value || undefined)
    }

    const result = await MaterialService.getFilePage(params)
    fileList.value = result.data?.list || result.list || []
    const total = result.data?.total || result.total || 0
    pagination.total = total
    totalFileCount.value = total
  } catch (error) {
    console.error('加载文件列表失败:', error)
    message.error('加载文件列表失败')
  } finally {
    loading.value = false
  }
}

const handleSearch = () => {
  pagination.current = 1
  loadFileList()
}

const handlePageChange = (page, pageSize) => {
  pagination.current = page
  pagination.pageSize = pageSize
  loadFileList()
}

const handlePageSizeChange = (current, size) => {
  pagination.current = 1
  pagination.pageSize = size
  loadFileList()
}

const handleFileClick = (file) => {
  const index = selectedFileIds.value.indexOf(file.id)
  if (index > -1) {
    selectedFileIds.value.splice(index, 1)
  } else {
    selectedFileIds.value.push(file.id)
  }
}

const handleOpenUploadModal = () => {
  uploadModalVisible.value = true
}

const handleFileUpload = async (filesWithCover, category, groupId) => {
  try {
    uploadLoading.value = true

    // 根据当前分类确定 fileCategory
    // 混剪素材用 video，数字人素材用 digital_human
    const fileCategory = activeCategory.value === 'DIGITAL_HUMAN' ? 'digital_human' : 'video'
    // 数字人素材不关联分组
    const uploadGroupId = activeCategory.value === 'DIGITAL_HUMAN' ? null : groupId

    for (const fileWithCover of filesWithCover) {
      await upload(fileWithCover.file, {
        fileCategory,
        groupId: uploadGroupId,
        coverBase64: fileWithCover.coverBase64,
        onStart: () => {},
        onProgress: () => {},
        onSuccess: (id) => {
          console.log('文件上传成功:', id)
        },
        onError: (error) => {
          message.error(error.message || '上传失败')
        }
      })
    }

    message.success(`成功上传 ${filesWithCover.length} 个文件`)
    uploadModalVisible.value = false
    await loadFileList()
    // 刷新存储配额
    await userStore.fetchUserProfile()
    // 混剪素材才刷新分组列表
    if (activeCategory.value === 'MIX') {
      await loadGroupList()
    }
  } catch (error) {
    console.error("文件上传失败:", error)
    message.error("文件上传失败: " + (error.message || "未知错误"))
  } finally {
    uploadLoading.value = false
  }
}


const handleSelectAll = (event) => {
  const checked = event.target.checked
  if (checked) {
    selectedFileIds.value = fileList.value.map(file => file.id)
  } else {
    selectedFileIds.value = []
  }
}

const handleBatchDelete = async () => {
  if (selectedFileIds.value.length === 0) {
    message.warning('请先选择要删除的文件')
    return
  }

  const count = selectedFileIds.value.length
  const fileIdsToDelete = [...selectedFileIds.value]
  const confirmed = await new Promise((resolve) => {
    Modal.confirm({
      title: '确认删除',
      content: `确定要删除选中的 ${count} 个文件吗？此操作不可恢复。`,
      okText: '确认删除',
      cancelText: '取消',
      okType: 'danger',
      centered: true,
      class: 'batch-delete-modal',
      onOk() {
        resolve(true)
      },
      onCancel() {
        resolve(false)
      },
    })
  })

  if (!confirmed) return

  try {
    loading.value = true
    await MaterialService.deleteFiles(fileIdsToDelete)

    // 移除已删除的文件
    fileList.value = fileList.value.filter(file => !fileIdsToDelete.includes(file.id))

    // 更新状态
    totalFileCount.value = Math.max(0, totalFileCount.value - count)
    selectedFileIds.value = []

    // 刷新存储配额
    await userStore.fetchUserProfile()

    // 如果删除后当前页没有数据了，则加载上一页
    if (fileList.value.length === 0 && pagination.current > 1) {
      pagination.current = pagination.current - 1
      await loadFileList()
    }

    message.success(`成功删除 ${count} 个文件`)
  } catch (error) {
    console.error('批量删除失败:', error)
    message.error('删除失败，请重试')
  } finally {
    loading.value = false
  }
}

const formatFileSize = (size) => {
  if (size < 1024) return size + ' B'
  if (size < 1024 * 1024) return (size / 1024).toFixed(2) + ' KB'
  if (size < 1024 * 1024 * 1024) return (size / (1024 * 1024)).toFixed(2) + ' MB'
  return (size / (1024 * 1024 * 1024)).toFixed(2) + ' GB'
}

const formatDate = (date) => {
  return new Date(date).toLocaleDateString()
}

const getFileTypeText = (fileName) => {
  if (!fileName) return ''
  const ext = fileName.split('.').pop()
  return ext ? `${ext.toLowerCase()}` : ''
}

const handleEditName = async (file) => {
  editingFileId.value = file.id
  editingDisplayName.value = file.displayName || file.fileName
  await nextTick()

  // 查找当前编辑文件的输入框
  const nameElement = document.querySelector(`[data-file-id="${file.id}"] .material-item__name`)
  if (nameElement) {
    const input = nameElement.querySelector('input')
    if (input) {
      input.focus()
      input.select()
    }
  }
}

const handleSaveName = async (file) => {
  const newName = editingDisplayName.value.trim()

  if (!newName) {
    message.warning('名称不能为空')
    editingFileId.value = null
    return
  }

  if (newName === file.displayName) {
    editingFileId.value = null
    return
  }

  try {
    await MaterialService.updateDisplayName(file.id, newName)
    file.displayName = newName
    message.success('重命名成功')

    // 成功动画效果
    const nameElement = document.querySelector(`[data-file-id="${file.id}"] .material-item__name`)
    if (nameElement) {
      nameElement.style.transition = 'all 0.3s ease'
      nameElement.style.transform = 'scale(1.05)'
      setTimeout(() => {
        nameElement.style.transform = 'scale(1)'
      }, 300)
    }
  } catch (error) {
    console.error('重命名失败:', error)
    message.error('重命名失败，请重试')
  } finally {
    editingFileId.value = null
  }
}

const handleImageError = (e) => {
  e.target.style.display = 'none'
}

// 监听分类变化
watch(activeCategory, () => {
  selectedFileIds.value = []
})

// 初始化
onMounted(async () => {
  // 刷新用户档案获取最新存储配额
  await userStore.fetchUserProfile()
  await loadGroupList()
})
</script>

<style scoped lang="less">
// 使用设计系统变量
// 主色: var(--color-primary-500) = #3B82F6

// ========================================
// 主容器
// ========================================
.material-list-container {
  display: flex;
  height: 100%;
  background: var(--color-gray-50);
}

// ========================================
// 侧边栏 - 分组面板
// ========================================
.material-sidebar {
  width: 220px;
  background: var(--color-bg-card);
  border-right: 1px solid var(--color-gray-200);
  display: flex;
  flex-direction: column;
  padding: var(--space-5) var(--space-3);
  flex-shrink: 0;
}

.sidebar-slide-enter-active,
.sidebar-slide-leave-active {
  transition: all var(--duration-slow) cubic-bezier(0.4, 0, 0.2, 1);
}

.sidebar-slide-enter-from,
.sidebar-slide-leave-to {
  width: 0;
  opacity: 0;
  padding-left: 0;
  padding-right: 0;
}

.sidebar-section {
  &__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 var(--space-2);
    margin-bottom: var(--space-3);

    span {
      font-size: var(--font-size-xs);
      font-weight: 600;
      color: var(--color-gray-500);
      text-transform: uppercase;
      letter-spacing: 0.8px;
    }

    .ant-btn {
      padding: 2px 6px;
      height: auto;
      color: var(--color-gray-500);

      &:hover {
        color: var(--color-primary-500);
      }
    }
  }
}

.sidebar-group-list {
  flex: 1;
  overflow-y: auto;
  margin: 0 calc(var(--space-1) * -1);
  padding: 0 var(--space-1);

  &::-webkit-scrollbar {
    width: 4px;
  }

  &::-webkit-scrollbar-thumb {
    background: var(--color-gray-200);
    border-radius: 2px;
  }
}

.sidebar-group-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  border-radius: var(--radius-md);
  margin-bottom: 2px;
  transition: all var(--duration-fast);

  &:hover {
    background: var(--color-gray-100);

    .sidebar-group-item__action-btn {
      opacity: 1;
    }
  }

  &--active {
    background: var(--color-primary-50);
    color: var(--color-primary-500);

    .sidebar-group-item__icon {
      color: var(--color-primary-500);
    }
  }

  &__content {
    display: flex;
    align-items: center;
    min-width: 0;
    flex: 1;
  }

  &__icon {
    margin-right: var(--space-2);
    font-size: var(--font-size-base);
    color: var(--color-gray-500);
    flex-shrink: 0;
  }

  &__name {
    font-size: var(--font-size-sm);
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  &__actions {
    display: flex;
    align-items: center;
    gap: 2px;
  }

  &__count {
    font-size: var(--font-size-xs);
    color: var(--color-gray-500);
    margin-right: var(--space-2);
  }

  &__action-btn {
    opacity: 0;
    padding: var(--space-1);
    cursor: pointer;
    color: var(--color-gray-500);
    font-size: var(--font-size-xs);
    transition: all var(--duration-fast);

    &:hover {
      color: var(--color-primary-500);
    }

    &--danger:hover {
      color: var(--color-error-500);
    }
  }

  &__edit-input {
    :deep(.ant-input) {
      height: 24px;
      font-size: var(--font-size-sm);
      border-color: var(--color-primary-500);
      box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
      border-radius: var(--radius-sm);
    }
  }
}

// ========================================
// 内容区域
// ========================================
.material-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  transition: all var(--duration-slow) cubic-bezier(0.4, 0, 0.2, 1);
}

// ========================================
// 顶部工具栏
// ========================================
.material-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-6);
  background: var(--color-bg-card);
  border-bottom: 1px solid var(--color-gray-200);
  gap: var(--space-6);
}

// 分类切换器
.category-switcher {
  display: flex;
  background: var(--color-gray-50);
  border-radius: var(--radius-md);
  padding: var(--space-1);
  gap: var(--space-1);

  &__item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-5);
    border-radius: var(--radius-md);
    cursor: pointer;
    font-size: var(--font-size-base);
    font-weight: 500;
    color: var(--color-gray-600);
    transition: all var(--duration-base) ease;

    &:hover {
      color: var(--color-gray-900);
    }

    &--active {
      background: var(--color-bg-card);
      color: var(--color-primary-500);
      box-shadow: var(--shadow-sm);

      .category-switcher__icon {
        color: var(--color-primary-500);
      }
    }
  }

  &__icon {
    font-size: var(--font-size-md);
    color: var(--color-gray-500);
    transition: color var(--duration-base) ease;
  }
}

// 存储配额显示
.storage-quota {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--color-gray-50);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-gray-200);

  &__label {
    font-size: var(--font-size-xs);
    color: var(--color-gray-500);
  }

  &__value {
    font-size: var(--font-size-xs);
    font-weight: 500;
    color: var(--color-gray-900);
  }

  &__bar {
    width: 80px;
    height: 4px;
    background: var(--color-gray-200);
    border-radius: 2px;
    overflow: hidden;
  }

  &__used {
    height: 100%;
    background: linear-gradient(90deg, var(--color-primary-500), var(--color-primary-400));
    border-radius: 2px;
    transition: width var(--duration-slow) ease;
  }
}

// 工具栏操作区
.toolbar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);

  .search-input {
    width: 280px;

    :deep(.ant-input) {
      border-radius: var(--radius-md);
      border-color: var(--color-gray-200);
      background: var(--color-gray-50);

      &:focus {
        background: var(--color-bg-card);
        border-color: var(--color-primary-500);
        box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
      }
    }

    :deep(.ant-input-prefix) {
      color: var(--color-gray-500);
    }
  }

  .upload-btn {
    border-radius: var(--radius-md);
    font-weight: 500;
    display: flex;
    align-items: center;
    gap: var(--space-2);
  }
}

// ========================================
// 批量操作栏
// ========================================
.batch-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-6);
  background: var(--color-primary-50);
  border-bottom: 1px solid rgba(59, 130, 246, 0.1);

  &__info {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-base);
    color: var(--color-gray-900);

    .anticon {
      color: var(--color-primary-500);
      font-size: var(--font-size-md);
    }

    strong {
      color: var(--color-primary-500);
      font-weight: 600;
    }
  }

  &__btns {
    display: flex;
    gap: var(--space-2);
  }
}

.fade-slide-enter-active,
.fade-slide-leave-active {
  transition: all var(--duration-slow) ease;
}

.fade-slide-enter-from,
.fade-slide-leave-to {
  opacity: 0;
  transform: translateY(-10px);
}

// ========================================
// 文件列表区域
// ========================================
.material-content__list {
  flex: 1;
  padding: var(--space-6);
  overflow-y: auto;

  .loading-spinner {
    width: 100%;
    min-height: 400px;
  }
}

// 空状态
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 80px var(--space-6);

  &__icon {
    width: 80px;
    height: 80px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-gray-100);
    border-radius: 50%;
    margin-bottom: var(--space-5);

    .anticon {
      font-size: 36px;
      color: var(--color-gray-500);
    }
  }

  &__text {
    font-size: var(--font-size-md);
    color: var(--color-gray-600);
    margin-bottom: var(--space-5);
  }
}

// ========================================
// 素材网格
// ========================================
.material-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: var(--space-5);
}

.material-item {
  position: relative;
  background: var(--color-bg-card);
  border: 1px solid var(--color-gray-200);
  border-radius: var(--radius-lg);
  overflow: hidden;
  cursor: pointer;
  transition: all var(--duration-slow) cubic-bezier(0.4, 0, 0.2, 1);

  &:hover {
    border-color: var(--color-primary-500);
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);

    .material-item__check {
      opacity: 1;
    }

    .material-item__overlay {
      opacity: 1;
    }
  }

  &--selected {
    border-color: var(--color-primary-500);
    box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2), var(--shadow-md);

    .material-item__check .check-circle {
      background: var(--color-primary-500);
      border-color: var(--color-primary-500);
      opacity: 1;

      .anticon {
        opacity: 1;
      }
    }
  }

  // 选择指示器
  &__check {
    position: absolute;
    top: var(--space-2);
    left: var(--space-2);
    z-index: 10;
    opacity: 0;
    transition: opacity var(--duration-fast);

    .check-circle {
      width: 22px;
      height: 22px;
      border-radius: 50%;
      background: rgba(255, 255, 255, 0.9);
      border: 2px solid var(--color-gray-200);
      display: flex;
      align-items: center;
      justify-content: center;
      transition: all var(--duration-fast);
      box-shadow: var(--shadow-sm);

      .anticon {
        font-size: var(--font-size-xs);
        color: white;
        opacity: 0;
        transition: opacity var(--duration-fast);
      }

      &--checked {
        background: var(--color-primary-500);
        border-color: var(--color-primary-500);

        .anticon {
          opacity: 1;
        }
      }
    }
  }

  // 预览区
  &__preview {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 10;
    background: linear-gradient(135deg, var(--color-gray-50) 0%, var(--color-gray-100) 100%);
    overflow: hidden;

    img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      transition: transform var(--duration-slower) ease;
    }

    &:hover img {
      transform: scale(1.05);
    }
  }

  &__preview-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;

    .anticon {
      font-size: 40px;
      color: var(--color-gray-500);
    }
  }

  &__overlay {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: var(--space-2) var(--space-3);
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.6));
    opacity: 0;
    transition: opacity var(--duration-slow) ease;
  }

  &__type-tag {
    font-size: var(--font-size-xs);
    font-weight: 600;
    color: white;
    text-transform: uppercase;
    letter-spacing: 0.5px;
  }

  // 信息区
  &__info {
    padding: var(--space-3) var(--space-4);
  }

  &__name {
    font-size: var(--font-size-base);
    font-weight: 600;
    color: var(--color-gray-900);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    line-height: 1.4;
    margin-bottom: var(--space-2);
    transition: color var(--duration-fast);

    &:hover {
      color: var(--color-primary-500);
    }

    :deep(.ant-input) {
      font-size: var(--font-size-base);
      font-weight: 600;
      height: 22px;
      border-radius: var(--radius-sm);
      border-color: var(--color-primary-500);
      box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
    }
  }

  &__meta {
    display: flex;
    align-items: center;
    font-size: var(--font-size-xs);
    color: var(--color-gray-500);

    .meta-dot {
      margin: 0 var(--space-2);
    }
  }
}

// ========================================
// 底部操作栏
// ========================================
.material-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-6);
  background: var(--color-bg-card);
  border-top: 1px solid var(--color-gray-200);

  .footer-left {
    display: flex;
    align-items: center;
    gap: var(--space-4);
  }

  .footer-count {
    font-size: var(--font-size-sm);
    color: var(--color-gray-500);
  }

  :deep(.ant-pagination) {
    .ant-pagination-item {
      border-radius: var(--radius-base);
      border-color: var(--color-gray-200);

      &:hover {
        border-color: var(--color-primary-500);

        a {
          color: var(--color-primary-500);
        }
      }
    }

    .ant-pagination-item-active {
      border-color: var(--color-primary-500);
      background: var(--color-primary-500);

      a {
        color: white;
      }
    }

    .ant-pagination-options {
      .ant-select-selector {
        border-radius: var(--radius-base);
        border-color: var(--color-gray-200);
      }
    }
  }
}

// ========================================
// 弹窗样式
// ========================================
:deep(.batch-delete-modal),
:deep(.delete-group-modal) {
  .ant-modal-content {
    border-radius: var(--radius-lg);
    overflow: hidden;
  }

  .ant-modal-body {
    padding: var(--space-6);
  }

  .ant-modal-footer {
    padding: var(--space-4) var(--space-6);
    border-top: 1px solid var(--color-gray-200);
  }
}
</style>
