<template>
  <div class="file-page">
    <!-- 顶部操作栏 -->
    <div class="page-toolbar">
      <div class="toolbar-left">
        <el-select v-model="filterType" placeholder="文件类型" clearable style="width:140px" @change="fetchData">
          <el-option label="头像" value="avatar" />
          <el-option label="图标" value="icon" />
          <el-option label="文档" value="doc" />
          <el-option label="其他" value="other" />
        </el-select>
      </div>
      <div class="toolbar-right">
        <el-button type="primary" @click="uploadVisible = true" v-permission="'system:file:upload'">
          <el-icon><Upload /></el-icon>上传文件
        </el-button>
        <el-button @click="fetchData" :icon="RefreshRight">刷新</el-button>
      </div>
    </div>

    <!-- 上传弹窗 -->
    <el-dialog v-model="uploadVisible" title="上传文件" width="460px" destroy-on-close>
      <el-form :model="uploadForm" label-width="80px">
        <el-form-item label="文件类型">
          <el-select v-model="uploadForm.fileType" style="width:100%">
            <el-option label="头像" value="avatar" />
            <el-option label="图标" value="icon" />
            <el-option label="文档" value="doc" />
            <el-option label="其他" value="other" />
          </el-select>
        </el-form-item>
        <el-form-item label="选择文件">
          <div class="upload-area" @click="triggerUpload" v-if="!uploadForm.file">
            <el-icon :size="32" color="#94a3b8"><UploadFilled /></el-icon>
            <p>点击选择文件</p>
          </div>
          <div class="upload-file" v-else>
            <el-icon><Document /></el-icon>
            <span>{{ uploadForm.file.name }}</span>
            <span class="upload-size">{{ formatSize(uploadForm.file.size) }}</span>
            <el-button size="small" text type="danger" @click="uploadForm.file = null">
              <el-icon><Close /></el-icon>
            </el-button>
          </div>
          <input ref="fileInputRef" type="file" style="display:none" @change="onFileSelected" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="uploadVisible = false">取消</el-button>
        <el-button type="primary" :loading="uploading" :disabled="!uploadForm.file" @click="doUpload">
          开始上传
        </el-button>
      </template>
    </el-dialog>

    <!-- 文件网格 -->
    <div class="file-grid" v-loading="loading">
      <div
        v-for="item in fileList"
        :key="item.id"
        class="file-card"
        @click="preview(item)"
      >
        <!-- 预览区域 -->
        <div class="file-preview">
          <template v-if="isImage(item.mimeType)">
            <img
              :src="getFileUrl(item.id)"
              :alt="item.fileName"
              class="file-thumb"
              loading="lazy"
            />
          </template>
          <template v-else-if="item.fileType === 'doc'">
            <el-icon :size="48" color="#6366f1"><Document /></el-icon>
          </template>
          <template v-else>
            <el-icon :size="48" color="#94a3b8"><FolderOpened /></el-icon>
          </template>
        </div>
        <!-- 信息 -->
        <div class="file-info">
          <div class="file-name" :title="item.fileName">{{ item.fileName }}</div>
          <div class="file-meta">
            <el-tag size="small" type="info">{{ item.fileType || 'other' }}</el-tag>
            <span class="file-size">{{ formatSize(item.fileSize) }}</span>
          </div>
        </div>
        <!-- 操作 -->
        <div class="file-actions" @click.stop>
          <el-button size="small" text @click="preview(item)">
            <el-icon><View /></el-icon>
          </el-button>
          <el-popconfirm title="确定删除此文件？" @confirm="handleDelete(item.id)">
            <template #reference>
              <el-button size="small" text type="danger">
                <el-icon><Delete /></el-icon>
              </el-button>
            </template>
          </el-popconfirm>
        </div>
      </div>
    </div>

    <el-empty v-if="!loading && fileList.length === 0" description="暂无文件" />

    <!-- 分页 -->
    <div class="page-footer" v-if="total > 0">
      <el-pagination
        v-model:current-page="page"
        :page-size="pageSize"
        :total="total"
        layout="prev, pager, next"
        @current-change="fetchData"
        small
      />
    </div>

    <!-- 预览弹窗 -->
    <el-dialog v-model="previewVisible" title="文件预览" width="720px" destroy-on-close>
      <div class="preview-body">
        <template v-if="previewItem && isImage(previewItem.mimeType)">
          <img :src="getFileUrl(previewItem.id)" style="max-width:100%;max-height:60vh;display:block;margin:0 auto" />
        </template>
        <template v-else>
          <el-empty description="非图片文件，无法预览" />
        </template>
        <div class="preview-meta" v-if="previewItem">
          <div class="meta-line"><span class="meta-label">文件名：</span>{{ previewItem.fileName }}</div>
          <div class="meta-line"><span class="meta-label">类型：</span>{{ previewItem.mimeType || '-' }}</div>
          <div class="meta-line"><span class="meta-label">大小：</span>{{ formatSize(previewItem.fileSize) }}</div>
          <div class="meta-line"><span class="meta-label">上传时间：</span>{{ previewItem.createdAt }}</div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { RefreshRight, Document, FolderOpened, View, Delete, Upload, UploadFilled, Close } from '@element-plus/icons-vue'
import request from '@/utils/request'

interface FileItem {
  id: string
  fileName: string
  fileType: string
  fileSize: number
  mimeType: string
  md5: string
  createdAt: string
}

const loading = ref(false)
const fileList = ref<FileItem[]>([])
const total = ref(0)
const page = ref(1)
const pageSize = ref(20)
const filterType = ref('')
const previewVisible = ref(false)
const previewItem = ref<FileItem | null>(null)
const gatewayUrl = import.meta.env.VITE_GATEWAY_URL || ''

// ===== 上传 =====
const uploadVisible = ref(false)
const uploading = ref(false)
const fileInputRef = ref<HTMLInputElement>()
const uploadForm = reactive({ fileType: 'other', file: null as File | null })

function triggerUpload() {
  fileInputRef.value?.click()
}

function onFileSelected(e: Event) {
  const file = (e.target as HTMLInputElement).files?.[0]
  if (file) uploadForm.file = file
}

async function doUpload() {
  if (!uploadForm.file) return
  uploading.value = true
  try {
    const fd = new FormData()
    fd.append('file', uploadForm.file)
    fd.append('fileType', uploadForm.fileType)
    await request.post('/zgapi/v1/admin/file/upload', fd)
    ElMessage.success('上传成功')
    uploadVisible.value = false
    uploadForm.file = null
    fetchData()
  } catch { /* ignore */ } finally {
    uploading.value = false
  }
}

function getFileUrl(id: string) {
  return `${gatewayUrl}/zgapi/v1/admin/file/${id}/view`
}

function isImage(mimeType: string | null | undefined) {
  return mimeType ? mimeType.startsWith('image/') : false
}

function formatSize(bytes: number | null) {
  if (!bytes) return '0 B'
  if (bytes < 1024) return bytes + ' B'
  if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB'
  return (bytes / 1048576).toFixed(1) + ' MB'
}

async function fetchData() {
  loading.value = true
  try {
    const res = await request.post('/zgapi/v1/admin/file/page', {
      page: page.value,
      pageSize: pageSize.value,
      fileType: filterType.value || undefined,
    })
    fileList.value = res.data?.records || []
    total.value = res.data?.total || 0
  } catch { /* 拦截器已提示 */ } finally {
    loading.value = false
  }
}

function preview(item: FileItem) {
  previewItem.value = item
  previewVisible.value = true
}

async function handleDelete(id: string) {
  try {
    await request.delete(`/zgapi/v1/admin/file/${id}`)
    ElMessage.success('已删除')
    if (fileList.value.length === 1 && page.value > 1) page.value--
    fetchData()
  } catch { /* ignore */ }
}

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

<style scoped>
.file-page { max-width: 1100px; }

/* 工具栏 */
.page-toolbar { display:flex; justify-content:space-between; align-items:center; margin-bottom:20px; }
.toolbar-left { display:flex; gap:12px; }
.page-footer { display:flex; justify-content:center; margin-top:24px; }

/* 文件网格 */
.file-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 16px;
}

.file-card {
  background: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  overflow: hidden;
  cursor: pointer;
  transition: all var(--transition-fast);
}
.file-card:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--color-primary);
}

/* 预览区 */
.file-preview {
  width: 100%;
  height: 160px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-page);
  overflow: hidden;
}
.file-thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 信息区 */
.file-info {
  padding: 12px;
}
.file-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 8px;
}
.file-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.file-size {
  font-size: 12px;
  color: var(--text-muted);
}

/* 操作 */
.file-actions {
  display: flex;
  justify-content: flex-end;
  padding: 0 8px 8px;
  gap: 4px;
}

/* 上传弹窗 */
.upload-area {
  width: 100%; height: 120px;
  border: 2px dashed var(--border-color);
  border-radius: var(--radius-md);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  cursor: pointer; transition: all var(--transition-fast);
  color: var(--text-muted); font-size: 13px; gap: 8px;
}
.upload-area:hover { border-color: var(--color-primary); background: var(--color-primary-bg); }
.upload-file {
  display: flex; align-items: center; gap: 10px;
  padding: 12px; background: var(--bg-page); border-radius: var(--radius-md);
  font-size: 13px;
}
.upload-size { color: var(--text-muted); font-size: 12px; margin-left: auto; }

/* 移动端 */
@media (max-width: 768px) {
  .file-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; }
  .file-preview { height: 120px; }
  .file-name { font-size: 12px; }
  .page-toolbar { flex-direction: column; gap: 10px; }
}

/* 预览弹窗 */
.preview-meta {
  margin-top: 20px;
  padding: 16px;
  background: var(--bg-page);
  border-radius: var(--radius-md);
}
.meta-line {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 2;
}
.meta-label {
  color: var(--text-muted);
}
</style>
