<template>
  <ElCard class="group-list-card" shadow="never">
    <div class="group-list-header">
      <ElInput
        v-model="keyword"
        :placeholder="t('dictionary.group.searchPlaceholder')"
        clearable
        @clear="handleSearch"
        @input="handleSearch"
      />
      <div class="group-actions">
        <ElButton type="primary" @click="openCreate">{{ t('dictionary.group.new') }}</ElButton>
        <ElButton @click="refresh">{{ t('dictionary.common.refresh') }}</ElButton>
      </div>
    </div>

    <ElScrollbar class="group-scroll">
      <div v-if="filteredGroups.length" class="group-list">
        <div
          v-for="group in filteredGroups"
          :key="group.id"
          class="group-item"
          :class="{ active: group.id === activeGroupId }"
          @click="selectGroup(group)"
        >
          <div class="group-info">
            <div class="group-name">{{ group.name }}</div>
            <div class="group-code">{{ group.code }}</div>
          </div>
          <div class="group-meta">
            <ElTag
              size="small"
              :type="group.scope === DictionaryScope.System ? 'primary' : 'success'"
            >
              {{
                group.scope === DictionaryScope.System
                  ? t('dictionary.common.system')
                  : t('dictionary.common.business')
              }}
            </ElTag>
            <ElDropdown trigger="click" @command="(command) => handleCommand(command, group)">
              <ElButton class="group-more" text @click.stop>
                <ElIcon><MoreFilled /></ElIcon>
              </ElButton>
              <template #dropdown>
                <ElDropdownMenu>
                  <ElDropdownItem command="edit">{{ t('dictionary.common.edit') }}</ElDropdownItem>
                  <ElDropdownItem command="delete" divided>{{
                    t('dictionary.common.delete')
                  }}</ElDropdownItem>
                </ElDropdownMenu>
              </template>
            </ElDropdown>
          </div>
        </div>
      </div>
      <div v-else class="group-empty">{{ t('dictionary.group.empty') }}</div>
    </ElScrollbar>
  </ElCard>

  <GroupFormDialog
    v-model="dialogVisible"
    :mode="dialogMode"
    :group="editingGroup"
    :default-scope="scope"
    :allow-scope-selection="allowScopeSelection"
    @success="handleDialogSuccess"
  />
</template>

<script setup lang="ts">
  import { computed, onMounted, ref, watch } from 'vue'
  import { useI18n } from 'vue-i18n'
  import { ElMessageBox, ElMessage } from 'element-plus'
  import { MoreFilled } from '@element-plus/icons-vue'
  import { useDictionaryGroupStore } from '@/store/modules/dictionaryGroup'
  import { DictionaryScope } from '@/enums/Dictionary'
  import GroupFormDialog from './GroupFormDialog.vue'

  defineOptions({ name: 'GroupList' })

  interface Props {
    scope?: DictionaryScope
    allowScopeSelection?: boolean
    pageSize?: number
  }

  const props = withDefaults(defineProps<Props>(), {
    scope: DictionaryScope.System,
    allowScopeSelection: true,
    pageSize: 200
  })

  const emit = defineEmits<{
    (event: 'select', group: Api.Dictionary.DictionaryGroupDto): void
  }>()

  const groupStore = useDictionaryGroupStore()
  const { t } = useI18n()
  const keyword = ref('')
  const dialogVisible = ref(false)
  const dialogMode = ref<'create' | 'edit'>('create')
  const editingGroup = ref<Api.Dictionary.DictionaryGroupDto | null>(null)

  const activeGroupId = computed(() => groupStore.currentGroup?.id ?? '')

  const filteredGroups = computed(() => {
    const search = keyword.value.trim().toLowerCase()
    const list = groupStore.groups
    if (!search) return list
    return list.filter(
      (group) =>
        group.code.toLowerCase().includes(search) || group.name.toLowerCase().includes(search)
    )
  })

  const fetchGroups = async () => {
    await groupStore.fetchGroups(props.scope, 1, props.pageSize)
    const list = groupStore.groups
    if (!list.length) {
      groupStore.currentGroup = null
      return
    }

    const current = groupStore.currentGroup
    if (!current || !list.some((group) => group.id === current.id)) {
      selectGroup(list[0])
      return
    }

    const matched = list.find((group) => group.id === current.id)
    selectGroup(matched ?? list[0])
  }

  const refresh = () => {
    fetchGroups()
  }

  const handleSearch = () => {
    // computed handles filtering
  }

  const selectGroup = (group: Api.Dictionary.DictionaryGroupDto) => {
    groupStore.currentGroup = group
    emit('select', group)
  }

  const openCreate = () => {
    dialogMode.value = 'create'
    editingGroup.value = null
    dialogVisible.value = true
  }

  const openEdit = (group: Api.Dictionary.DictionaryGroupDto) => {
    dialogMode.value = 'edit'
    editingGroup.value = group
    dialogVisible.value = true
  }

  const handleDelete = async (group: Api.Dictionary.DictionaryGroupDto) => {
    try {
      await ElMessageBox.confirm(
        t('dictionary.group.deleteConfirm'),
        t('dictionary.common.warning'),
        {
          type: 'warning',
          confirmButtonText: t('dictionary.common.confirm'),
          cancelButtonText: t('dictionary.common.cancel')
        }
      )
      const success = await groupStore.deleteGroup(group.id)
      if (success) {
        ElMessage.success(t('dictionary.group.deleteSuccess'))
      }
    } catch {
      // cancelled
    }
  }

  const handleCommand = (command: string, group: Api.Dictionary.DictionaryGroupDto) => {
    if (command === 'edit') {
      openEdit(group)
    } else if (command === 'delete') {
      handleDelete(group)
    }
  }

  const handleDialogSuccess = (group: Api.Dictionary.DictionaryGroupDto) => {
    fetchGroups().then(() => selectGroup(group))
  }

  watch(
    () => props.scope,
    () => {
      fetchGroups()
    }
  )

  onMounted(() => {
    fetchGroups()
  })
</script>

<style scoped>
  .group-list-card {
    display: flex;
    flex-direction: column;
    height: 100%;
  }

  .group-list-header {
    display: flex;
    flex-direction: column;
    gap: 12px;
  }

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

  .group-scroll {
    flex: 1;
    margin-top: 12px;
  }

  .group-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

  .group-item {
    box-sizing: border-box;
    display: flex;
    gap: 12px;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    min-width: 220px;
    padding: 10px 12px;
    cursor: pointer;
    background: #fff;
    border: 1px solid #ebeef5;
    border-radius: 12px;
    transition: all 0.15s ease;
  }

  .group-item:hover {
    border-color: #dcdfe6;
    box-shadow: 0 4px 14px rgb(64 158 255 / 8%);
  }

  .group-item.active {
    background: #f0f7ff;
    border-color: var(--el-color-primary);
  }

  .group-info {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }

  .group-name {
    font-weight: 600;
    color: #303133;
  }

  .group-code {
    font-size: 12px;
    color: #909399;
  }

  .group-meta {
    display: flex;
    gap: 6px;
    align-items: center;
  }

  .group-more {
    padding: 0 6px;
    line-height: 1;
  }

  .group-empty {
    padding: 24px 8px;
    color: #909399;
    text-align: center;
  }
</style>
