<template>
  <div class="file-list-panel" :style="{ width: width + '%' }">
    <div class="panel-header">
      <span class="panel-title">📋 文件列表</span>
      <div class="panel-header-right">
        <a-popover trigger="click" position="bottom" :content-style="{ padding: '4px', width: '170px' }">
          <a-button size="mini" type="text" class="settings-btn">
            <icon-more />
          </a-button>
          <template #content>
            <div class="col-setting-title">列设置</div>
            <div class="col-setting-item" style="cursor: default;">
              <span class="drag-handle"></span>
              <a-checkbox :model-value="showHeader" @change="(val: boolean) => { showHeader = val; localStorage.setItem(SHOW_HEADER_KEY, String(val)) }">
                显示表头
              </a-checkbox>
            </div>
            <div
              v-for="(col, idx) in orderedColumns"
              :key="col.key"
              class="col-setting-item"
              draggable="true"
              @dragstart="onDragStart($event, idx)"
              @dragover.prevent
              @drop="onDrop($event, idx)"
            >
              <span class="drag-handle">⠿</span>
              <a-checkbox
                :model-value="col.visible"
                :disabled="col.key === 'name' && visibleCount <= 1"
                @change="(val: boolean) => toggleColumn(col.key, val)"
              >{{ col.label }}</a-checkbox>
              <!-- 可排序列：点击图标排序 -->
              <span
                v-if="colSortMap[col.key]"
                class="col-sort-icon"
                :class="{ 'col-sort-active': sortBy === colSortMap[col.key] }"
                :title="sortBy === colSortMap[col.key] ? (sortOrder === 'asc' ? '升序 → 点击降序' : '降序 → 点击升序') : `按${col.label}排序`"
                @click.stop="emit('sort', colSortMap[col.key])"
              >
                <IconSort v-if="sortBy !== colSortMap[col.key]" />
                <IconSortAscending v-else-if="sortOrder === 'asc'" />
                <IconSortDescending v-else />
              </span>
            </div>
          </template>
        </a-popover>
      </div>
    </div>

    <div
      class="file-list-wrapper thin-dark-scrollbar"
      @contextmenu.prevent="handleWrapperContextMenu"
    >
      <!-- 文件列表（滚动区域） -->
      <a-table
        v-if="config.fileList.length > 0 || config.fileLoading"
        :columns="tableColumns"
        :data="pagedFileList"
        :loading="config.fileLoading"
        :pagination="false"
        :bordered="false"
        :show-header="showHeader"
        size="mini"
        :row-class-name="getRowClassName"
        class="file-table"
        @row-click="handleRowClick"
        @row-contextmenu="handleRowContextMenu"
      />

      <!-- 空状态 -->
      <div v-if="config.fileList.length === 0 && !config.fileLoading" class="empty-state">
        <span style="font-size: 32px">📭</span>
        <span>此文件夹为空</span>
      </div>
    </div>

    <!-- 分页栏（固定在面板底部，不随内容滚动） -->
    <div v-if="config.fileList.length > 0" class="pagination-bar">
      <span class="pagination-total">共 {{ config.fileList.length }} 项</span>
      <span class="pagination-nav">
        <span class="page-btn" :class="{ disabled: currentPage <= 1 }" @click="onPageChange(currentPage - 1)">
          <icon-left />
        </span>
        <span class="page-info">{{ currentPage }} / {{ totalPages }}</span>
        <span class="page-btn" :class="{ disabled: currentPage >= totalPages }" @click="onPageChange(currentPage + 1)">
          <icon-right />
        </span>
      </span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { h, computed, nextTick, ref, watch } from 'vue'
import { Input, Button } from '@arco-design/web-vue'
import { IconStar, IconStarFill, IconSort, IconSortAscending, IconSortDescending, IconMore, IconLeft, IconRight } from '@arco-design/web-vue/es/icon'
import { formatBytes, formatFileTime, getFileIcon, getExt } from '@/utils/fileUtils'
import { STORAGE_KEYS } from '@/utils/constants'
import type { FileListPanelConfig, FileItem } from '@/types/file-system'

// Props
interface Props {
  config: FileListPanelConfig
  width: number
  favorites: string[]
  sortBy: string
  sortOrder: string
}

const props = defineProps<Props>()

// Emits
interface Emits {
  (e: 'fileClick', file: FileItem): void
  (e: 'fileDoubleClick', file: FileItem): void
  (e: 'toggleFavorite', file: FileItem): void
  (e: 'startEditing', path: string, name: string): void
  (e: 'saveEditing', path: string, newName: string): void
  (e: 'cancelEditing'): void
  (e: 'contextMenu', event: MouseEvent, file: FileItem | null): void
  (e: 'nameUpdate', newName: string): void
  (e: 'sort', field: string): void
}

const emit = defineEmits<Emits>()

// 列 key → 排序字段映射
const colSortMap: Record<string, string> = {
  icon: 'type',
  name: 'name',
  time: 'modified_time',
  size: 'size'
}

// ========== 列配置（支持显隐 + 排序） ==========
const COL_SETTINGS_KEY = STORAGE_KEYS.FILESYSTEM.COL_SETTINGS
const SHOW_HEADER_KEY = STORAGE_KEYS.FILESYSTEM.SHOW_HEADER

interface ColumnConfig {
  key: string
  label: string
  visible: boolean
  order: number
}

const defaultColumns: ColumnConfig[] = [
  { key: 'icon', label: '图标(T)', visible: true, order: 0 },
  { key: 'name', label: '名称', visible: true, order: 1 },
  { key: 'time', label: '时间', visible: true, order: 2 },
  { key: 'size', label: '大小', visible: true, order: 3 },
  { key: 'fav', label: '收藏', visible: true, order: 4 }
]

// 从 localStorage 恢复或使用默认值（按 key 匹合，允许列数变化）
function loadColSettings(): ColumnConfig[] {
  try {
    const saved = localStorage.getItem(COL_SETTINGS_KEY)
    if (saved) {
      const parsed = JSON.parse(saved) as ColumnConfig[]
      if (Array.isArray(parsed)) {
        // 以 defaultColumns 为基准，合并已保存的 visible/order
        return defaultColumns.map((def, i) => {
          const existing = parsed.find(p => p.key === def.key)
          return existing ? { ...def, visible: existing.visible ?? true, order: existing.order ?? i } : { ...def }
        })
      }
    }
  } catch { /* localStorage 不可用则使用默认列配置 */ }
  return [...defaultColumns]
}

const colSettings = ref<ColumnConfig[]>(loadColSettings())
// 默认隐藏表头（localStorage 无值时默认不显示）
const showHeader = ref(localStorage.getItem(SHOW_HEADER_KEY) === 'true')

// 手动持久化（避免 deep watch 频繁写入）
function saveColSettings() {
  localStorage.setItem(COL_SETTINGS_KEY, JSON.stringify(colSettings.value))
}

// 排序后的列配置
const orderedColumns = computed(() =>
  [...colSettings.value].sort((a, b) => a.order - b.order)
)

// 可见列数量
const visibleCount = computed(() =>
  colSettings.value.filter(c => c.visible).length
)

// 切换单列显隐
const toggleColumn = (key: string, visible: boolean) => {
  const col = colSettings.value.find(c => c.key === key)
  if (col) { col.visible = visible; saveColSettings() }
}

// HTML5 拖拽排序
const dragIdx = ref(-1)
const onDragStart = (_e: DragEvent, idx: number) => { dragIdx.value = idx }
const onDrop = (_e: DragEvent, idx: number) => {
  if (dragIdx.value === -1 || dragIdx.value === idx) return
  const list = [...orderedColumns.value]
  const [moved] = list.splice(dragIdx.value, 1)
  list.splice(idx, 0, moved)
  // 更新 order 值
  list.forEach((c, i) => {
    const target = colSettings.value.find(x => x.key === c.key)
    if (target) target.order = i
  })
  dragIdx.value = -1
  saveColSettings()
}

// 排序图标渲染
const sortIcon = (field: string) => {
  if (props.sortBy !== field) return () => h(IconSort, { style: { fontSize: '12px', color: 'var(--color-text-4)' } })
  return () => props.sortOrder === 'asc'
    ? h(IconSortAscending, { style: { fontSize: '12px', color: 'rgb(var(--primary-6))' } })
    : h(IconSortDescending, { style: { fontSize: '12px', color: 'rgb(var(--primary-6))' } })
}

// 根据配置构建单列定义
function buildColumn(key: string, editPath: string | undefined) {
  switch (key) {
    case 'icon':
      return {
        title: () => h('div', {
          class: 'th-sortable th-sort-center',
          onClick: () => emit('sort', 'type')
        }, [
          h('span', { style: { fontWeight: 600, fontSize: '11px', marginRight: '2px' } }, 'T'),
          sortIcon('type')()
        ]),
        width: 32,
        bodyCellClass: 'col-icon',
        render: ({ record }: { record: FileItem }) => {
          const ext = getExt(record.name)
          return h('span', {
            class: 'file-item-icon',
            title: ext ? `.${ext.toUpperCase()} : ${record.name}` : record.name
          }, getFileIcon(record))
        }
      }

    case 'name':
      return {
        title: () => h('div', {
          class: 'th-sortable',
          onClick: () => emit('sort', 'name')
        }, [
          h('span', { style: { fontWeight: 600 } }, '名称'),
          sortIcon('name')()
        ]),
        dataIndex: 'name',
        ellipsis: true,
        render: ({ record }: { record: FileItem }) => {
          const isEditing = editPath === record.path
          if (isEditing) {
            return h(Input, {
              modelValue: props.config.editingFileName || record.name,
              size: 'mini',
              class: 'file-name-edit-input',
              'onUpdate:modelValue': (val: string) => emit('nameUpdate', val),
              onBlur: () => emit('saveEditing', editPath!, props.config.editingFileName || record.name),
              onKeyup: (ev: KeyboardEvent) => {
                if (ev.key === 'Enter') emit('saveEditing', editPath!, props.config.editingFileName || record.name)
                else if (ev.key === 'Escape') emit('cancelEditing')
              },
              onClick: (ev: Event) => ev.stopPropagation()
            })
          }
          return h('span', { class: 'file-item-name', title: record.name }, record.name)
        }
      }

    case 'time':
      return {
        title: () => h('div', {
          class: 'th-sortable th-sort-right',
          onClick: () => emit('sort', 'modified_time')
        }, [
          h('span', { style: { fontWeight: 600 } }, '时间'),
          sortIcon('modified_time')()
        ]),
        dataIndex: 'modified_time',
        width: 125,
        align: 'right' as const,
        render: ({ record }: { record: FileItem }) => {
          if (editPath === record.path || !record.modified_time) return null
          return h('span', { class: 'file-item-time' }, formatFileTime(record.modified_time))
        }
      }

    case 'size':
      return {
        title: () => h('div', {
          class: 'th-sortable th-sort-right',
          onClick: () => emit('sort', 'size')
        }, [
          h('span', { style: { fontWeight: 600 } }, '大小'),
          sortIcon('size')()
        ]),
        dataIndex: 'size',
        width: 70,
        align: 'right' as const,
        render: ({ record }: { record: FileItem }) => {
          if (record.isDir || editPath === record.path) return null
          return h('span', { class: 'file-item-size' }, formatBytes(record.size))
        }
      }

    case 'fav':
      return {
        title: '',
        width: 28,
        render: ({ record }: { record: FileItem }) => {
          if (editPath === record.path) return null
          const favorited = props.favorites.includes(record.path)
          return h(Button, {
            type: 'text',
            size: 'mini',
            class: 'file-item-fav',
            onClick: (ev: Event) => { ev.stopPropagation(); emit('toggleFavorite', record) }
          }, {
            icon: () => favorited
              ? h(IconStarFill, { style: { color: '#ffcd00' } })
              : h(IconStar)
          })
        }
      }

    default:
      return null
  }
}

// ========== 动态表格列 ==========
const tableColumns = computed(() => {
  const editPath = props.config.editingFilePath
  return orderedColumns.value
    .filter(c => c.visible)
    .map(c => buildColumn(c.key, editPath))
    .filter(Boolean)
})

// ========== 分页 ==========
const currentPage = ref(1)
const pageSize = 100

const pagedFileList = computed(() => {
  const list = props.config.fileList
  const start = (currentPage.value - 1) * pageSize
  return list.slice(start, start + pageSize)
})

const totalPages = computed(() => Math.max(1, Math.ceil(props.config.fileList.length / pageSize)))

const onPageChange = (page: number) => {
  if (page < 1 || page > totalPages.value) return
  currentPage.value = page
}

// 当文件列表变化时重置到第1页
watch(() => props.config.fileList.length, () => { currentPage.value = 1 })

// ========== 行事件处理 ==========
const handleRowClick = (record: FileItem, ev: Event) => {
  const target = ev.target as HTMLElement
  if (target.closest('.arco-btn') || target.closest('.arco-input-wrapper')) return
  emit('fileClick', record)
}

const handleRowContextMenu = (record: FileItem, ev: Event) => {
  ev.preventDefault()
  emit('contextMenu', ev as MouseEvent, record)
}

const getRowClassName = (record: FileItem): string => [
  props.config.selectedFileItem?.path === record.path && 'row-selected',
  props.config.editingFilePath === record.path && 'row-editing'
].filter(Boolean).join(' ')

const handleWrapperContextMenu = (event: MouseEvent) => {
  emit('contextMenu', event, null)
}

const focusEditingItem = () => {
  nextTick(() => {
    const input = document.querySelector('.file-table .file-name-edit-input input') as HTMLInputElement | null
    if (!input) return
    input.focus()
    const val = input.value
    const dot = val.lastIndexOf('.')
    input.setSelectionRange(0, dot > 0 ? dot : val.length)
  })
}

defineExpose({ focusEditingItem })
</script>

<style scoped>
/* ====== 布局 ====== */
.file-list-panel {
  display: flex;
  flex-direction: column;
  flex: 1;           /* 父级是 flex 容器，用 flex:1 而非 height:100% */
  min-height: 0;     /* 允许收缩到小于内容高度 */
  background: var(--color-bg-1);
}

.panel-header {
  padding: 3px 12px;
  border-bottom: 1px solid var(--color-border);
  background: var(--color-bg-2);
  flex-shrink: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.panel-header-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.panel-title { font-size: 13px; font-weight: 600; color: var(--color-text-1); }
.panel-count { font-size: 12px; color: var(--color-text-3); }

.settings-btn {
  color: var(--color-text-3);
  padding: 2px 4px;
}
.settings-btn:hover {
  color: var(--color-text-2);
}

/* 列项排序图标 */
.col-sort-icon {
  margin-left: auto;
  font-size: 12px;
  color: var(--color-text-4);
  cursor: pointer;
  padding: 2px;
  border-radius: 3px;
  flex-shrink: 0;
  transition: all 0.15s;
}
.col-sort-icon:hover {
  background: var(--color-fill-2);
  color: var(--color-text-2);
}
.col-sort-active {
  color: rgb(var(--primary-6));
}

/* 滚动容器（table + 分页 的统一滚动层） */
.file-list-wrapper {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 0 2px;
}

/* ====== Table ====== */
.file-table {
  flex: 1;
  min-height: 0;
}
.file-table :deep(.arco-table) {
  font-size: 13px;
  table-layout: fixed;
}

.file-table :deep(.arco-table-cell) {
  padding: 5px 2px !important;
}

/* 表头样式 */
.file-table :deep(.arco-table-header) {
  border-bottom: 1px solid var(--color-border);
}

.file-table :deep(.arco-table-th) {
  font-size: 11px;
  color: var(--color-text-3);
  background: var(--color-bg-2);
  font-weight: normal;
  user-select: none;
  white-space: nowrap;
}

/* 可排序列头 */
.file-table :deep(.th-sortable) {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  cursor: pointer;
  border-radius: 3px;
  padding: 4px 8px;
  transition: background 0.15s;
}
.file-table :deep(.th-sortable:hover) {
  background: var(--color-fill-2);
}
.file-table :deep(.th-sort-right) { justify-content: flex-end; }
.file-table :deep(.th-sort-center) { justify-content: center; }

/* 表体行 */
.file-table :deep(.arco-table-tbody .arco-table-tr) {
  cursor: pointer;
  transition: background 0.15s;
}
.file-table :deep(.arco-table-tbody .arco-table-tr:hover:not(.row-selected)) {
  background: var(--color-fill-2);
}

/* 数据单元格 */
.file-table :deep(.arco-table-td) {
  border-bottom: 1px solid var(--color-border-2);
  vertical-align: middle;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 行状态 */
.file-table :deep(.arco-table-tr.row-selected) {
  background: var(--color-fill-3) !important;
}
.file-table :deep(.arco-table-tr.row-selected .file-item-name) {
  font-weight: 500;
}
.file-table :deep(.arco-table-tr.row-editing) {
  background: var(--color-fill-1);
}

/* ====== 列内容 ====== */
.col-icon { text-align: center; vertical-align: middle !important; }
.file-item-icon {
  font-size: 16px;
  line-height: 1;
  display: inline-block;
  font-weight: 500;
}
.file-item-name { font-size: 13px; color: var(--color-text-2); }
.file-item-size,
.file-item-time { font-size: 11px; color: var(--color-text-3); }

/* 收藏星标 */
.file-item-fav { opacity: 0.5; transition: opacity 0.2s; }
.file-table :deep(.arco-table-tr:hover .file-item-fav) { opacity: 1; }

/* 编辑输入框 */
.file-name-edit-input :deep(.arco-input) {
  font-size: 13px;
  padding: 0 8px;
  height: 24px;
  line-height: 24px;
}

/* ====== 列设置面板 ====== */
.col-setting-title {
  font-size: 12px;
  font-weight: 600;
  color: var(--color-text-2);
  padding: 4px 8px 6px;
  border-bottom: 1px solid var(--color-border-2);
  margin-bottom: 2px;
}

.col-setting-item {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 3px 6px;
  border-radius: 3px;
  cursor: grab;
  transition: background 0.15s;
}
.col-setting-item:active { cursor: grabbing; }
.col-setting-item:hover { background: var(--color-fill-1); }

.drag-handle {
  color: var(--color-text-4);
  font-size: 14px;
  user-select: none;
  flex-shrink: 0;
  line-height: 1;
}

/* 空状态 */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60px 20px;
  color: var(--color-text-3);
  gap: 8px;
}
.empty-state span:nth-child(2) { font-size: 14px; }

/* 分页栏（固定底部） */
.pagination-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 4px 10px;
  background: var(--color-bg-2);
  border-top: 1px solid var(--color-border);
  flex-shrink: 0;
}
.pagination-total {
  font-size: 12px;
  color: var(--color-text-3);
}
.pagination-nav {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
}
.page-btn {
  cursor: pointer;
  color: var(--color-text-2);
  padding: 0 3px;
  line-height: 1;
  user-select: none;
}
.page-btn:hover:not(.disabled) { color: rgb(var(--primary-6)); }
.page-btn.disabled { color: var(--color-text-4); cursor: default; }
.page-info { color: var(--color-text-2); min-width: 28px; text-align: center; }
</style>
