<template>
  <div
    v-if="uiStore.contextMenu.isOpen"
    class="context-menu-overlay"
    @click="close"
    @contextmenu.prevent="close"
  >
    <div ref="menuRef" class="context-menu" :style="menuStyle">
      <ul v-if="uiStore.contextMenu.itemType === 'icon'">
        <li class="layout-section">
          <div class="layout-title">
            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="menu-icon"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><line x1="3" y1="9" x2="21" y2="9"></line><line x1="9" y1="21" x2="9" y2="9"></line></svg>
            <span>布局</span>
          </div>
          <div class="widget-size-options">
            <span v-for="size in iconSizes" :key="size" @click="changeIconSize(size)" class="size-option">{{ size }}</span>
          </div>
        </li>
        <li><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="menu-icon"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>在新标签页打开</li>
        <li @click="handleEditIcon"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="menu-icon"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"></path><path d="m15 5 4 4"></path></svg>编辑图标</li>
        <li><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="menu-icon"><path d="m12 19-7-7 7-7 7 7-7 7Z"></path><path d="M19 5v14"></path><path d="M5 5v14"></path></svg>编辑主页</li>
        <li class="menu-danger" @click="deleteItem"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="menu-icon"><path d="M3 6h18"></path><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"></path><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>删除</li>
      </ul>
      <ul v-else-if="uiStore.contextMenu.itemType === 'widget'">
        <li class="layout-section">
          <div class="layout-title">
            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="menu-icon"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><line x1="3" y1="9" x2="21" y2="9"></line><line x1="9" y1="21" x2="9" y2="9"></line></svg>
            <span>布局</span>
          </div>
          <div class="widget-size-options">
            <span v-for="size in widgetSizes" :key="size" @click="changeWidgetSize(size)" class="size-option">{{ size }}</span>
          </div>
        </li>
        <li @click="handleEditWidget"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="menu-icon"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"></path></svg>编辑组件</li>
        <li class="menu-danger" @click="deleteItem"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="menu-icon"><path d="M3 6h18"></path><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"></path><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>删除</li>
      </ul>
      <ul v-else-if="uiStore.contextMenu.itemType === 'desktop'" class="desktop-menu">
        <li class="desktop-item" @click="handleDesktopAction('add-icon')">
          <span class="desktop-label">添加图标</span>
          <span class="desktop-trailing">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="menu-trailing-icon"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
          </span>
        </li>
        <li class="desktop-item" @click="handleDesktopAction('wallpaper')">
          <span class="desktop-label">换壁纸</span>
          <span class="desktop-trailing">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="menu-trailing-icon"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="menu-trailing-icon"><path d="M20.8 4.6a5.5 5.5 0 0 0-7.8 0L12 5.6l-1-1a5.5 5.5 0 0 0-7.8 7.8l1 1L12 21l7.8-7.6 1-1a5.5 5.5 0 0 0 0-7.8z"></path></svg>
          </span>
        </li>
        <li class="desktop-item" @click="handleDesktopAction('search')">
          <span class="desktop-label">本地搜索</span>
          <span class="desktop-shortcut">Ctrl+F</span>
        </li>
        <li class="desktop-item" @click="handleDesktopAction('backup')">
          <span class="desktop-label">立即备份</span>
          <span class="desktop-trailing">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="menu-trailing-icon"><path d="M20 16.5a4.5 4.5 0 0 0-1.4-8.8A6 6 0 0 0 6 9.8a4 4 0 0 0 0 8h13.5z"></path><polyline points="12 12 12 19"></polyline><polyline points="9 16 12 19 15 16"></polyline></svg>
          </span>
        </li>
        <li class="desktop-item" @click="handleDesktopAction('settings')">
          <span class="desktop-label">设置</span>
          <span class="desktop-trailing">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="menu-trailing-icon"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.65 1.65 0 0 0-1.8-.3 1.65 1.65 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.65 1.65 0 0 0-1-1.5 1.65 1.65 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.65 1.65 0 0 0 .3-1.8 1.65 1.65 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.65 1.65 0 0 0 1.5-1 1.65 1.65 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.65 1.65 0 0 0 1.8.3H9a1.65 1.65 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.65 1.65 0 0 0 1 1.5 1.65 1.65 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.65 1.65 0 0 0-.3 1.8V9a1.65 1.65 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.65 1.65 0 0 0-1.5 1z"></path></svg>
          </span>
        </li>
      </ul>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
import { useUIStore } from '@/store/useUIStore';
import { useLayoutStore } from '@/store/useLayoutStore';
import { useWidgetsStore } from '@/store/useWidgetsStore';

const emit = defineEmits<{
  (event: 'add-icon'): void;
  (event: 'edit-icon', id: string): void;
  (event: 'edit-widget', id: string): void;
  (event: 'settings'): void;
}>();

const uiStore = useUIStore();
const layoutStore = useLayoutStore();
const widgetsStore = useWidgetsStore();

type ItemSize = '1x1' | '1x2' | '2x1' | '2x2' | '2x4';

type DesktopAction = 'add-icon' | 'wallpaper' | 'search' | 'backup' | 'settings';

const widgetSizes: ItemSize[] = ['1x1', '1x2', '2x1', '2x2', '2x4'];
const iconSizes: ItemSize[] = ['1x1', '1x2', '2x1', '2x2', '2x4'];

const menuRef = ref<HTMLElement | null>(null);
const menuPosition = ref({ x: 0, y: 0 });
const viewportPadding = 8;

const clampMenuPosition = () => {
  const menuEl = menuRef.value;
  const baseX = uiStore.contextMenu.x;
  const baseY = uiStore.contextMenu.y;
  if (!menuEl) {
    menuPosition.value = { x: baseX, y: baseY };
    return;
  }
  const rect = menuEl.getBoundingClientRect();
  const maxX = Math.max(viewportPadding, window.innerWidth - rect.width - viewportPadding);
  const maxY = Math.max(viewportPadding, window.innerHeight - rect.height - viewportPadding);
  const x = Math.min(Math.max(baseX, viewportPadding), maxX);
  const y = Math.min(Math.max(baseY, viewportPadding), maxY);
  menuPosition.value = { x, y };
};

const menuStyle = computed(() => ({
  left: `${menuPosition.value.x}px`,
  top: `${menuPosition.value.y}px`,
}));

watch(
  () => [
    uiStore.contextMenu.isOpen,
    uiStore.contextMenu.x,
    uiStore.contextMenu.y,
    uiStore.contextMenu.itemType,
  ],
  async () => {
    if (!uiStore.contextMenu.isOpen) return;
    await nextTick();
    clampMenuPosition();
  }
);

onMounted(() => {
  window.addEventListener('resize', clampMenuPosition);
});

onUnmounted(() => {
  window.removeEventListener('resize', clampMenuPosition);
});

const close = () => {
  uiStore.closeContextMenu();
};

const deleteItem = () => {
  if (uiStore.contextMenu.itemId) {
    if (uiStore.contextMenu.itemType === 'icon') {
      layoutStore.deleteIcon(uiStore.contextMenu.itemId);
    } else if (uiStore.contextMenu.itemType === 'widget') {
      widgetsStore.deleteWidget(uiStore.contextMenu.itemId);
    }
  }
  close();
};

const handleEditIcon = () => {
  if (uiStore.contextMenu.itemType !== 'icon') return;
  if (uiStore.contextMenu.itemId) {
    emit('edit-icon', uiStore.contextMenu.itemId);
  }
  close();
};

const handleEditWidget = () => {
  if (uiStore.contextMenu.itemType !== 'widget') return;
  if (uiStore.contextMenu.itemId) {
    emit('edit-widget', uiStore.contextMenu.itemId);
  }
  close();
};

const changeWidgetSize = (newSize: ItemSize) => {
  if (uiStore.contextMenu.itemId) {
    widgetsStore.updateWidgetSize(uiStore.contextMenu.itemId, newSize);
  }
  close();
};

const changeIconSize = (newSize: ItemSize) => {
  if (uiStore.contextMenu.itemId) {
    layoutStore.updateIconSize(uiStore.contextMenu.itemId, newSize);
  }
  close();
};

const handleDesktopAction = (action: DesktopAction) => {
  if (action === 'add-icon') {
    emit('add-icon');
  }
  if (action === 'settings') {
    emit('settings');
  }
  close();
};
</script>

<style lang="scss" scoped>
@import '@/styles/tokens.scss';

.context-menu-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: $z-index-menu - 1;
}

.context-menu {
  position: absolute;
  width: var(--context-menu-width);
  background-color: $color-surface-2;
  backdrop-filter: blur($backdrop-filter-blur) saturate($backdrop-filter-saturation);
  border-radius: $border-radius-medium;
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: $shadow-lg;
  z-index: $z-index-menu;
  padding: var(--context-menu-padding);
  transform-origin: top left;
  animation: context-menu-pop 110ms cubic-bezier(0.16, 1, 0.3, 1);

  ul {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  li {
    display: flex;
    align-items: center;
    padding: var(--context-menu-item-padding-y) var(--context-menu-item-padding-x);
    border-radius: $border-radius-small;
    cursor: pointer;
    color: $color-text-primary;
    font-size: 14px;

    &:hover {
      background-color: rgba(255, 255, 255, 0.1);
    }

    &.layout-section {
      padding: var(--context-menu-layout-section-padding-y) var(--context-menu-layout-section-padding-x);
      flex-direction: column;
      align-items: stretch;
      cursor: default;
      &:hover {
        background-color: transparent;
      }
    }
  }

  li.menu-danger {
    color: #ff5c5c;

    .menu-icon {
      stroke: #ff5c5c;
    }
  }

  .menu-icon {
    margin-right: var(--context-menu-icon-margin-right);
    width: var(--context-menu-icon-size);
    height: var(--context-menu-icon-size);
  }
}

@keyframes context-menu-pop {
  0% {
    opacity: 0;
    transform: scale(0.92);
  }
  100% {
    transform: scale(1);
  }
}

.layout-title {
  display: flex;
  align-items: center;
  font-size: 14px;
  margin-bottom: var(--context-menu-layout-title-margin-bottom);
}

.widget-size-options {
  display: flex;
  flex-wrap: wrap;
  gap: var(--context-menu-layout-options-gap);

  .size-option {
    display: flex;
    justify-content: center;
    align-items: center;
    width: var(--context-menu-layout-option-width);
    padding: var(--context-menu-layout-option-padding-y) 0;
    border-radius: var(--radius-pill);
    background-color: rgba(255, 255, 255, 0.08);
    cursor: pointer;
    font-size: 12px;

    &:hover {
      background-color: rgba(255, 255, 255, 0.15);
    }
  }
}

.desktop-menu {
  .desktop-item {
    justify-content: space-between;
    gap: 12px;
  }
}

.desktop-label {
  font-size: 14px;
}

.desktop-trailing {
  display: flex;
  align-items: center;
  gap: 8px;
  color: $color-text-secondary;
}

.menu-trailing-icon {
  width: 16px;
  height: 16px;
  stroke: currentColor;
}

.desktop-shortcut {
  font-size: 12px;
  color: $color-text-secondary;
}
</style>
