<template>
  <div class="file-manage">
    <!-- Header -->
    <div class="page-header">
      <div class="header-left">
        <h2 class="page-title">文件管理</h2>
        <p class="page-subtitle">管理您的文档集合</p>
      </div>
      <div class="header-actions">
        <el-button type="primary" @click="handleUpload" class="upload-btn">
          <el-icon><Upload /></el-icon>
          <span>上传文件</span>
        </el-button>
      </div>
    </div>

    <!-- Stats Cards -->
    <div class="stats-grid">
      <div
        class="stat-card stat-total"
        :class="{ active: filterStatus === '' }"
        @click="filterStatus = ''"
      >
        <div class="stat-glow"></div>
        <div class="stat-inner">
          <div class="stat-icon-wrap">
            <el-icon size="24"><Document /></el-icon>
          </div>
          <div class="stat-info">
            <span class="stat-value">{{ files.length }}</span>
            <span class="stat-label">总文件数</span>
          </div>
        </div>
      </div>
      <div
        class="stat-card stat-completed"
        :class="{ active: filterStatus === 'completed' }"
        @click="filterStatus = filterStatus === 'completed' ? '' : 'completed'"
      >
        <div class="stat-glow"></div>
        <div class="stat-inner">
          <div class="stat-icon-wrap">
            <el-icon size="24"><CircleCheckFilled /></el-icon>
          </div>
          <div class="stat-info">
            <span class="stat-value">{{ completedFiles }}</span>
            <span class="stat-label">已完成</span>
          </div>
        </div>
      </div>
      <div
        class="stat-card stat-processing"
        :class="{ active: filterStatus === 'processing' }"
        @click="filterStatus = filterStatus === 'processing' ? '' : 'processing'"
      >
        <div class="stat-glow"></div>
        <div class="stat-inner">
          <div class="stat-icon-wrap">
            <el-icon size="24"><Loading /></el-icon>
          </div>
          <div class="stat-info">
            <span class="stat-value">{{ processingFiles.length }}</span>
            <span class="stat-label">处理中</span>
          </div>
        </div>
      </div>
      <div
        class="stat-card stat-failed"
        :class="{ active: filterStatus === 'failed' }"
        @click="filterStatus = filterStatus === 'failed' ? '' : 'failed'"
      >
        <div class="stat-glow"></div>
        <div class="stat-inner">
          <div class="stat-icon-wrap">
            <el-icon size="24"><CircleCloseFilled /></el-icon>
          </div>
          <div class="stat-info">
            <span class="stat-value">{{ failedFiles }}</span>
            <span class="stat-label">失败</span>
          </div>
        </div>
      </div>
    </div>

    <!-- File List Container -->
    <div class="file-container" v-loading="loading && isInitialLoad">
      <!-- Empty State -->
      <div v-if="!loading && !isInitialLoad && filteredFiles.length === 0 && !uploading" class="empty-state">
        <div class="empty-illustration">
          <div class="orbit orbit-1"></div>
          <div class="orbit orbit-2"></div>
          <div class="orbit orbit-3"></div>
          <div class="empty-core">
            <el-icon size="40"><FolderOpened /></el-icon>
          </div>
        </div>
        <h3 class="empty-title">暂无文件</h3>
        <p class="empty-desc">上传您的第一个文档，开启智能处理之旅</p>
      </div>

      <!-- Files Table -->
      <div v-else class="files-table-wrapper">
        <!-- Table Header -->
        <div class="table-header">
          <div class="table-select">
            <el-checkbox
              :model-value="isAllSelected"
              @change="toggleSelectAll"
              class="select-all"
            >
              <span v-if="selectedCount > 0" class="selected-text">已选择 {{ selectedCount }} 项</span>
              <span v-else>全选</span>
            </el-checkbox>
          </div>
          <div class="table-actions" v-if="selectedCount > 0">
            <el-button type="danger" size="small" plain @click="batchDelete" class="batch-delete-btn">
              <el-icon><Delete /></el-icon>
              <span>批量删除</span>
            </el-button>
          </div>
        </div>

        <!-- Table Body -->
        <div class="files-table">
          <div
            v-for="(file, index) in filteredFiles"
            :key="file.id"
            class="file-row"
            :class="{
              'is-selected': isSelected(file.id),
              'is-processing': file.status === 'processing',
              'row-animated': isInitialLoad
            }"
            :style="{ '--delay': index * 0.04 + 's' }"
          >
            <!-- Select Checkbox -->
            <div class="col-select">
              <el-checkbox
                :model-value="isSelected(file.id)"
                @change="toggleSelect(file.id)"
              />
            </div>

            <!-- File Icon -->
            <div class="col-icon">
              <div class="file-type-icon" :style="{ '--type-color': getTypeColor(file.file_type) }">
                <el-icon size="18">
                  <component :is="getFileIcon(file.file_type)" />
                </el-icon>
              </div>
            </div>

            <!-- File Name -->
            <div class="col-name">
              <span class="filename-text">{{ file.filename }}</span>
              <span class="file-ext">{{ getFileExt(file.filename) }}</span>
            </div>

            <!-- Size -->
            <div class="col-size">
              {{ formatSize(file.size) }}
            </div>

            <!-- Date -->
            <div class="col-date">
              {{ formatDate(file.created_at) }}
            </div>

            <!-- Status -->
            <div class="col-status">
              <div class="status-pill" :class="'status-' + file.status">
                <span class="status-dot"></span>
                <span class="status-text">{{ getStatusText(file.status) }}</span>
              </div>
            </div>

            <!-- Actions -->
            <div class="col-actions">
              <el-tooltip content="预览" placement="top" v-if="file.status === 'completed'">
                <el-button text size="small" class="action-btn preview" @click="handlePreview(file)">
                  <el-icon><View /></el-icon>
                </el-button>
              </el-tooltip>
              <el-popconfirm title="确定删除此文件？" @confirm="handleDelete(file)">
                <template #reference>
                  <el-button text size="small" class="action-btn delete">
                    <el-icon><Delete /></el-icon>
                  </el-button>
                </template>
              </el-popconfirm>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- Upload Dialog -->
    <el-dialog v-model="uploadDialogVisible" title="上传文件" width="520px" class="upload-dialog" :close-on-click-modal="false">
      <div class="upload-area" @click="triggerUpload">
        <el-upload
          ref="uploadRef"
          class="upload-component"
          :auto-upload="false"
          :limit="10"
          :on-change="handleChange"
          :on-remove="handleRemove"
          :file-list="fileList"
          drag
          multiple
          accept=".pdf,.docx,.doc,.xlsx,.xls,.csv,.epub,.md,.txt"
          style="display: none;"
        />
        <div class="upload-content">
          <div class="upload-illustration">
            <div class="upload-ring"></div>
            <div class="upload-core">
              <el-icon size="32"><UploadFilled /></el-icon>
            </div>
          </div>
          <div class="upload-text">
            拖拽文件到此处，或 <em>点击选择</em>
          </div>
          <div class="upload-hint">
            支持 PDF、DOCX、Excel、EPUB、Markdown 等格式
          </div>
        </div>
      </div>

      <!-- Selected Files -->
      <div v-if="fileList.length > 0" class="selected-area">
        <div class="selected-header">
          <span>已选择 <strong>{{ fileList.length }}</strong> 个文件</span>
          <el-button text size="small" @click="fileList = []">清空</el-button>
        </div>
        <div class="selected-list">
          <div v-for="item in fileList" :key="item.uid" class="selected-item">
            <el-icon size="14"><Document /></el-icon>
            <span>{{ item.name }}</span>
          </div>
        </div>
      </div>

      <template #footer>
        <el-button @click="uploadDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitUpload" :loading="uploading" :disabled="fileList.length === 0">
          开始上传
        </el-button>
      </template>
    </el-dialog>
  </div>

  <!-- Preview Modal -->
  <Teleport to="body">
    <!-- Backdrop -->
    <Transition name="fade">
      <div
        v-if="previewVisible"
        class="preview-backdrop"
        @click="previewVisible = false"
      ></div>
    </Transition>

    <!-- Preview Modal -->
    <Transition name="slide-right">
      <div v-if="previewVisible" class="preview-modal">
        <!-- Header -->
        <div class="preview-header">
          <div class="header-title">
            <el-icon class="title-icon"><Document /></el-icon>
            <span class="filename">{{ previewFile?.filename }}</span>
          </div>
          <el-button class="close-btn" text @click="previewVisible = false">
            <el-icon><Close /></el-icon>
          </el-button>
        </div>

        <!-- Tabs -->
        <div class="preview-tabs-wrapper">
          <div class="preview-tabs">
            <button
              class="tab-item"
              :class="{ active: previewMode === 'source' }"
              @click="switchPreviewMode('source')"
            >
              源文件
            </button>
            <button
              class="tab-item"
              :class="{ active: previewMode === 'markdown' }"
              @click="switchPreviewMode('markdown')"
            >
              Markdown
            </button>
            <div class="tab-indicator" :class="{ 'at-right': previewMode === 'markdown' }"></div>
          </div>
        </div>

        <!-- Content -->
        <div class="preview-content" v-loading="previewLoading">
          <iframe v-if="isPdfPreview && pdfDataUrl" :src="pdfDataUrl" class="pdf-viewer"></iframe>
          <pre v-else-if="previewContent" class="code-content">{{ previewContent }}</pre>
          <div v-else-if="!previewLoading && !isPdfPreview" class="preview-empty">
            <el-icon size="32"><Document /></el-icon>
            <span>暂无内容</span>
          </div>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { ElMessage } from 'element-plus'
import { fileApi } from '@/api'

const route = useRoute()
const projectId = computed(() => route.params.id)

const loading = ref(false)
const files = ref([])
const filterStatus = ref('')
const isInitialLoad = ref(true)

const filteredFiles = computed(() => {
  if (!filterStatus.value) return files.value
  return files.value.filter(f => f.status === filterStatus.value)
})
const uploadDialogVisible = ref(false)
const uploading = ref(false)
const uploadRef = ref(null)
const fileList = ref([])

// Multi-select
const selectedFiles = ref([])

const isAllSelected = computed(() => filteredFiles.value.length > 0 && selectedFiles.value.length === filteredFiles.value.length)
const selectedCount = computed(() => selectedFiles.value.length)

const toggleSelectAll = () => {
  if (isAllSelected.value) {
    selectedFiles.value = []
  } else {
    selectedFiles.value = filteredFiles.value.map(f => f.id)
  }
}

const toggleSelect = (fileId) => {
  const index = selectedFiles.value.indexOf(fileId)
  if (index === -1) {
    selectedFiles.value.push(fileId)
  } else {
    selectedFiles.value.splice(index, 1)
  }
}

const isSelected = (fileId) => selectedFiles.value.includes(fileId)

const batchDelete = async () => {
  if (selectedFiles.value.length === 0) return
  try {
    for (const fileId of selectedFiles.value) {
      await fileApi.delete(projectId.value, fileId)
    }
    ElMessage.success(`已删除 ${selectedFiles.value.length} 个文件`)
    selectedFiles.value = []
    fetchFiles()
  } catch (error) {
    ElMessage.error('删除失败')
  }
}

// Preview
const previewVisible = ref(false)
const previewFile = ref(null)
const previewContent = ref('')
const previewLoading = ref(false)
const previewMode = ref('source') // 'source' | 'markdown'
const isPdfPreview = ref(false)
const pdfDataUrl = ref('')

const completedFiles = computed(() => files.value.filter(f => f.status === 'completed').length)
const processingFiles = computed(() => files.value.filter(f => f.status === 'processing' || f.status === 'pending'))
const failedFiles = computed(() => files.value.filter(f => f.status === 'failed').length)

const fetchFiles = async () => {
  const wasInitial = isInitialLoad.value
  loading.value = true
  try {
    const res = await fileApi.list(projectId.value)
    files.value = res || []
  } catch (error) {
    files.value = []
  } finally {
    loading.value = false
    if (wasInitial) {
      isInitialLoad.value = false
    }
  }
}

const handleUpload = () => {
  fileList.value = []
  uploadDialogVisible.value = true
}

const handleChange = (file, files) => { fileList.value = files }
const handleRemove = (file, files) => { fileList.value = files }

const triggerUpload = () => {
  const input = uploadRef.value?.$el?.querySelector('input')
  if (input) {
    input.click()
  }
}

const submitUpload = async () => {
  if (fileList.value.length === 0) {
    ElMessage.warning('请先选择文件')
    return
  }

  // 保存上传前的文件数量
  const prevFileCount = files.value.length

  // 先关闭对话框
  uploadDialogVisible.value = false
  ElMessage.success('已开始上传文件')

  // 设置上传状态，防止显示空状态
  uploading.value = true

  // 在后台逐个上传（不等待上传完成）
  const uploadPromises = fileList.value.map(async (item) => {
    try {
      const formData = new FormData()
      formData.append('file', item.raw)
      await fileApi.upload(projectId.value, formData)
    } catch (error) {
      console.error('上传失败:', error)
    }
  })

  // 立即刷新文件列表，显示新增的文件（状态为 processing）
  await fetchFiles()

  // 如果之前没有文件，需要等待上传的Promise完成后再刷新一次
  if (prevFileCount === 0) {
    await Promise.all(uploadPromises)
    await fetchFiles()
  }

  // 持续轮询文件列表，直到没有 processing 状态的文件
  const pollInterval = setInterval(async () => {
    await fetchFiles()
    // 检查是否还有处理中的文件
    const hasProcessing = files.value.some(f => f.status === 'processing')
    if (!hasProcessing) {
      clearInterval(pollInterval)
      uploading.value = false
    }
  }, 2000)

  // 最多轮询60秒
  setTimeout(() => {
    clearInterval(pollInterval)
    uploading.value = false
  }, 60000)
}

const handleDelete = async (file) => {
  try {
    await fileApi.delete(projectId.value, file.id)
    ElMessage.success('删除成功')
    fetchFiles()
  } catch (error) {
    ElMessage.error('删除失败')
  }
}

const handlePreview = async (file) => {
  previewFile.value = file
  previewVisible.value = true
  previewContent.value = ''
  previewLoading.value = true
  previewMode.value = 'source'

  try {
    await loadPreviewContent()
  } finally {
    previewLoading.value = false
  }
}

const loadPreviewContent = async () => {
  if (!previewFile.value) return
  previewLoading.value = true
  isPdfPreview.value = false
  pdfDataUrl.value = ''

  try {
    const endpoint = previewMode.value === 'source' ? 'raw' : 'content'
    const response = await fetch(`/api/v1/projects/${projectId.value}/files/${previewFile.value.id}/${endpoint}`)
    if (response.ok) {
      const text = await response.text()
      if (text.startsWith('data:application/pdf;base64,')) {
        isPdfPreview.value = true
        pdfDataUrl.value = text
        previewContent.value = ''
      } else {
        previewContent.value = text
      }
    } else {
      previewContent.value = '无法加载内容'
    }
  } catch (error) {
    previewContent.value = '加载失败: ' + error.message
  } finally {
    previewLoading.value = false
  }
}

const switchPreviewMode = async (mode) => {
  previewMode.value = mode
  await loadPreviewContent()
}

const getFileIcon = (type) => {
  const map = { pdf: 'Document', docx: 'Document', xlsx: 'Grid', csv: 'Document', epub: 'Notebook', md: 'Document', txt: 'Document' }
  return map[type] || 'Document'
}

const getTypeColor = (type) => {
  const map = {
    pdf: '#ef4444',
    docx: '#3b82f6',
    xlsx: '#22c55e',
    csv: '#22c55e',
    epub: '#f59e0b',
    md: '#8b5cf6',
    txt: '#6b7280'
  }
  return map[type] || '#6b7280'
}

const getFileExt = (filename) => {
  if (!filename) return ''
  const ext = filename.split('.').pop()?.toLowerCase()
  return ext ? '.' + ext : ''
}

const getStatusText = (status) => {
  const map = {
    processing: '处理中',
    completed: '已完成',
    failed: '失败',
    pending: '待处理'
  }
  return map[status] || '未知'
}

const formatSize = (bytes) => {
  if (!bytes) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]
}

const formatDate = (date) => {
  if (!date) return ''
  return new Date(date).toLocaleDateString('zh-CN', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })
}

onMounted(() => fetchFiles())
</script>

<style scoped>
/* ========================
   CSS Variables
   ======================== */
.file-manage {
  --accent-cyan: #00d4ff;
  --accent-cyan-dim: rgba(0, 212, 255, 0.15);
  --accent-cyan-glow: rgba(0, 212, 255, 0.4);
  --bg-elevated: #0f1117;
  --bg-card: #161920;
  --bg-hover: #1c2029;
  --border-subtle: rgba(255, 255, 255, 0.08);
  --border-active: rgba(0, 212, 255, 0.3);
  --text-secondary: #9ca3af;
  --text-muted: #6b7280;
  --success: #22c55e;
  --warning: #f59e0b;
  --danger: #ef4444;
  --radius-lg: 12px;
  --radius-md: 8px;
  --radius-sm: 6px;
  padding: 28px 32px;
}

/* ========================
   Header
   ======================== */
.page-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 28px;
}

.header-left {
  position: relative;
}

.page-title {
  font-size: 28px;
  font-weight: 700;
  margin: 0;
  background: linear-gradient(135deg, #ffffff 0%, var(--accent-cyan) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  letter-spacing: -0.5px;
}

.page-subtitle {
  font-size: 14px;
  color: var(--text-muted);
  margin: 6px 0 0;
}

.header-actions {
  display: flex;
  gap: 12px;
}

.upload-btn {
  background: var(--accent-cyan) !important;
  border: none !important;
  color: #030407 !important;
  font-weight: 600;
  padding: 10px 22px;
  border-radius: var(--radius-md);
  box-shadow: 0 0 20px var(--accent-cyan-dim);
  transition: all 0.2s ease;
}

.upload-btn:hover {
  box-shadow: 0 0 35px var(--accent-cyan-glow);
  transform: translateY(-1px);
}

.qa-btn {
  background: var(--bg-card) !important;
  border: 1px solid var(--border-subtle) !important;
  color: var(--text-secondary) !important;
  font-weight: 500;
  padding: 10px 22px;
  border-radius: var(--radius-md);
}

.qa-btn:hover:not(:disabled) {
  background: var(--bg-hover) !important;
  border-color: var(--accent-cyan) !important;
  color: var(--accent-cyan) !important;
}

.qa-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ========================
   Stats Grid
   ======================== */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-bottom: 24px;
}

.stat-card {
  position: relative;
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: all 0.25s ease;
}

.stat-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  opacity: 0;
  transition: opacity 0.25s ease;
}

.stat-card:hover {
  transform: translateY(-2px);
  border-color: var(--border-active);
  cursor: pointer;
}

.stat-card:hover::before {
  opacity: 1;
}

.stat-card.active {
  border-color: var(--accent-cyan);
  box-shadow: 0 0 20px var(--accent-cyan-dim);
}

.stat-card.active::before {
  opacity: 1;
}

.stat-card.active .stat-glow {
  opacity: 0.5;
}

.stat-glow {
  position: absolute;
  top: -50%;
  left: -50%;
  width: 200%;
  height: 200%;
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
}

.stat-card:hover .stat-glow {
  opacity: 0.5;
}

/* Stat variations */
.stat-total {
  --stat-color: #818cf8;
}

.stat-total::before {
  background: linear-gradient(90deg, #6366f1, #818cf8);
}

.stat-total .stat-glow {
  background: radial-gradient(circle at 30% 30%, rgba(99, 102, 241, 0.3), transparent 50%);
}

.stat-completed {
  --stat-color: var(--success);
}

.stat-completed::before {
  background: linear-gradient(90deg, #16a34a, var(--success));
}

.stat-completed .stat-glow {
  background: radial-gradient(circle at 30% 30%, rgba(34, 197, 94, 0.3), transparent 50%);
}

.stat-processing {
  --stat-color: var(--warning);
}

.stat-processing::before {
  background: linear-gradient(90deg, #d97706, var(--warning));
}

.stat-processing .stat-glow {
  background: radial-gradient(circle at 30% 30%, rgba(245, 158, 11, 0.3), transparent 50%);
}

.stat-failed {
  --stat-color: var(--danger);
}

.stat-failed::before {
  background: linear-gradient(90deg, #dc2626, var(--danger));
}

.stat-failed .stat-glow {
  background: radial-gradient(circle at 30% 30%, rgba(239, 68, 68, 0.3), transparent 50%);
}

.stat-inner {
  position: relative;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 20px 22px;
  z-index: 1;
}

.stat-icon-wrap {
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.05);
  border-radius: var(--radius-md);
  color: var(--stat-color);
}

.stat-info {
  display: flex;
  flex-direction: column;
}

.stat-value {
  font-size: 28px;
  font-weight: 700;
  color: #ffffff;
  font-family: 'SF Mono', 'JetBrains Mono', monospace;
  line-height: 1.1;
}

.stat-label {
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 2px;
}

/* ========================
   File Container
   ======================== */
.file-container {
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  overflow: hidden;
  overflow-x: auto;
}

/* ========================
   Empty State
   ======================== */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 80px 40px;
  min-height: 450px;
}

.empty-illustration {
  position: relative;
  width: 140px;
  height: 140px;
  margin-bottom: 28px;
}

.orbit {
  position: absolute;
  border-radius: 50%;
  border: 1px dashed rgba(0, 212, 255, 0.2);
}

.orbit-1 {
  inset: 10px;
  animation: orbit-rotate 20s linear infinite;
}

.orbit-2 {
  inset: 30px;
  border-color: rgba(0, 212, 255, 0.15);
  animation: orbit-rotate 15s linear infinite reverse;
}

.orbit-3 {
  inset: 50px;
  border-color: rgba(0, 212, 255, 0.1);
  animation: orbit-rotate 10s linear infinite;
}

@keyframes orbit-rotate {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.empty-core {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 70px;
  height: 70px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--bg-hover) 0%, var(--bg-card) 100%);
  border: 1px solid var(--border-subtle);
  border-radius: 50%;
  color: var(--accent-cyan);
  box-shadow: 0 0 40px var(--accent-cyan-dim);
}

.empty-title {
  font-size: 22px;
  font-weight: 600;
  color: #ffffff;
  margin: 0 0 8px;
}

.empty-desc {
  font-size: 14px;
  color: var(--text-muted);
  margin: 0;
  text-align: center;
}

/* ========================
   Files Table
   ======================== */
.files-table-wrapper {
  display: flex;
  flex-direction: column;
  min-width: 800px;
}

.table-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 20px;
  background: var(--bg-elevated);
  border-bottom: 1px solid var(--border-subtle);
}

.table-select .select-all {
  --el-checkbox-text-color: var(--text-secondary);
}

.selected-text {
  color: var(--accent-cyan);
  font-weight: 500;
}

.batch-delete-btn {
  background: transparent !important;
  border-color: var(--danger) !important;
  color: var(--danger) !important;
}

.batch-delete-btn:hover {
  background: var(--danger) !important;
  color: white !important;
}

.files-table {
  display: flex;
  flex-direction: column;
}

.file-row {
  display: grid;
  grid-template-columns: 40px 50px 1fr 80px 100px 80px 70px;
  align-items: center;
  gap: 16px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--border-subtle);
  transition: background 0.15s ease;
}

.file-row.row-animated {
  animation: row-in 0.3s ease backwards;
  animation-delay: var(--delay);
}

@keyframes row-in {
  from {
    opacity: 0;
    transform: translateX(-10px);
  }
}

.file-row:hover {
  background: var(--bg-hover);
}

.file-row.is-selected {
  background: rgba(0, 212, 255, 0.05);
}

.file-row.is-processing {
  background: rgba(245, 158, 11, 0.03);
}

.file-row.is-processing:hover {
  background: rgba(245, 158, 11, 0.08);
}

/* Column styles */
.col-select {
  display: flex;
  justify-content: center;
}

.col-icon {
  display: flex;
  justify-content: center;
}

.file-type-icon {
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--type-color) 15%, transparent);
  border-radius: var(--radius-sm);
  color: var(--type-color);
}

.col-name {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

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

.file-ext {
  font-size: 11px;
  font-family: 'SF Mono', monospace;
  color: var(--text-muted);
  background: rgba(255, 255, 255, 0.05);
  padding: 2px 6px;
  border-radius: 4px;
  flex-shrink: 0;
}

.col-size,
.col-date {
  font-size: 13px;
  color: var(--text-muted);
  font-family: 'SF Mono', monospace;
  min-width: 70px;
}

.col-status {
  min-width: 80px;
}

/* Status Pill */
.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 500;
}

.status-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
}

.status-processing {
  background: rgba(245, 158, 11, 0.1);
  color: var(--warning);
}

.status-processing .status-dot {
  background: var(--warning);
  animation: pulse 1.5s ease-in-out infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

.status-completed {
  background: rgba(34, 197, 94, 0.1);
  color: var(--success);
}

.status-completed .status-dot {
  background: var(--success);
}

.status-failed {
  background: rgba(239, 68, 68, 0.1);
  color: var(--danger);
}

.status-failed .status-dot {
  background: var(--danger);
}

.status-pending {
  background: rgba(107, 114, 128, 0.1);
  color: var(--text-muted);
}

.status-pending .status-dot {
  background: var(--text-muted);
}

/* Actions */
.col-actions {
  display: flex;
  justify-content: flex-end;
  gap: 4px;
  min-width: 70px;
}

.action-btn {
  color: var(--text-muted) !important;
  transition: all 0.15s ease;
}

.action-btn:hover {
  color: var(--accent-cyan) !important;
  background: var(--accent-cyan-dim) !important;
}

.action-btn.delete:hover {
  color: var(--danger) !important;
  background: rgba(239, 68, 68, 0.1) !important;
}

/* ========================
   Upload Dialog
   ======================== */
:deep(.upload-dialog .el-dialog) {
  background: var(--bg-elevated) !important;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
}

:deep(.upload-dialog .el-dialog__header) {
  padding: 20px 24px;
  border-bottom: 1px solid var(--border-subtle);
}

:deep(.upload-dialog .el-dialog__title) {
  font-weight: 600;
  font-size: 18px;
  color: #ffffff;
}

:deep(.upload-dialog .el-dialog__body) {
  padding: 24px;
}

.upload-area {
  border: 2px dashed var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: 48px 24px;
  cursor: pointer;
  transition: all 0.2s ease;
  background: var(--bg-card);
}

.upload-area:hover {
  border-color: var(--accent-cyan);
  background: var(--accent-cyan-dim);
}

.upload-content {
  text-align: center;
}

.upload-illustration {
  position: relative;
  width: 80px;
  height: 80px;
  margin: 0 auto 20px;
}

.upload-ring {
  position: absolute;
  inset: 0;
  border: 2px dashed var(--accent-cyan);
  border-radius: 50%;
  opacity: 0.3;
  animation: ring-pulse 2s ease-in-out infinite;
}

@keyframes ring-pulse {
  0%, 100% { transform: scale(1); opacity: 0.3; }
  50% { transform: scale(1.1); opacity: 0.15; }
}

.upload-core {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-cyan-dim);
  border-radius: 50%;
  color: var(--accent-cyan);
}

.upload-text {
  font-size: 15px;
  color: var(--text-secondary);
  margin-bottom: 8px;
}

.upload-text em {
  color: var(--accent-cyan);
  font-style: normal;
  font-weight: 600;
}

.upload-hint {
  font-size: 13px;
  color: var(--text-muted);
}

/* Selected Files */
.selected-area {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid var(--border-subtle);
}

.selected-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  font-size: 14px;
  color: var(--text-secondary);
}

.selected-header strong {
  color: var(--accent-cyan);
}

.selected-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  max-height: 150px;
  overflow-y: auto;
}

.selected-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  background: var(--bg-tertiary);
  border-radius: var(--radius-sm);
  font-size: 13px;
  color: var(--text-secondary);
}

/* ========================
   Preview Modal
   ======================== */
.preview-backdrop {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: rgba(0, 0, 0, 0.7);
  backdrop-filter: blur(4px);
}

.preview-modal {
  position: fixed;
  top: 20px;
  bottom: 20px;
  right: 40px;
  z-index: 2001;
  width: 720px;
  max-width: calc(100vw - 80px);
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.preview-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border-subtle);
  background: var(--bg-card);
}

.header-title {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  flex: 1;
}

.title-icon {
  font-size: 20px;
  color: var(--accent-cyan);
  flex-shrink: 0;
}

.filename {
  font-size: 15px;
  font-weight: 600;
  color: #ffffff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.close-btn {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  color: var(--text-muted) !important;
}

.close-btn:hover {
  background: var(--bg-hover) !important;
  color: #ffffff !important;
}

.preview-tabs-wrapper {
  padding: 12px 20px 0;
  background: var(--bg-card);
}

.preview-tabs {
  position: relative;
  display: flex;
  background: var(--bg-elevated);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  padding: 4px;
  border: 1px solid var(--border-subtle);
  border-bottom: none;
}

.tab-item {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px 16px;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s ease;
  position: relative;
  z-index: 1;
}

.tab-item:hover:not(.active) {
  color: var(--text-secondary);
}

.tab-item.active {
  color: #ffffff;
}

.tab-indicator {
  position: absolute;
  top: 4px;
  left: 4px;
  width: calc(50% - 4px);
  height: calc(100% - 8px);
  background: var(--accent-cyan);
  border-radius: var(--radius-sm);
  transition: transform 0.2s ease;
  z-index: 0;
  opacity: 0.15;
}

.tab-indicator.at-right {
  transform: translateX(100%);
}

.preview-content {
  flex: 1;
  overflow: auto;
  background: var(--bg-primary);
  border-left: 1px solid var(--border-subtle);
  border-right: 1px solid var(--border-subtle);
}

.code-content {
  font-family: 'SF Mono', 'JetBrains Mono', monospace;
  font-size: 13px;
  line-height: 1.7;
  color: var(--text-secondary);
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0;
  padding: 20px;
}

.pdf-viewer {
  width: 100%;
  height: 100%;
  min-height: 400px;
  border: none;
  background: white;
}

.preview-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 300px;
  color: var(--text-muted);
  gap: 12px;
}

/* Transitions */
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.2s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

.slide-right-enter-active {
  transition: all 0.25s ease;
}

.slide-right-leave-active {
  transition: all 0.15s ease;
}

.slide-right-enter-from {
  opacity: 0;
  transform: translateX(30px);
}

.slide-right-leave-to {
  opacity: 0;
  transform: translateX(20px);
}

/* ========================
   Responsive
   ======================== */
@media (max-width: 900px) {
  .file-manage {
    padding: 20px;
  }

  .stats-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .page-header {
    flex-direction: column;
    gap: 16px;
  }

  .header-actions {
    width: 100%;
  }

  .header-actions .el-button {
    flex: 1;
  }

  .file-row {
    grid-template-columns: 40px 40px 1fr 60px;
    gap: 8px;
  }

  .col-date,
  .col-status {
    display: none;
  }

  .col-actions {
    min-width: 50px;
  }

  .preview-modal {
    right: 20px;
    left: 20px;
    top: 20px;
    bottom: 20px;
    width: auto;
    max-width: none;
  }
}
</style>
