<template>
  <ElCard class="item-table-card" shadow="never">
    <ArtTableHeader :loading="loading || dragLoading" layout="refresh">
      <template #left>
        <ElSpace wrap>
          <ElButton type="primary" :disabled="!currentGroup" @click="openCreate">
            {{ t('dictionary.item.new') }}
          </ElButton>
          <ElButton :disabled="!currentGroup" @click="openImport">
            {{ t('dictionary.item.import') }}
          </ElButton>
          <ElDropdown :disabled="!currentGroup" @command="handleExport">
            <ElButton>
              {{ t('dictionary.item.export') }}
              <ElIcon class="el-icon--right"><ArrowDown /></ElIcon>
            </ElButton>
            <template #dropdown>
              <ElDropdownMenu>
                <ElDropdownItem command="csv">CSV</ElDropdownItem>
                <ElDropdownItem command="json">JSON</ElDropdownItem>
              </ElDropdownMenu>
            </template>
          </ElDropdown>
          <ElButton @click="refreshItems" :disabled="!currentGroup">
            {{ t('dictionary.common.refresh') }}
          </ElButton>
        </ElSpace>
      </template>
    </ArtTableHeader>

    <ElTable
      ref="tableRef"
      class="dictionary-table"
      :data="pagedItems"
      :row-key="(row) => row.id"
      v-loading="loading || dragLoading"
      @cell-dblclick="handleCellDblClick"
    >
      <ElTableColumn width="40">
        <template #default>
          <span class="drag-handle"
            ><ElIcon><Rank /></ElIcon
          ></span>
        </template>
      </ElTableColumn>
      <ElTableColumn prop="key" :label="t('dictionary.common.key')" min-width="160" sortable />
      <ElTableColumn :label="t('dictionary.common.value')" min-width="200">
        <template #default="{ row }">
          {{ extractI18nText(row.value, locale) }}
        </template>
      </ElTableColumn>
      <ElTableColumn :label="t('dictionary.common.default')" width="100">
        <template #default="{ row }">
          <ElTag v-if="row.isDefault" size="small" type="success">
            {{ t('dictionary.common.default') }}
          </ElTag>
        </template>
      </ElTableColumn>
      <ElTableColumn :label="t('dictionary.common.enabled')" width="120">
        <template #default="{ row }">
          <ElSwitch v-model="row.isEnabled" @change="() => handleToggleEnabled(row)" />
        </template>
      </ElTableColumn>
      <ElTableColumn :label="t('dictionary.common.sortOrder')" width="140">
        <template #default="{ row }">
          <div class="sort-cell">
            <ElInputNumber
              v-if="editingSortId === row.id"
              v-model="editingSortValue"
              :min="0"
              :step="10"
              size="small"
              @blur="saveSortEdit(row)"
            />
            <span v-else>{{ row.sortOrder }}</span>
          </div>
        </template>
      </ElTableColumn>
      <ElTableColumn :label="t('dictionary.common.actions')" width="180" fixed="right">
        <template #default="{ row }">
          <div class="action-group">
            <button class="art-action-btn primary" @click="openEdit(row)">
              <ArtSvgIcon icon="ri:edit-2-line" class="art-action-icon" />
              <span>{{ t('dictionary.common.edit') }}</span>
            </button>
            <ElDropdown trigger="click" @command="(cmd) => cmd === 'delete' && handleDelete(row)">
              <button class="art-action-btn info">
                <ArtSvgIcon icon="ri:more-2-line" class="art-action-icon" />
                <span>{{ t('user.action.more') }}</span>
              </button>
              <template #dropdown>
                <ElDropdownMenu>
                  <ElDropdownItem command="delete">
                    <div class="flex items-center gap-2 text-danger">
                      <ArtSvgIcon icon="ri:delete-bin-line" />
                      <span>{{ t('dictionary.common.delete') }}</span>
                    </div>
                  </ElDropdownItem>
                </ElDropdownMenu>
              </template>
            </ElDropdown>
          </div>
        </template>
      </ElTableColumn>
    </ElTable>

    <ElPagination
      v-if="totalCount > 0"
      class="table-pagination"
      :current-page="pagination.page"
      :page-size="pagination.pageSize"
      :page-sizes="[20, 50, 100]"
      layout="total, sizes, prev, pager, next"
      :total="totalCount"
      @size-change="handlePageSizeChange"
      @current-change="handlePageChange"
    />
  </ElCard>

  <ItemFormDialog
    v-model="itemDialogVisible"
    :mode="itemDialogMode"
    :group-id="currentGroup?.id"
    :item="editingItem"
    @success="handleItemSaved"
  />

  <ImportDialog
    v-model="importDialogVisible"
    :group="currentGroup"
    @success="handleImportSuccess"
  />
</template>

<script setup lang="ts">
  import { ArrowDown, Rank } from '@element-plus/icons-vue'
  import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
  import { ElMessage } from 'element-plus'
  import { useI18n } from 'vue-i18n'
  import { useDraggable } from 'vue-draggable-plus'
  import { exportGroup } from '@/api/dictionary/group'
  import { extractI18nText } from '@/types/dictionary'
  import { useDictionaryItemStore } from '@/store/modules/dictionaryItem'
  import ArtTableHeader from '@/components/core/tables/art-table-header/index.vue'
  import ItemFormDialog from './ItemFormDialog.vue'
  import ImportDialog from './ImportDialog.vue'

  defineOptions({ name: 'ItemTable' })

  interface Props {
    group?: Api.Dictionary.DictionaryGroupDto | null
  }

  const props = defineProps<Props>()

  const { locale, t } = useI18n()
  const itemStore = useDictionaryItemStore()

  const tableRef = ref()
  const tableBodyRef = ref<HTMLElement | null>(null)
  const dragLoading = ref(false)
  const editingSortId = ref<string | null>(null)
  const editingSortValue = ref(0)
  const itemDialogVisible = ref(false)
  const itemDialogMode = ref<'create' | 'edit'>('create')
  const editingItem = ref<Api.Dictionary.DictionaryItemDto | null>(null)
  const importDialogVisible = ref(false)

  const pagination = ref({
    page: 1,
    pageSize: 50
  })

  const loading = computed(() => itemStore.loading)
  const currentGroup = computed(() => props.group ?? null)
  const totalCount = computed(() => itemStore.items.length)
  const pagedItems = ref<Api.Dictionary.DictionaryItemDto[]>([])

  const syncPagedItems = () => {
    const start = (pagination.value.page - 1) * pagination.value.pageSize
    const end = start + pagination.value.pageSize
    pagedItems.value = itemStore.items.slice(start, end)
  }

  const refreshItems = async () => {
    if (!currentGroup.value) return
    await itemStore.fetchItems(currentGroup.value.id)
  }

  const openCreate = () => {
    itemDialogMode.value = 'create'
    editingItem.value = null
    itemDialogVisible.value = true
  }

  const openEdit = (item: Api.Dictionary.DictionaryItemDto) => {
    itemDialogMode.value = 'edit'
    editingItem.value = item
    itemDialogVisible.value = true
  }

  const handleItemSaved = () => {
    syncPagedItems()
  }

  const handleDelete = async (item: Api.Dictionary.DictionaryItemDto) => {
    if (!currentGroup.value) return
    const success = await itemStore.deleteItem(currentGroup.value.id, item.id)
    if (success) {
      ElMessage.success(t('dictionary.item.deleteSuccess'))
      syncPagedItems()
    }
  }

  const openImport = () => {
    if (!currentGroup.value) {
      ElMessage.warning(t('dictionary.common.selectGroupFirst'))
      return
    }
    importDialogVisible.value = true
  }

  const handleImportSuccess = async () => {
    if (!currentGroup.value) return
    await itemStore.fetchItems(currentGroup.value.id)
    ElMessage.success(t('dictionary.item.importCompleted'))
  }

  const handleExport = async (format: 'csv' | 'json') => {
    if (!currentGroup.value) return
    const blob = await exportGroup(currentGroup.value.id, format)
    const url = URL.createObjectURL(blob)
    const link = document.createElement('a')
    const timestamp = new Date().toISOString().replace(/[:.]/g, '')
    link.href = url
    link.download = `${currentGroup.value.code}_${timestamp}.${format}`
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    URL.revokeObjectURL(url)
  }

  const handleToggleEnabled = async (item: Api.Dictionary.DictionaryItemDto) => {
    if (!currentGroup.value) return
    await itemStore.updateItem(currentGroup.value.id, item.id, {
      key: item.key,
      value: item.value,
      isDefault: item.isDefault,
      isEnabled: item.isEnabled,
      sortOrder: item.sortOrder,
      description: item.description ?? null,
      rowVersion: item.rowVersion
    })
  }

  const handleCellDblClick = (row: Api.Dictionary.DictionaryItemDto, column: any) => {
    if (column.property === 'sortOrder') {
      editingSortId.value = row.id
      editingSortValue.value = row.sortOrder
      nextTick(() => {
        const input = tableRef.value?.$el?.querySelector(
          '.sort-cell input'
        ) as HTMLInputElement | null
        input?.focus()
      })
    }
  }

  const saveSortEdit = async (item: Api.Dictionary.DictionaryItemDto) => {
    if (!currentGroup.value) return
    if (editingSortId.value !== item.id) return
    editingSortId.value = null
    if (editingSortValue.value === item.sortOrder) return

    await itemStore.updateItem(currentGroup.value.id, item.id, {
      key: item.key,
      value: item.value,
      isDefault: item.isDefault,
      isEnabled: item.isEnabled,
      sortOrder: editingSortValue.value,
      description: item.description ?? null,
      rowVersion: item.rowVersion
    })
  }

  const handleDragEnd = async () => {
    if (!currentGroup.value) return

    dragLoading.value = true
    try {
      const start = (pagination.value.page - 1) * pagination.value.pageSize
      const updated = [...itemStore.items]
      updated.splice(start, pagedItems.value.length, ...pagedItems.value)
      itemStore.items = updated

      const updates = updated.map((item, index) => ({
        item,
        sortOrder: (index + 1) * 10
      }))

      await Promise.all(
        updates.map(({ item, sortOrder }) =>
          itemStore.updateItem(currentGroup.value!.id, item.id, {
            key: item.key,
            value: item.value,
            isDefault: item.isDefault,
            isEnabled: item.isEnabled,
            sortOrder,
            description: item.description ?? null,
            rowVersion: item.rowVersion
          })
        )
      )

      ElMessage.success(t('dictionary.item.sortUpdated'))
      syncPagedItems()
    } finally {
      dragLoading.value = false
    }
  }

  const { start, destroy } = useDraggable(tableBodyRef, pagedItems, {
    handle: '.drag-handle',
    animation: 150,
    ghostClass: 'drag-ghost',
    immediate: false,
    onEnd: handleDragEnd
  })

  const initDraggable = async () => {
    await nextTick()
    tableBodyRef.value = tableRef.value?.$el?.querySelector('.el-table__body-wrapper tbody') || null
    if (tableBodyRef.value) {
      destroy()
      start(tableBodyRef.value)
    }
  }

  const handlePageChange = (page: number) => {
    pagination.value.page = page
    syncPagedItems()
    initDraggable()
  }

  const handlePageSizeChange = (size: number) => {
    pagination.value.pageSize = size
    pagination.value.page = 1
    syncPagedItems()
    initDraggable()
  }

  watch(
    () => itemStore.items,
    () => syncPagedItems(),
    { deep: true }
  )

  watch(
    () => currentGroup.value?.id,
    async (groupId) => {
      pagination.value.page = 1
      if (!groupId) {
        itemStore.reset()
        syncPagedItems()
        initDraggable()
        return
      }
      await itemStore.fetchItems(groupId)
      syncPagedItems()
      initDraggable()
    },
    { immediate: true }
  )

  onMounted(() => {
    syncPagedItems()
    initDraggable()
  })

  onBeforeUnmount(() => {
    destroy()
  })
</script>

<style scoped>
  .item-table-card {
    display: flex;
    flex-direction: column;
    gap: 12px;
    height: 100%;
  }

  .dictionary-table {
    width: 100%;
  }

  .drag-handle {
    font-size: 16px;
    color: #909399;
    cursor: grab;
  }

  .action-group {
    display: flex;
    gap: 8px;
  }

  .table-pagination {
    display: flex;
    justify-content: flex-end;
    margin-top: 16px;
  }

  .sort-cell {
    display: inline-flex;
    align-items: center;
    min-height: 28px;
  }

  :deep(.drag-ghost) {
    background: #ecf5ff;
    opacity: 0.7;
  }
</style>
