<template>
  <div class="w-full animate-reveal">
    <div class="flex items-center justify-between mb-6">
      <h1 class="text-2xl font-serif italic text-white">附件管理</h1>
      <button @click="showUploadModal = true" class="admin-btn-primary">
        上传附件
      </button>
    </div>

    <!-- Filters -->
    <AdminTableFilter
      v-model:keyword="searchKeyword"
      keyword-placeholder="搜索文件名..."
      @search="loadAttachments"
      @reset="resetFilters"
    >
      <template #filters>
        <div class="filter-field">
          <label>分类</label>
          <CustomSelect
            v-model="filterCategoryId"
            :options="categoryOptions"
            placeholder="全部"
            style="width: 140px;"
          />
        </div>
        <div class="filter-field">
          <label>类型</label>
          <CustomSelect
            v-model="filterFileType"
            :options="fileTypeOptions"
            placeholder="全部"
            style="width: 120px;"
          />
        </div>
      </template>
    </AdminTableFilter>

    <!-- Attachments Grid -->
    <div v-if="loading" class="flex justify-center items-center h-64">
      <div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-art-accent"></div>
    </div>

    <div v-else-if="attachments.length === 0" class="text-center py-20 text-art-muted">
      <p>暂无附件</p>
    </div>

    <div v-else class="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4">
      <div
        v-for="attachment in attachments"
        :key="attachment.id"
        @click="openDetailModal(attachment)"
        class="admin-card p-4 group cursor-pointer hover:border-art-accent transition-colors"
      >
        <div v-if="attachment.fileType === 'image'" class="aspect-square mb-2 rounded overflow-hidden bg-white/5">
          <img :src="attachment.fileUrl" :alt="attachment.originalName" class="w-full h-full object-cover" />
        </div>
        <div v-else-if="attachment.fileType === 'video'" class="aspect-square mb-2 rounded overflow-hidden bg-black/40 relative">
          <video
            :src="attachment.fileUrl"
            muted
            preload="metadata"
            class="w-full h-full object-cover"
          />
          <div class="absolute inset-0 flex items-center justify-center bg-black/30 pointer-events-none">
            <div class="w-10 h-10 rounded-full bg-white/20 backdrop-blur-sm flex items-center justify-center border border-white/30">
              <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="white">
                <polygon points="8 5 19 12 8 19 8 5"></polygon>
              </svg>
            </div>
          </div>
        </div>
        <div v-else class="aspect-square mb-2 rounded bg-white/5 flex items-center justify-center">
          <i data-lucide="file" class="w-12 h-12 text-art-muted"></i>
        </div>
        
        <p class="text-xs text-white truncate mb-1" :title="attachment.originalName">
          {{ attachment.originalName }}
        </p>
        <p class="text-xs text-art-muted mb-2">
          {{ formatFileSize(attachment.fileSize) }}
        </p>
        
        <div class="flex gap-2 opacity-0 group-hover:opacity-100 transition-opacity">
          <button
            @click.stop="copyUrl(attachment.fileUrl)"
            class="flex-1 px-2 py-1 text-xs bg-white/5 hover:bg-white/10 rounded transition-colors"
          >
            复制链接
          </button>
          <button
            @click.stop="deleteAttachment(attachment.id)"
            class="px-2 py-1 text-xs bg-red-500/20 hover:bg-red-500/30 text-red-400 rounded transition-colors"
          >
            删除
          </button>
        </div>
      </div>
    </div>

    <!-- Detail Modal -->
    <AttachmentDetailModal
      :show="showDetailModal"
      :attachment="selectedAttachment"
      :categories="categories"
      @update:show="showDetailModal = $event"
      @save="handleSaveCategory"
      @copy-url="copyUrl"
    />

    <!-- Upload Modal -->
    <div v-if="showUploadModal" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50" @click.self="showUploadModal = false">
      <div class="admin-card max-w-md w-full mx-4">
        <h2 class="text-xl font-serif italic text-white mb-4">上传附件</h2>
        
        <div class="space-y-4">
          <div>
            <label class="block text-sm text-art-muted mb-2">选择文件</label>
            <div
              @click="triggerUploadSelect"
              @dragover.prevent="handleDragOver"
              @dragenter.prevent="handleDragEnter"
              @dragleave.prevent="handleDragLeave"
              @drop.prevent="handleDrop"
              class="border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors"
              :class="[
                isDragging ? 'border-art-accent bg-art-accent/5' : 'border-white/20 hover:border-art-accent/50',
                uploading ? 'opacity-50 cursor-not-allowed' : ''
              ]"
            >
              <input
                type="file"
                ref="uploadInput"
                @change="handleUploadFileSelect"
                class="hidden"
              />
              <p class="text-sm text-art-muted">点击或拖拽文件到此处上传</p>
              <p v-if="pendingFileName" class="text-xs text-art-accent mt-2">已选择：{{ pendingFileName }}</p>
            </div>
          </div>
          
          <div>
            <label class="block text-sm text-art-muted mb-2">分类（可选）</label>
            <CustomSelect
              v-model="uploadCategoryId"
              :options="uploadCategoryOptions"
              placeholder="无分类"
            />
          </div>
          
          <div class="flex gap-3">
            <button type="button" @click="showUploadModal = false" class="admin-btn-secondary flex-1">
              取消
            </button>
            <button type="button" @click="uploadFile" :disabled="uploading" class="admin-btn-primary flex-1">
              {{ uploading ? '上传中...' : '上传' }}
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import { useToast } from '../../composables/useToast'
import CustomSelect from '../../components/CustomSelect.vue'
import AdminTableFilter from '../../components/admin/AdminTableFilter.vue'
import AttachmentDetailModal from '../../components/admin/AttachmentDetailModal.vue'
import { getAdminAttachments, updateAttachment, API_BASE, authFetch, parseApiResponse, type Attachment } from '../../services/api'
import { useImageDropUpload } from '../../composables/useImageDropUpload'

const toast = useToast()

interface LocalAttachment extends Omit<Attachment, 'mimeType' | 'createdAt' | 'storageType'> {
  categoryId?: number
  mimeType?: string
  storageType?: string
  createdAt?: string
}

interface Category {
  id: number
  name: string
}

const attachments = ref<LocalAttachment[]>([])
const categories = ref<Category[]>([])
const loading = ref(false)
const showUploadModal = ref(false)
const showDetailModal = ref(false)
const selectedAttachment = ref<LocalAttachment | null>(null)
const uploadInput = ref<HTMLInputElement | null>(null)
const uploadCategoryId = ref(0)
const uploading = ref(false)
const pendingFileName = ref('')
const filterCategoryId = ref(0)
const filterFileType = ref('')
const searchKeyword = ref('')

// 计算属性：分类选项
const categoryOptions = computed(() => {
  return [
    { value: 0, label: '全部' },
    ...categories.value.map(cat => ({ value: cat.id, label: cat.name }))
  ]
})

// 计算属性：文件类型选项
const fileTypeOptions = computed(() => {
  return [
    { value: '', label: '全部' },
    { value: 'image', label: '图片' },
    { value: 'video', label: '视频' },
    { value: 'document', label: '文档' },
    { value: 'other', label: '其他' }
  ]
})

// 计算属性：上传分类选项
const uploadCategoryOptions = computed(() => {
  return [
    { value: 0, label: '无分类' },
    ...categories.value.map(cat => ({ value: cat.id, label: cat.name }))
  ]
})


const loadAttachments = async () => {
  loading.value = true
  try {
    const data = await getAdminAttachments({
      page: 1,
      pageSize: 100,
      categoryId: filterCategoryId.value > 0 ? filterCategoryId.value : undefined,
      fileType: filterFileType.value || undefined,
      keyword: searchKeyword.value.trim() || undefined,
    })
    attachments.value = data.list as LocalAttachment[]
  } catch (err: any) {
    toast.showToast(err.message || '加载失败', 'error')
  } finally {
    loading.value = false
  }
}

const resetFilters = () => {
  searchKeyword.value = ''
  filterCategoryId.value = 0
  filterFileType.value = ''
  loadAttachments()
}

const loadCategories = async () => {
  try {
    const data = await parseApiResponse<Category[]>(await authFetch(`${API_BASE}/admin/attachment-categories`))
    categories.value = data || []
  } catch (err) {
    console.error('Failed to load categories:', err)
  }
}

const handleUploadFileSelect = () => {
  const file = uploadInput.value?.files?.[0]
  if (file) {
    pendingFileName.value = file.name
    void uploadFileWithFile(file)
  }
}

const triggerUploadSelect = () => {
  if (uploading.value) return
  uploadInput.value?.click()
}

const { isDragging, handleDragOver, handleDragEnter, handleDragLeave, handleDrop } = useImageDropUpload({
  disabled: () => uploading.value,
  acceptImagesOnly: false,
  onFiles: (files) => {
    if (files[0]) {
      pendingFileName.value = files[0].name
      void uploadFileWithFile(files[0])
    }
  },
})

const uploadFileWithFile = async (file: File) => {
  uploading.value = true
  try {
    const formData = new FormData()
    formData.append('file', file)
    if (uploadCategoryId.value > 0) {
      formData.append('categoryId', uploadCategoryId.value.toString())
    }
    formData.append('storageType', 'local')

    await parseApiResponse(await authFetch(`${API_BASE}/admin/attachments/upload`, {
      method: 'POST',
      headers: {},
      body: formData
    }))

    toast.showToast('上传成功', 'success')
    showUploadModal.value = false
    if (uploadInput.value) uploadInput.value.value = ''
    uploadCategoryId.value = 0
    pendingFileName.value = ''
    loadAttachments()
  } catch (err: any) {
    toast.showToast(err.message || '上传失败', 'error')
  } finally {
    uploading.value = false
  }
}

const uploadFile = async () => {
  if (!uploadInput.value?.files || uploadInput.value.files.length === 0) {
    toast.showToast('请选择文件', 'error')
    return
  }

  await uploadFileWithFile(uploadInput.value.files[0])
}

const deleteAttachment = async (id: number) => {
  if (!confirm('确定要删除这个附件吗？')) return

  try {
    await parseApiResponse(await authFetch(`${API_BASE}/admin/attachments/${id}`, {
      method: 'DELETE'
    }))

    toast.showToast('删除成功', 'success')
    loadAttachments()
  } catch (err: any) {
    toast.showToast(err.message || '删除失败', 'error')
  }
}

const copyUrl = (url: string) => {
  navigator.clipboard.writeText(url)
  toast.showToast('链接已复制', 'success')
}

const formatFileSize = (bytes: number): string => {
  if (bytes < 1024) return bytes + ' B'
  if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'
  return (bytes / (1024 * 1024)).toFixed(1) + ' MB'
}

const openDetailModal = (attachment: LocalAttachment) => {
  selectedAttachment.value = attachment
  showDetailModal.value = true
}

const handleSaveCategory = async (data: { categoryId: number | null }) => {
  if (!selectedAttachment.value) return

  try {
    await updateAttachment(selectedAttachment.value.id, data)
    
    toast.showToast('分类更新成功', 'success')
    
    // 更新本地数据
    if (selectedAttachment.value) {
      selectedAttachment.value.categoryId = data.categoryId || undefined
    }
    
    // 刷新列表
    loadAttachments()
    
    // 关闭模态框
    showDetailModal.value = false
    selectedAttachment.value = null
  } catch (err: any) {
    toast.showToast(err.message || '更新失败', 'error')
  }
}

onMounted(() => {
  loadCategories()
  loadAttachments()
})
</script>
