<template>
  <div class="file-list-view">
    <div class="list-header" :style="gridStyle">
      <div class="col-checkbox">
        <input type="checkbox" :checked="isAllSelected" :indeterminate="isPartialSelected" @change="$emit('toggleSelectAll')" />
      </div>
      <div v-for="col in columns" :key="col.key" class="col-data">{{ col.title }}</div>
      <div class="col-actions">{{ t('Actions') }}</div>
    </div>
    <div class="list-body">
      <div
        v-for="row in rows"
        :key="row.name"
        class="list-item"
        :style="gridStyle"
        :class="{ selected: selectedKeys.includes(row.name), previewed: previewName === row.name }"
        @click="$emit('rowClick', row)"
      >
        <div class="col-checkbox" @click.stop>
          <input type="checkbox" :checked="selectedKeys.includes(row.name)" @change="$emit('toggleSelection', row.name)" />
        </div>
        <div v-for="col in columns" :key="col.key" class="col-data" @click.stop="$emit('rowClick', row)">
          <!-- 文件名列：显示缩略图 + 文件名 -->
          <template v-if="col.key === 'file_name'">
            <div class="file-name-cell">
              <img
                v-if="isImageFile(row) && row.thumbnail_url"
                :src="row.thumbnail_url"
                class="file-thumb"
                loading="lazy"
                decoding="async"
              />
              <Icon v-else :icon="getFileIcon(row)" :size="18" class="file-icon" :style="{ color: getFileColor(row) }" />
              <span class="file-name-text">{{ row.file_name || row.name }}</span>
            </div>
          </template>
          <!-- 文件大小列：格式化 -->
          <template v-else-if="col.key === 'file_size'">
            {{ row.file_size ? formatFileSize(row.file_size) : '—' }}
          </template>
          <!-- 时间列：ISO 8601 -->
          <template v-else-if="col.key === 'modified' || col.key === 'creation'">
            {{ formatDateTime(row[col.key]) }}
          </template>
          <!-- 其他列 -->
          <template v-else>{{ row[col.key] ?? '—' }}</template>
        </div>
        <div class="col-actions" @click.stop>
          <slot name="actions" :row="row" />
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { Icon } from '@iconify/vue'
import { t } from '@/shared/i18n'

interface Column {
  key: string
  title: string
  width?: string
}

const props = defineProps<{
  rows: any[]
  columns: Column[]
  selectedKeys: string[]
  previewName: string
}>()

defineEmits(['rowClick', 'toggleSelection', 'toggleSelectAll'])

const isAllSelected = computed(() => props.rows.length > 0 && props.rows.every(r => props.selectedKeys.includes(r.name)))
const isPartialSelected = computed(() => !isAllSelected.value && props.rows.some(r => props.selectedKeys.includes(r.name)))

const gridStyle = computed(() => {
  const parts = ['40px'] // checkbox
  props.columns.forEach(c => {
    parts.push(c.width || 'minmax(100px, 1fr)')
  })
  parts.push('120px') // actions
  return { gridTemplateColumns: parts.join(' ') }
})

const IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp', 'ico']

function isImageFile(row: any): boolean {
  return IMAGE_EXTENSIONS.includes((row.file_type || '').toLowerCase())
}

function getFileIcon(row: any): string {
  const ext = (row.file_type || '').toLowerCase()
  if (row.is_folder) return 'tabler:folder'
  if (IMAGE_EXTENSIONS.includes(ext)) return 'tabler:photo'
  if (['pdf'].includes(ext)) return 'tabler:file-type-pdf'
  if (['doc', 'docx'].includes(ext)) return 'tabler:file-type-doc'
  if (['xls', 'xlsx'].includes(ext)) return 'tabler:file-type-xls'
  if (['ppt', 'pptx'].includes(ext)) return 'tabler:file-type-ppt'
  if (['zip', 'rar', '7z', 'tar', 'gz'].includes(ext)) return 'tabler:file-zip'
  if (['mp4', 'avi', 'mov', 'mkv', 'webm'].includes(ext)) return 'tabler:file-type-video'
  if (['mp3', 'wav', 'flac', 'aac', 'ogg'].includes(ext)) return 'tabler:file-type-audio'
  if (['txt', 'md', 'csv'].includes(ext)) return 'tabler:file-type-text'
  if (['js', 'ts', 'py', 'html', 'css', 'json', 'xml'].includes(ext)) return 'tabler:file-type-code'
  return 'tabler:file'
}

function getFileColor(row: any): string {
  const ext = (row.file_type || '').toLowerCase()
  if (row.is_folder) return '#f59e0b'
  if (IMAGE_EXTENSIONS.includes(ext)) return '#10b981'
  if (['pdf'].includes(ext)) return '#ef4444'
  if (['doc', 'docx'].includes(ext)) return '#3b82f6'
  if (['xls', 'xlsx'].includes(ext)) return '#059669'
  if (['zip', 'rar', '7z'].includes(ext)) return '#8b5cf6'
  if (['mp4', 'avi', 'mov'].includes(ext)) return '#ec4899'
  if (['mp3', 'wav', 'flac'].includes(ext)) return '#f97316'
  return '#6b7280'
}

function formatFileSize(bytes: number | string): string {
  const size = typeof bytes === 'string' ? parseInt(bytes, 10) : bytes
  if (isNaN(size) || size === 0) return '0 B'
  const units = ['B', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(size) / Math.log(1024))
  return (size / Math.pow(1024, i)).toFixed(i > 0 ? 1 : 0) + ' ' + units[i]
}

import { formatDateTimeInTimezone } from '@/shared/utils/timezone'

function formatDateTime(value: any): string {
  if (!value) return '—'
  try {
    return formatDateTimeInTimezone(value)
  } catch { return String(value) }
}
</script>

<style scoped>
.file-list-view {
  background: #fff;
  overflow: hidden;
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.list-header {
  display: grid;
  align-items: center;
  gap: 12px;
  padding: 0 12px;
  height: 45px;
  background: #fff;
  border-bottom: 1px solid #f0f0f0;
  font-size: 12px;
  font-weight: 600;
  color: #6b7280;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  flex-shrink: 0;
}

.list-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

.list-item {
  display: grid;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border-bottom: 1px solid #f5f5f5;
  cursor: pointer;
  transition: background 0.15s;
  font-size: 13px;
}

.list-item:hover { background: #f8fafc; }
.list-item.selected { background: #f0f9ff; }
.list-item.previewed {
  background: #eff6ff;
  border-left: 2px solid #3b82f6;
  border-radius: 6px 0 0 6px;
  border-bottom-color: transparent;
}

.col-checkbox {
  display: flex;
  align-items: center;
  justify-content: center;
}

.col-checkbox input { cursor: pointer; accent-color: #3b82f6; width: 16px; height: 16px; }

.col-data {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.col-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  opacity: 0;
  transition: opacity 0.15s;
}

.list-item:hover .col-actions { opacity: 1; }

/* 文件名列 */
.file-name-cell {
  display: flex;
  align-items: center;
  gap: 8px;
  overflow: hidden;
}

.file-thumb {
  width: 28px;
  height: 28px;
  border-radius: 4px;
  object-fit: cover;
  flex-shrink: 0;
}

.file-icon { flex-shrink: 0; }

.file-name-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: #1f2937;
  font-weight: 450;
}
</style>
