<script setup lang="ts">
import { NTreeSelect, type TreeSelectOption } from 'naive-ui'
import { computed, ref, watch } from 'vue'

import type { Compartment } from '@/types/api'

/** 区间选择器:按 parentId 组树,与官方控制台一致分层展示;
 *  父级不在列表中的节点视为根 compartment 的直接子级,根以 value='' 表示。 */
const props = withDefaults(
  defineProps<{
    value: string
    compartments: Compartment[]
    rootLabel: string
    loading?: boolean
    disabled?: boolean
    size?: 'small' | 'medium'
  }>(),
  { size: 'small' },
)
const emit = defineEmits<{ 'update:value': [string] }>()

function groupByParent(list: Compartment[]): Map<string, Compartment[]> {
  const ids = new Set(list.map((c) => c.id))
  const map = new Map<string, Compartment[]>()
  for (const c of list) {
    const parent = ids.has(c.parentId) ? c.parentId : ''
    map.set(parent, [...(map.get(parent) ?? []), c])
  }
  for (const arr of map.values()) arr.sort((a, b) => a.name.localeCompare(b.name, 'zh-CN'))
  return map
}

function toNodes(map: Map<string, Compartment[]>, parent: string): TreeSelectOption[] | undefined {
  const list = map.get(parent)
  if (!list) return undefined
  return list.map((c) => ({ label: c.name, key: c.id, children: toNodes(map, c.id) }))
}

const tree = computed<TreeSelectOption[]>(() => {
  const map = groupByParent(props.compartments)
  return [{ label: props.rootLabel, key: '', children: toNodes(map, '') }]
})

/** 选项异步加载,default-expand-all 不可靠,改为受控展开全部父节点 */
const expandedKeys = ref<Array<string | number>>([])
watch(
  tree,
  (nodes) => {
    const keys: string[] = []
    const walk = (list: TreeSelectOption[]) => {
      for (const n of list) {
        if (!n.children?.length) continue
        keys.push(String(n.key))
        walk(n.children)
      }
    }
    walk(nodes)
    expandedKeys.value = keys
  },
  { immediate: true },
)

function onUpdate(v: string | number | Array<string | number> | null) {
  emit('update:value', typeof v === 'string' ? v : '')
}
</script>

<template>
  <NTreeSelect
    class="min-w-0"
    :value="value"
    :options="tree"
    :expanded-keys="expandedKeys"
    :loading="loading"
    :disabled="disabled"
    :size="size"
    :indent="18"
    :consistent-menu-width="false"
    filterable
    @update:value="onUpdate"
    @update:expanded-keys="(keys: Array<string | number>) => (expandedKeys = keys)"
  />
</template>
