<script setup>
import { ref, watch, nextTick, onMounted, onUnmounted } from "vue";

const props = defineProps({
  visible: Boolean,
  position: {
    type: Object,
    default: () => ({ x: 0, y: 0 }),
  },
  items: {
    type: Array,
    default: () => [],
  },
});

const emit = defineEmits(["close", "select"]);

const menuRef = ref(null);
const adjustedPosition = ref({ x: 0, y: 0 });
const hoveredItem = ref(null);
const submenuPositions = ref(new Map());
const hideTimer = ref(null); // 添加隐藏定时器

// 计算菜单位置，处理边界问题
const calculatePosition = () => {
  if (!menuRef.value || !props.visible) return;

  const menu = menuRef.value;
  const menuRect = menu.getBoundingClientRect();
  const windowWidth = window.innerWidth;
  const windowHeight = window.innerHeight;

  let x = props.position.x;
  let y = props.position.y;

  // 右边界检测
  if (x + menuRect.width > windowWidth - 10) {
    x = x - menuRect.width;
  }

  // 底边界检测
  if (y + menuRect.height > windowHeight - 10) {
    y = windowHeight - menuRect.height - 10;
  }

  // 左边界检测
  if (x < 10) {
    x = 10;
  }

  // 顶边界检测
  if (y < 10) {
    y = 10;
  }

  adjustedPosition.value = { x, y };
};

// 计算子菜单位置
const calculateSubmenuPosition = (itemElement, itemIndex) => {
  if (!itemElement || !menuRef.value) return { x: 0, y: 0, direction: "right" };

  const itemRect = itemElement.getBoundingClientRect();
  const menuRect = menuRef.value.getBoundingClientRect();
  const windowWidth = window.innerWidth;
  const windowHeight = window.innerHeight;

  // 预估子菜单宽度（可以根据实际情况调整）
  const submenuWidth = 200;
  const submenuHeight = 300; // 预估高度

  let x = itemRect.right + 4;
  // 直接使用菜单项相对于主菜单容器的偏移量
  let y = itemElement.offsetTop;
  let direction = "right";

  // 右边界检测，如果右侧空间不足，显示在左侧
  if (x + submenuWidth > windowWidth - 10) {
    x = itemRect.left - submenuWidth - 4;
    direction = "left";
  }

  // 底边界检测 - 基于子菜单的绝对位置检查
  const absoluteSubmenuBottom = itemRect.top + submenuHeight;
  if (absoluteSubmenuBottom > windowHeight - 10) {
    // 计算可用的最大Y位置（相对于主菜单）
    const maxAbsoluteY = windowHeight - submenuHeight - 10;
    const maxRelativeY = maxAbsoluteY - menuRect.top;
    y = Math.max(0, maxRelativeY);
  }

  // 左边界检测
  if (x < 10) {
    x = 10;
    direction = "right";
  }

  // 确保 y 不为负数
  if (y < 0) {
    y = 0;
  }

  y = 0;

  const position = { x, y, direction };
  submenuPositions.value.set(itemIndex, position);
  return position;
};

// 清除隐藏定时器
const clearHideTimer = () => {
  if (hideTimer.value) {
    clearTimeout(hideTimer.value);
    hideTimer.value = null;
  }
};

// 显示子菜单
const showSubmenu = (item, index, element) => {
  if (item.children && item.children.length > 0) {
    clearHideTimer();
    hoveredItem.value = index;
    nextTick(() => {
      calculateSubmenuPosition(element, index);
    });
  }
};

// 隐藏子菜单（延迟）
const hideSubmenu = (index) => {
  clearHideTimer();
  hideTimer.value = setTimeout(() => {
    if (hoveredItem.value === index) {
      hoveredItem.value = null;
    }
  }, 150);
};

// 处理鼠标进入菜单项
const handleItemMouseEnter = (item, index, event) => {
  const element = event.target.closest(".context-menu-item");
  showSubmenu(item, index, element);
};

// 处理鼠标在菜单项内移动
const handleItemMouseMove = (item, index, event) => {
  // 如果当前菜单项有子菜单但子菜单未显示，则显示子菜单
  if (item.children && item.children.length > 0 && hoveredItem.value !== index) {
    const element = event.target.closest(".context-menu-item");
    showSubmenu(item, index, element);
  }
};

// 处理鼠标离开菜单项
const handleItemMouseLeave = (item, index) => {
  // 只有当有子菜单时才延迟隐藏
  if (item.children && item.children.length > 0) {
    hideSubmenu(index);
  } else {
    hoveredItem.value = null;
  }
};

// 处理鼠标进入子菜单
const handleSubmenuMouseEnter = (index) => {
  clearHideTimer();
  hoveredItem.value = index;
};

// 处理鼠标离开子菜单
const handleSubmenuMouseLeave = (index) => {
  hideSubmenu(index);
};

// 监听可见性和位置变化
watch([() => props.visible, () => props.position], () => {
  if (props.visible) {
    nextTick(() => {
      calculatePosition();
    });
  } else {
    hoveredItem.value = null;
    submenuPositions.value.clear();
  }
});

// 处理菜单项点击
const handleItemClick = (item, index) => {
  if (item.disabled || item.type === "divider") return;

  // 如果有子菜单，不关闭菜单
  if (item.children && item.children.length > 0) {
    return;
  }

  emit("select", item, index);

  if (item.action) {
    item.action();
  }

  emit("close");
};

// 处理子菜单项点击
const handleSubItemClick = (subItem, parentIndex, subIndex) => {
  if (subItem.disabled || subItem.type === "divider") return;

  emit("select", subItem, `${parentIndex}-${subIndex}`);

  if (subItem.action) {
    subItem.action();
  }

  emit("close");
};

// 处理外部点击关闭
const handleOutsideClick = (event) => {
  if (menuRef.value && !menuRef.value.contains(event.target)) {
    emit("close");
  }
};

// 处理 ESC 键关闭
const handleEscKey = (event) => {
  if (event.key === "Escape") {
    emit("close");
  }
};

onMounted(() => {
  document.addEventListener("click", handleOutsideClick, true);
  document.addEventListener("contextmenu", handleOutsideClick, true);
  document.addEventListener("keydown", handleEscKey);
});

onUnmounted(() => {
  document.removeEventListener("click", handleOutsideClick, true);
  document.removeEventListener("contextmenu", handleOutsideClick, true);
  document.removeEventListener("keydown", handleEscKey);
});
</script>

<template>
  <teleport to="body">
    <transition name="context-menu">
      <div
        v-if="visible"
        ref="menuRef"
        class="context-menu"
        :style="{
          top: `${adjustedPosition.y}px`,
          left: `${adjustedPosition.x}px`,
        }"
        @contextmenu.prevent
      >
        <template v-for="(item, index) in items" :key="index">
          <!-- 分隔线 -->
          <div v-if="item.type === 'divider'" class="context-menu-divider"></div>

          <!-- 菜单项 -->
          <div
            v-else
            class="context-menu-item"
            :class="{
              disabled: item.disabled,
              danger: item.danger,
              'has-children': item.children && item.children.length > 0,
              hovered: hoveredItem === index,
            }"
            @click="handleItemClick(item, index)"
            @mouseenter="handleItemMouseEnter(item, index, $event)"
            @mousemove="handleItemMouseMove(item, index, $event)"
            @mouseleave="handleItemMouseLeave(item, index)"
          >
            <span class="context-menu-icon" v-if="item.icon">
              <SvgIcon
                :name="item.icon"
                size="14"
                :style="{
                  transform: item.inverIcon ? `rotate(90deg)` : 'none',
                }"
              />
            </span>
            <span class="context-menu-label">{{ item.label }}</span>
            <span class="context-menu-shortcut" v-if="item.shortcut">
              {{ item.shortcut }}
            </span>
            <span class="context-menu-arrow" v-if="item.children && item.children.length > 0">
              <SvgIcon name="CRight" size="12" />
            </span>

            <!-- 子菜单 -->
            <transition name="context-submenu">
              <div
                v-if="item.children && item.children.length > 0 && hoveredItem === index"
                class="context-submenu"
                :class="{
                  'submenu-left': submenuPositions.get(index)?.direction === 'left',
                }"
                @mouseenter="handleSubmenuMouseEnter(index)"
                @mouseleave="handleSubmenuMouseLeave"
              >
                <template v-for="(subItem, subIndex) in item.children" :key="subIndex">
                  <!-- 子菜单分隔线 -->
                  <div v-if="subItem.type === 'divider'" class="context-menu-divider"></div>

                  <!-- 子菜单项 -->
                  <div
                    v-else
                    class="context-menu-item"
                    :class="{
                      disabled: subItem.disabled,
                      danger: subItem.danger,
                    }"
                    @click="handleSubItemClick(subItem, index, subIndex)"
                  >
                    <span class="context-menu-icon" v-if="subItem.icon">
                      <SvgIcon
                        :name="subItem.icon"
                        size="14"
                        :style="{
                          transform: subItem.inverIcon ? `rotate(90deg)` : 'none',
                        }"
                      />
                    </span>
                    <span class="context-menu-label">{{ subItem.label }}</span>
                    <span class="context-menu-shortcut" v-if="subItem.shortcut">
                      {{ subItem.shortcut }}
                    </span>
                  </div>
                </template>
              </div>
            </transition>
          </div>
        </template>
      </div>
    </transition>
  </teleport>
</template>

<style scoped lang="less">
@import "./contextMenu.less";
</style>
