<template>
  <div class="bitable-file-list-view">
    <!-- Top bar -->
    <div class="bitable-file-list-view__topbar">
      <div class="bitable-file-list-view__topbar-left">
        <a-button type="text" :icon="h(ArrowLeftOutlined)" @click="goBack" />
        <span class="bitable-file-list-view__title">多维表格</span>
      </div>
      <div class="bitable-file-list-view__topbar-right">
        <a-button type="primary" :icon="h(PlusOutlined)" @click="createOpen = true">
          新建文件
        </a-button>
      </div>
    </div>

    <!-- Body: file grid -->
    <div class="bitable-file-list-view__body">
      <a-spin :spinning="store.isLoading">
        <div v-if="store.files.length > 0" class="bitable-file-list-view__grid">
          <FileCard
            v-for="file in store.files"
            :key="file.id"
            :file="file"
            @open="handleOpen"
            @rename="handleRename"
            @delete="handleDelete"
          />
        </div>

        <a-empty
          v-else-if="!store.isLoading"
          description="还没有多维表格文件，点击右上角新建"
          class="bitable-file-list-view__empty"
        />
      </a-spin>
    </div>

    <!-- Create file modal -->
    <FileCreateModal
      :open="createOpen"
      @success="handleCreated"
      @cancel="createOpen = false"
    />

    <!-- Rename modal -->
    <a-modal
      :open="renameOpen"
      title="重命名文件"
      :confirm-loading="renaming"
      @ok="handleRenameOk"
      @cancel="renameOpen = false"
    >
      <a-form layout="vertical">
        <a-form-item label="图标">
          <a-select v-model:value="renameForm.icon" :options="iconSelectOptions">
            <template #option="{ value: optValue }">
              <span class="bitable-file-list-view__option">
                <component
                  :is="resolveBitableIcon(optValue)"
                  class="bitable-file-list-view__option-icon"
                />
                <span>{{ labelForKey(optValue) }}</span>
              </span>
            </template>
            <template #label="{ value: labelValue }">
              <span class="bitable-file-list-view__option">
                <component
                  :is="resolveBitableIcon(labelValue)"
                  class="bitable-file-list-view__option-icon"
                />
                <span>{{ labelForKey(labelValue) }}</span>
              </span>
            </template>
          </a-select>
        </a-form-item>
        <a-form-item label="文件名">
          <a-input v-model:value="renameForm.name" :maxlength="100" />
        </a-form-item>
        <a-form-item label="描述">
          <a-textarea v-model:value="renameForm.description" :rows="2" :maxlength="500" />
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, h, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { Modal as AModal } from 'ant-design-vue'
import { ArrowLeftOutlined, PlusOutlined } from '@ant-design/icons-vue'
import { useBitableStore } from '@/stores/bitable'
import type { IBitableFile } from '@/api/bitable'
import FileCard from '@/components/bitable/FileCard.vue'
import FileCreateModal from '@/components/bitable/FileCreateModal.vue'
import {
  BITABLE_ICON_OPTIONS,
  DEFAULT_BITABLE_ICON,
  resolveBitableIcon,
  type BitableIconKey,
} from '@/components/bitable/bitableIcons'

const router = useRouter()
const store = useBitableStore()

const createOpen = ref(false)
const renameOpen = ref(false)
const renaming = ref(false)

/**
 * ``icon`` accepts any string here because legacy DB rows may still
 * contain the old emoji values (clipboard-emoji etc.). The select options only
 * show the new Bitable icon keys; the resolver maps unknown values to
 * the default ``table`` icon at render time.
 */
const renameForm = reactive({
  id: '',
  icon: DEFAULT_BITABLE_ICON as BitableIconKey | string,
  name: '',
  description: '',
})

const iconSelectOptions = computed(() =>
  BITABLE_ICON_OPTIONS.map((o) => ({ value: o.value, label: o.label })),
)

function labelForKey(key: string): string {
  return BITABLE_ICON_OPTIONS.find((o) => o.value === key)?.label ?? key
}

onMounted(() => {
  store.loadFiles()
})

function goBack(): void {
  router.push('/agent/chat')
}

function handleOpen(fileId: string): void {
  router.push(`/bitable/${fileId}`)
}

function handleCreated(fileId: string): void {
  createOpen.value = false
  router.push(`/bitable/${fileId}`)
}

function handleRename(file: IBitableFile): void {
  renameForm.id = file.id
  renameForm.icon = file.icon
  renameForm.name = file.name
  renameForm.description = file.description
  renameOpen.value = true
}

async function handleRenameOk(): Promise<void> {
  if (!renameForm.name.trim()) return
  renaming.value = true
  try {
    await store.updateFile(renameForm.id, {
      name: renameForm.name.trim(),
      icon: renameForm.icon,
      description: renameForm.description.trim(),
    })
    renameOpen.value = false
  } finally {
    renaming.value = false
  }
}

function handleDelete(file: IBitableFile): void {
  AModal.confirm({
    title: '删除文件',
    content: `确定删除「${file.name}」吗？该文件下的所有数据表都将被删除，此操作不可恢复。`,
    okText: '删除',
    okType: 'danger',
    cancelText: '取消',
    onOk: async () => {
      await store.deleteFile(file.id)
    },
  })
}
</script>

<style scoped>
.bitable-file-list-view {
  display: flex;
  flex-direction: column;
  height: 100vh;
  width: 100vw;
  overflow: hidden;
  background: var(--bitable-color-bg-secondary);
}

.bitable-file-list-view__topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--bitable-spacing-sm) var(--bitable-spacing-lg);
  background: var(--bitable-color-bg);
  border-bottom: 1px solid var(--bitable-color-border);
  flex-shrink: 0;
}

.bitable-file-list-view__topbar-left {
  display: flex;
  align-items: center;
  gap: 8px;
}

.bitable-file-list-view__topbar-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.bitable-file-list-view__title {
  font-weight: 600;
  font-size: 16px;
}

.bitable-file-list-view__body {
  flex: 1;
  overflow: auto;
  padding: 24px;
}

.bitable-file-list-view__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 16px;
  max-width: 1400px;
  margin: 0 auto;
}

.bitable-file-list-view__empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 80px 0;
}

.bitable-file-list-view__option {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.bitable-file-list-view__option-icon {
  font-size: var(--bitable-font-lg);
  color: var(--bitable-color-primary);
}
</style>
