<script lang="ts" setup>
/**
 * 快捷入口（Premium）：角色钉住导航（图标瓷砖网格）+ 本地搜索全部授权菜单
 * 视觉：40px tinted 圆角图标容器，hover 抬升 + 容器着色加深；搜索结果行式列表
 * 数据源：钉住项走 admin/get-quick-menu；搜索池 = 钉住项 ∪ accessMenus 拍平叶子（纯本地，无接口）
 */
import type { SearchableMenuItem } from '../utils/flatten-menus';

import { computed, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';

import { IconifyIcon as VbenIcon } from '@vben/icons';
import { useAccessStore } from '@vben/stores';
import { openWindow } from '@vben/utils';

import { Input } from 'ant-design-vue';

import { getQuickMenuApi } from '#/views/system/admin/api';

import { filterMenusByKeyword, flattenMenus } from '../utils/flatten-menus';

interface Props {
  title: string;
}
defineProps<Props>();

/** 钉住的快捷导航项（角色配置） */
type PinnedItem = {
  title: string;
  icon: string;
  url: string;
  color?: string;
};

const router = useRouter();
const accessStore = useAccessStore();

const pinnedItems = ref<PinnedItem[]>([]);
const keyword = ref('');

/** 全部授权叶子菜单（本地拍平，一次计算） */
const searchableMenus = computed<SearchableMenuItem[]>(() =>
  flattenMenus(accessStore.accessMenus),
);

/**
 * 搜索结果：钉住项 ∪ 叶子菜单，按 path 去重
 */
const searchResults = computed<SearchableMenuItem[]>(() => {
  const kw = keyword.value.trim();
  if (!kw) return [];
  const fromPinned: SearchableMenuItem[] = pinnedItems.value
    .filter((item) => item.title.toLowerCase().includes(kw.toLowerCase()))
    .map((item) => ({ title: item.title, path: item.url, icon: item.icon }));
  const fromMenus = filterMenusByKeyword(searchableMenus.value, kw);
  const seen = new Set<string>();
  const merged: SearchableMenuItem[] = [];
  for (const item of [...fromPinned, ...fromMenus]) {
    if (!item.path || seen.has(item.path)) continue;
    seen.add(item.path);
    merged.push(item);
  }
  return merged;
});

/** 是否处于搜索态 */
const isSearching = computed(() => keyword.value.trim() !== '');

/**
 * 拉取角色钉住的快捷导航
 */
async function fetchPinned() {
  try {
    const res = await getQuickMenuApi();
    pinnedItems.value = Array.isArray(res) ? res : [];
  } catch {
    pinnedItems.value = [];
  }
}

/**
 * 跳转：外链新窗口，内部路由 push
 */
function navTo(url: string) {
  if (!url) return;
  if (url.startsWith('http')) {
    openWindow(url);
    return;
  }
  router.push(url).catch(() => {});
}

/**
 * 回车快捷跳转第一条搜索结果
 */
function onEnter() {
  const first = searchResults.value[0];
  if (first) navTo(first.path);
}

onMounted(fetchPinned);
</script>

<template>
  <div class="quick-entry">
    <div class="quick-entry__head">
      <div class="quick-entry__title-wrap">
        <span class="quick-entry__title-bar"></span>
        <span class="quick-entry__title">{{ title }}</span>
      </div>
      <Input
        v-model:value="keyword"
        allow-clear
        class="quick-entry__search"
        placeholder="搜索菜单，回车直达"
        @press-enter="onEnter"
      >
        <template #prefix>
          <VbenIcon class="quick-entry__search-icon" icon="lucide:search" />
        </template>
      </Input>
    </div>

    <!-- 搜索态：紧凑结果列表 -->
    <div v-if="isSearching" class="quick-entry__results">
      <template v-if="searchResults.length > 0">
        <div
          v-for="item in searchResults"
          :key="item.path"
          class="quick-entry__result-item"
          @click="navTo(item.path)"
        >
          <span class="quick-entry__result-icon-box">
            <VbenIcon :icon="item.icon || 'lucide:file'" class="quick-entry__result-icon" />
          </span>
          <span class="quick-entry__result-title">{{ item.title }}</span>
          <span class="quick-entry__result-path">{{ item.path }}</span>
          <VbenIcon class="quick-entry__result-arrow" icon="lucide:arrow-right" />
        </div>
      </template>
      <div v-else class="quick-entry__empty">
        <VbenIcon class="quick-entry__empty-icon" icon="lucide:search-x" />
        未找到匹配菜单
      </div>
    </div>

    <!-- 默认态：钉住项瓷砖网格 -->
    <div v-else-if="pinnedItems.length > 0" class="quick-entry__grid">
      <div
        v-for="item in pinnedItems"
        :key="item.url + item.title"
        class="quick-entry__cell"
        @click="navTo(item.url)"
      >
        <span class="quick-entry__cell-icon-box">
          <VbenIcon
            :icon="item.icon || 'lucide:link'"
            :style="item.color ? { color: item.color, opacity: 0.9 } : undefined"
            class="quick-entry__cell-icon"
          />
        </span>
        <span class="quick-entry__cell-title">{{ item.title }}</span>
      </div>
    </div>

    <div v-else class="quick-entry__empty">
      <VbenIcon class="quick-entry__empty-icon" icon="lucide:compass" />
      请在「角色管理」配置快捷导航，或直接搜索菜单
    </div>
  </div>
</template>

<style scoped>
.quick-entry {
  padding: 18px 20px;
  background: hsl(var(--card));
  border: 1px solid hsl(var(--border) / 0.7);
  border-radius: 12px;
}

.quick-entry__head {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

/* 标题前竖条：低成本的高级感层级标识 */
.quick-entry__title-wrap {
  display: flex;
  gap: 8px;
  align-items: center;
}

.quick-entry__title-bar {
  width: 3px;
  height: 14px;
  background: linear-gradient(180deg, hsl(var(--primary)), hsl(var(--primary) / 0.4));
  border-radius: 2px;
}

.quick-entry__title {
  font-size: 15px;
  font-weight: 650;
  color: hsl(var(--foreground));
  letter-spacing: -0.01em;
}

.quick-entry__search {
  max-width: 280px;
  border-radius: 8px;
}

.quick-entry__search-icon {
  width: 15px;
  height: 15px;
  color: hsl(var(--muted-foreground));
}

/* 瓷砖网格：桌面 8 列 → 平板 6 列 → 手机 4 列 */
.quick-entry__grid {
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 10px;
}

@media (max-width: 1024px) {
  .quick-entry__grid {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }
}

@media (max-width: 640px) {
  .quick-entry__grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.quick-entry__cell {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
  padding: 14px 4px 12px;
  cursor: pointer;
  border: 1px solid transparent;
  border-radius: 12px;
  transition:
    transform 0.2s cubic-bezier(0.4, 0, 0.2, 1),
    border-color 0.2s ease,
    background-color 0.2s ease,
    box-shadow 0.2s ease;
}

.quick-entry__cell:hover {
  background: hsl(var(--card));
  border-color: hsl(var(--primary) / 0.25);
  transform: translateY(-2px);
  box-shadow:
    0 1px 2px hsl(var(--foreground) / 0.04),
    0 8px 20px hsl(var(--primary) / 0.1);
}

/* 图标容器：tinted 圆角方块，hover 着色加深 */
.quick-entry__cell-icon-box {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  background: hsl(var(--primary) / 0.09);
  border-radius: 11px;
  transition: background-color 0.2s ease;
}

.quick-entry__cell:hover .quick-entry__cell-icon-box {
  background: hsl(var(--primary) / 0.16);
}

.quick-entry__cell-icon {
  width: 20px;
  height: 20px;
  color: hsl(var(--primary));
}

.quick-entry__cell-title {
  max-width: 100%;
  overflow: hidden;
  font-size: 12px;
  color: hsl(var(--foreground) / 0.85);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.quick-entry__results {
  max-height: 320px;
  overflow-y: auto;
}

.quick-entry__result-item {
  display: flex;
  gap: 10px;
  align-items: center;
  padding: 9px 12px;
  cursor: pointer;
  border-radius: 10px;
  transition: background-color 0.15s ease;
}

.quick-entry__result-item:hover {
  background: hsl(var(--primary) / 0.07);
}

.quick-entry__result-icon-box {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  background: hsl(var(--primary) / 0.09);
  border-radius: 8px;
  flex-shrink: 0;
}

.quick-entry__result-icon {
  width: 14px;
  height: 14px;
  color: hsl(var(--primary));
}

.quick-entry__result-title {
  font-size: 13px;
  font-weight: 500;
  color: hsl(var(--foreground));
  white-space: nowrap;
}

.quick-entry__result-path {
  flex: 1;
  overflow: hidden;
  font-size: 12px;
  color: hsl(var(--muted-foreground));
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 结果行箭头：hover 时滑入，提示可点 */
.quick-entry__result-arrow {
  width: 14px;
  height: 14px;
  color: hsl(var(--primary));
  opacity: 0;
  transform: translateX(-4px);
  transition:
    opacity 0.15s ease,
    transform 0.15s ease;
  flex-shrink: 0;
}

.quick-entry__result-item:hover .quick-entry__result-arrow {
  opacity: 1;
  transform: translateX(0);
}

.quick-entry__empty {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
  padding: 28px 0;
  font-size: 13px;
  color: hsl(var(--muted-foreground));
}

.quick-entry__empty-icon {
  width: 22px;
  height: 22px;
  color: hsl(var(--muted-foreground) / 0.6);
}

@media (prefers-reduced-motion: reduce) {
  .quick-entry__cell,
  .quick-entry__result-arrow {
    transition: none;
  }

  .quick-entry__cell:hover {
    transform: none;
  }
}
</style>
