<template>
  <div
    class="dropdown-item"
    @mouseenter="onHover"
    @mouseleave="onLeave"
    @click="onClick"
  >
    <div class="item-content">
      <icon-folder v-if="item.isDir" />
      <icon-file v-else />
      <span class="item-name">{{ item.name }}</span>
      <icon-right v-if="item.isDir" class="item-arrow" />
    </div>

    <!-- 子级菜单（递归） -->
    <Transition name="dropdown-fade">
      <div
        v-if="visible"
        class="sub-dropdown"
        :style="style"
        @mouseenter="onSubmenuHover"
        @mouseleave="onSubmenuLeave"
      >
        <div v-if="loading" class="dropdown-loading">
          <a-spin :size="16" />
          <span>加载中...</span>
        </div>
        <div v-else-if="error" class="dropdown-error">
          <icon-exclamation-circle />
          <span>{{ error }}</span>
        </div>
        <div v-else-if="!children.length" class="dropdown-empty">
          <icon-folder />
          <span>空文件夹</span>
        </div>
        <template v-else>
          <DropdownItem
            v-for="child in children"
            :key="child.path"
            :item="child"
            :level="level + 1"
            @navigate="emitNavigate"
            @openFile="emitOpenFile"
          />
        </template>
      </div>
    </Transition>
  </div>
</template>

<script setup lang="ts">
import { ref, inject, watch, type Ref } from 'vue'
import { IconRight, IconFolder, IconFile, IconExclamationCircle } from '@arco-design/web-vue/es/icon'
import { listDir } from '@/api/system'
import { sortFileList } from '@/utils/fileUtils'
import { useTimeout } from '@/composables/useTimeout'

interface Props {
  item: {
    name: string
    path: string
    isDir: boolean
  }
  level: number
}

const props = defineProps<Props>()

interface Emits {
  (e: 'navigate', path: string): void
  (e: 'openFile', path: string): void
}

const emit = defineEmits<Emits>()

const { setTimeout: delay, clearTimeout } = useTimeout()

const openMenus = inject<Ref<Map<number, string>>>('openMenus', ref(new Map()))
const closeMenu = inject<(level: number) => void>('closeMenu', () => {})

const visible = ref(false)
const loading = ref(false)
const error = ref('')
const children = ref<Array<{ name: string; path: string; isDir: boolean }>>([])
const style = ref<{ top: string; left: string }>({ top: '0px', left: '0px' })

const hoverTimer = ref<NodeJS.Timeout | null>(null)
const leaveTimer = ref<NodeJS.Timeout | null>(null)
const hoveringMenu = ref(false)

const menuKey = `menu-${props.item.path}-${props.level}`

watch(openMenus, (map) => {
  visible.value = map.get(props.level) === menuKey
}, { deep: true })

const loadChildren = async () => {
  if (!props.item.isDir) return

  loading.value = true
  error.value = ''

  try {
    const files = await listDir(props.item.path)
    children.value = sortFileList(files.map(f => ({
      name: f.name,
      path: f.path,
      isDir: f.isDir
    })))
  } catch (err) {
    console.error('[DropdownItem] 加载失败:', err)
    error.value = '加载失败'
  } finally {
    loading.value = false
  }
}

const openMenu = (rect: DOMRect) => {
  closeMenu(props.level)

  const newMap = new Map(openMenus.value)
  newMap.set(props.level, menuKey)
  openMenus.value = newMap

  style.value = {
    top: `${rect.top}px`,
    left: `${rect.right + 4}px`
  }

  visible.value = true
  loadChildren()
}

const scheduleClose = (ms: number) => {
  return delay(() => {
    if (!hoveringMenu.value) closeMenu(props.level)
  }, ms)
}

const onHover = (event: MouseEvent) => {
  if (!props.item.isDir) return

  hoveringMenu.value = false
  if (leaveTimer.value) clearTimeout(leaveTimer.value)

  const rect = (event.currentTarget as HTMLElement).getBoundingClientRect()
  hoverTimer.value = delay(() => openMenu(rect), 200)
}

const onLeave = () => {
  if (hoverTimer.value) clearTimeout(hoverTimer.value)
  leaveTimer.value = scheduleClose(200)
}

const onSubmenuHover = () => {
  hoveringMenu.value = true
  if (leaveTimer.value) clearTimeout(leaveTimer.value)
}

const onSubmenuLeave = () => {
  hoveringMenu.value = false
  leaveTimer.value = scheduleClose(100)
}

const onClick = (event: MouseEvent) => {
  if (leaveTimer.value) clearTimeout(leaveTimer.value)

  // 阻止事件冒泡，避免触发父级 breadcrumb-segment 的点击
  event.stopPropagation()

  const eventType = props.item.isDir ? 'navigate' : 'openFile'
  emit(eventType, props.item.path)
}

const emitNavigate = (path: string) => emit('navigate', path)
const emitOpenFile = (path: string) => emit('openFile', path)
</script>

<style scoped>
.dropdown-item {
  position: relative;
  display: flex;
  align-items: center;
  padding: 6px 8px;
  border-radius: var(--border-radius-small);
  cursor: pointer;
  transition: all 0.1s;
  font-size: 13px;
  color: var(--color-text-1);
  line-height: 1.5;
}

.item-content {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
}

.item-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.item-arrow {
  font-size: 12px;
  color: var(--color-text-3);
  flex-shrink: 0;
  margin-left: 4px;
}

.dropdown-item:hover {
  background: var(--color-fill-2);
}

/* 子级菜单 */
.sub-dropdown {
  position: fixed;
  min-width: 200px;
  max-width: 280px;
  max-height: 320px;
  overflow-y: auto;
  background: var(--color-bg-popup);
  border: 1px solid var(--color-border);
  border-radius: var(--border-radius-small);
  box-shadow: var(--shadow2-dropdown);
  z-index: calc(1000 + var(--level, 0));
  padding: 4px;
}

.dropdown-loading,
.dropdown-error,
.dropdown-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 16px;
  color: var(--color-text-3);
  font-size: 13px;
}

/* 动画 */
.dropdown-fade-enter-active,
.dropdown-fade-leave-active {
  transition: opacity 0.15s, transform 0.15s;
}

.dropdown-fade-enter-from,
.dropdown-fade-leave-to {
  opacity: 0;
  transform: translateY(-4px);
}

/* 滚动条 */
.sub-dropdown::-webkit-scrollbar {
  width: 6px;
}

.sub-dropdown::-webkit-scrollbar-track {
  background: transparent;
}

.sub-dropdown::-webkit-scrollbar-thumb {
  background: var(--color-fill-3);
  border-radius: 3px;
}

.sub-dropdown::-webkit-scrollbar-thumb:hover {
  background: var(--color-fill-4);
}
</style>
