<!-- 顶部菜单搜索 -->
<template>
    <div class="header-search-icon" @click.stop="openSearch">
        <el-icon style="transform: scale(1.18)">
            <SearchOutlined />
        </el-icon>
    </div>

    <el-dialog
        v-model="visible"
        width="600px"
        :show-close="false"
        :modal="true"
        destroy-on-close
        class="menu-search-dialog"
        top="15vh"
        @closed="handleClosed"
        append-to-body
    >
        <div class="search-container">
            <div class="search-input-wrapper">
                <el-icon class="search-icon"><Search /></el-icon>
                <input
                    ref="inputRef"
                    v-model="searchVal"
                    class="search-input"
                    placeholder="搜索菜单..."
                    @input="handleInput"
                    @keydown.down.prevent="navigate(1)"
                    @keydown.up.prevent="navigate(-1)"
                    @keydown.enter.prevent="selectCurrent"
                />
            </div>

            <div
                class="search-results"
                v-show="options.length > 0 || searchVal"
            >
                <div v-if="options.length === 0" class="no-data"
                    >无匹配菜单</div
                >
                <div v-else class="result-list">
                    <div
                        v-for="(item, index) in options"
                        :key="item.path"
                        class="result-item"
                        :class="{ 'is-active': index === activeIndex }"
                        @mouseenter="activeIndex = index"
                        @click="selectItem(item)"
                    >
                        <div class="result-item-content">
                            <span
                                class="item-title"
                                v-html="highlightText(item.title, searchVal)"
                            ></span>
                            <span
                                class="item-path"
                                v-html="highlightText(item.path, searchVal)"
                            ></span>
                        </div>
                        <el-icon class="enter-icon"><Back /></el-icon>
                    </div>
                </div>
            </div>
        </div>
    </el-dialog>
</template>

<script setup>
    import { ref, nextTick, computed, onMounted, onUnmounted } from 'vue';
    import { useRouter } from 'vue-router';
    import { SearchOutlined } from '@/components/icons';
    import { Search, Back } from '@element-plus/icons-vue';
    import { useUserStore } from '@/store/modules/user';

    const router = useRouter();
    const userStore = useUserStore();

    const visible = ref(false);
    const searchVal = ref('');
    const options = ref([]);
    const inputRef = ref(null);
    const activeIndex = ref(0);

    // Flatten menus
    const flattenMenus = (menus, parentTitle = '') => {
        let result = [];
        if (!menus) return result;
        menus.forEach((menu) => {
            const title = parentTitle
                ? `${parentTitle} / ${menu.meta?.title}`
                : menu.meta?.title;
            // Only leaf nodes or actionable menus
            if (!menu.children || menu.children.length === 0) {
                if (!menu.meta?.hide) {
                    result.push({
                        title: title || menu.path,
                        path: menu.path
                    });
                }
            }
            if (menu.children && menu.children.length > 0) {
                result = result.concat(flattenMenus(menu.children, title));
            }
        });
        return result;
    };

    const allMenus = computed(() => flattenMenus(userStore.menus || []));

    const openSearch = () => {
        visible.value = true;
        searchVal.value = '';
        options.value = [];
        activeIndex.value = 0;
        nextTick(() => {
            inputRef.value?.focus();
        });
    };

    const handleClosed = () => {
        searchVal.value = '';
        options.value = [];
        activeIndex.value = 0;
    };

    const handleInput = () => {
        const query = searchVal.value.trim();
        if (query) {
            const lowerQuery = query.toLowerCase();
            options.value = allMenus.value.filter((item) => {
                return (
                    item.title.toLowerCase().includes(lowerQuery) ||
                    item.path.toLowerCase().includes(lowerQuery)
                );
            });
            activeIndex.value = 0; // Reset active index on new search
        } else {
            options.value = [];
        }
    };

    const navigate = (direction) => {
        if (options.value.length === 0) return;
        activeIndex.value += direction;
        if (activeIndex.value < 0) {
            activeIndex.value = options.value.length - 1;
        } else if (activeIndex.value >= options.value.length) {
            activeIndex.value = 0;
        }

        // Auto scroll
        nextTick(() => {
            const activeEl = document.querySelector('.result-item.is-active');
            if (activeEl) {
                activeEl.scrollIntoView({ block: 'nearest' });
            }
        });
    };

    const selectCurrent = () => {
        if (options.value.length > 0 && activeIndex.value >= 0) {
            selectItem(options.value[activeIndex.value]);
        }
    };

    const selectItem = (item) => {
        if (item && item.path) {
            router.push(item.path);
            visible.value = false;
        }
    };

    const highlightText = (text, query) => {
        if (!query || !text) return text;
        // Escape regex special characters
        const safeQuery = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
        const regex = new RegExp(`(${safeQuery})`, 'gi');
        return text.replace(regex, '<span class="highlight">$1</span>');
    };

    // Keyboard shortcut Ctrl+K / Cmd+K
    const handleKeydown = (e) => {
        if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
            e.preventDefault();
            openSearch();
        }
    };

    onMounted(() => {
        window.addEventListener('keydown', handleKeydown);
    });

    onUnmounted(() => {
        window.removeEventListener('keydown', handleKeydown);
    });
</script>

<style scoped>
    .header-search-icon {
        display: flex;
        align-items: center;
        justify-content: center;
        height: 100%;
        cursor: pointer;
    }

    .search-container {
        display: flex;
        flex-direction: column;
    }

    .search-input-wrapper {
        display: flex;
        align-items: center;
        padding: 0 16px;
        height: 60px;
        border-bottom: 1px solid var(--el-border-color-light);
    }

    .search-icon {
        font-size: 22px;
        color: var(--el-text-color-secondary);
        margin-right: 12px;
    }

    .search-input {
        flex: 1;
        height: 100%;
        border: none;
        outline: none;
        font-size: 18px;
        color: var(--el-text-color-primary);
        background: transparent;
    }

    .search-input::placeholder {
        color: var(--el-text-color-placeholder);
    }

    .search-results {
        max-height: 400px;
        overflow-y: auto;
        padding: 12px 0;
    }

    .no-data {
        padding: 30px 0;
        text-align: center;
        color: var(--el-text-color-secondary);
        font-size: 14px;
    }

    .result-list {
        display: flex;
        flex-direction: column;
        padding: 0 12px;
    }

    .result-item {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 12px 16px;
        margin-bottom: 8px;
        border-radius: 8px;
        cursor: pointer;
        transition: all 0.2s;
        background-color: var(--el-fill-color-blank);
        border: 1px solid var(--el-border-color-lighter);
    }

    .result-item:last-child {
        margin-bottom: 0;
    }

    .result-item.is-active,
    .result-item:hover {
        background-color: var(--el-color-primary-light-9);
        border-color: var(--el-color-primary-light-5);
    }

    .result-item-content {
        display: flex;
        flex-direction: column;
        gap: 4px;
    }

    .item-title {
        font-size: 14px;
        font-weight: 500;
        color: var(--el-text-color-primary);
    }

    .item-path {
        font-size: 12px;
        color: var(--el-text-color-secondary);
    }

    .enter-icon {
        opacity: 0;
        color: var(--el-color-primary);
        font-size: 16px;
        transform: scaleX(-1); /* Make it look like an enter key */
    }

    .result-item.is-active .enter-icon {
        opacity: 1;
    }

    /* Make highlight global so v-html can use it */
    :deep(.highlight) {
        color: var(--el-color-primary);
        font-weight: bold;
    }
</style>

<style>
    .menu-search-dialog {
        border-radius: 12px !important;
        overflow: hidden;
    }
    .menu-search-dialog .el-dialog__header {
        display: none;
    }
    .menu-search-dialog .el-dialog__body {
        padding: 0;
    }
</style>
