<template>
    <div class="qr-suggest-container" @mousemove="handleMouseMove">
        <template v-if="flatItems.length">
            <div v-for="(group, groupIdx) in groupedItems" :key="groupIdx" class="qr-suggest-group">
                <div class="qr-suggest-group-title" :title="group.name">{{ group.name }}</div>

                <template v-for="item in group.items" :key="item.__flatIndex">
                    <!-- 文本 -->
                    <div v-if="!item.format || item.format === 'text'" :ref="(el) => bindItemRef(el, item.__flatIndex)"
                        :class="['qr-suggest-item', { 'is-active': item.__flatIndex === selectedIndex }]"
                        :title="item.content" @click="handleSelect(item.__flatIndex)"
                        @mouseenter="handleMouseEnter(item.__flatIndex)">
                        <span class="qr-suggest-item-title">
                            <HighLight :text="item.title" :highlight="query" type="title" />
                        </span>
                        <span class="qr-suggest-item-content">
                            <HighLight :text="item.content" :highlight="query" />
                        </span>
                    </div>

                    <!-- 图片 -->
                    <div v-else-if="item.format === 'image'" :ref="(el) => bindItemRef(el, item.__flatIndex)"
                        :class="['qr-suggest-item', 'qr-suggest-item--media', { 'is-active': item.__flatIndex === selectedIndex }]"
                        @click="handleSelect(item.__flatIndex)" @mouseenter="handleMouseEnter(item.__flatIndex)">
                        <span class="qr-suggest-item-title">
                            <HighLight :text="item.title" :highlight="query" type="title" />
                        </span>
                        <img class="qr-suggest-item-thumb" :src="item.thumbImage || item.content" :alt="item.title" />
                    </div>

                    <!-- 视频 -->
                    <div v-else-if="item.format === 'video'" :ref="(el) => bindItemRef(el, item.__flatIndex)"
                        :class="['qr-suggest-item', 'qr-suggest-item--media', { 'is-active': item.__flatIndex === selectedIndex }]"
                        @click="handleSelect(item.__flatIndex)" @mouseenter="handleMouseEnter(item.__flatIndex)">
                        <span class="qr-suggest-item-title">
                            <HighLight :text="item.title" :highlight="query" type="title" />
                        </span>
                        <img class="qr-suggest-item-thumb" :src="item.thumbImage || videoThumbnailFallback"
                            :alt="item.title" />
                    </div>
                </template>
            </div>
        </template>
        <div v-else class="qr-suggest-empty">{{ emptyText }}</div>
    </div>
</template>

<script setup lang="ts">
import { computed, nextTick, ref, watch } from 'vue';
import HighLight from './HighLight.vue';
import videoThumbnailFallback from './videoThumbnail.png';

interface QuickReplyFlatItem {
    id: string;
    content: string;
    title: string;
    group: string;
    format: string;
    thumbImage: string;
}

interface QuickReplyPropItem extends QuickReplyFlatItem {
    __flatIndex: number;
}

interface Props {
    items: QuickReplyFlatItem[];
    query?: string;
    command: (payload: { id: string; content: string; format: string; thumbImage: string }) => void;
}

const props = defineProps<Props>();

const emptyText = '暂无数据';

const selectedIndex = ref(0);
const isKeyboardControl = ref(false);
const itemRefs = ref<Record<number, HTMLDivElement | null>>({});

const flatItems = computed<QuickReplyPropItem[]>(() => {
    const groupMap: Record<string, QuickReplyFlatItem[]> = {};
    props.items.forEach((item) => {
        const key = item.group || '';
        if (!groupMap[key]) groupMap[key] = [];
        groupMap[key].push(item);
    });

    const result: QuickReplyPropItem[] = [];
    let flatIndex = 0;
    Object.keys(groupMap).forEach((groupName) => {
        (groupMap[groupName] ?? []).forEach((it) => {
            result.push({ ...it, __flatIndex: flatIndex });
            flatIndex += 1;
        });
    });
    return result;
});

const groupedItems = computed(() => {
    const map = new Map<string, QuickReplyPropItem[]>();
    flatItems.value.forEach((item) => {
        const key = item.group || '';
        if (!map.has(key)) map.set(key, []);
        map.get(key)!.push(item);
    });
    return Array.from(map.entries()).map(([name, items]) => ({ name, items }));
});

const bindItemRef = (el: any, index: number) => {
    itemRefs.value[index] = el as HTMLDivElement | null;
};

const scrollToSelected = () => {
    const el = itemRefs.value[selectedIndex.value];
    if (el && typeof el.scrollIntoView === 'function') {
        el.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
    }
};

watch(selectedIndex, () => {
    nextTick(scrollToSelected);
});

watch(
    () => props.items,
    () => {
        selectedIndex.value = 0;
        isKeyboardControl.value = false;
    },
);

const selectByIndex = (index: number) => {
    const target = flatItems.value.find((it) => it.__flatIndex === index);
    if (!target) return;
    props.command({
        id: target.id,
        content: target.content,
        format: target.format || 'text',
        thumbImage: target.thumbImage || '',
    });
};

const handleSelect = (index: number) => {
    selectByIndex(index);
};

const handleMouseEnter = (index: number) => {
    if (!isKeyboardControl.value) {
        selectedIndex.value = index;
    }
};

const handleMouseMove = () => {
    isKeyboardControl.value = false;
};

const upHandler = () => {
    if (!flatItems.value.length) return;
    isKeyboardControl.value = true;
    const len = flatItems.value.length;
    selectedIndex.value = (selectedIndex.value + len - 1) % len;
};

const downHandler = () => {
    if (!flatItems.value.length) return;
    isKeyboardControl.value = true;
    const len = flatItems.value.length;
    selectedIndex.value = (selectedIndex.value + 1) % len;
};

const enterHandler = () => {
    if (!flatItems.value.length) return;
    selectByIndex(selectedIndex.value);
};

// 供 suggestion.ts 通过 ref 调用
const onKeyDown = ({ event }: { event: KeyboardEvent }) => {
    if (event.key === 'ArrowUp') {
        upHandler();
        return true;
    }
    if (event.key === 'ArrowDown') {
        downHandler();
        return true;
    }
    if (event.key === 'Enter') {
        if (!flatItems.value.length) return true;
        enterHandler();
        event.stopPropagation();
        return true;
    }
    return false;
};

defineExpose({ onKeyDown });
</script>

<style scoped>
.qr-suggest-container {
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.05), 0 10px 20px rgba(0, 0, 0, 0.1);
    color: rgba(0, 0, 0, 0.85);
    font-size: 13px;
    overflow: hidden auto;
    padding: 6px 4px;
    max-height: 300px;
    min-width: 360px;
    max-width: 640px;
    box-sizing: border-box;
    scrollbar-width: thin;
    scrollbar-color: rgba(0, 0, 0, 0.15) transparent;
}

.qr-suggest-container::-webkit-scrollbar {
    width: 4px;
}

.qr-suggest-container::-webkit-scrollbar-track {
    background: transparent;
}

.qr-suggest-container::-webkit-scrollbar-thumb {
    background: rgba(0, 0, 0, 0.15);
    border-radius: 4px;
}

.qr-suggest-container::-webkit-scrollbar-thumb:hover {
    background: rgba(0, 0, 0, 0.25);
}

.qr-suggest-group {
    margin-bottom: 6px;
}

.qr-suggest-group:last-child {
    margin-bottom: 0;
}

.qr-suggest-group-title {
    display: none;
}

.qr-suggest-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 10px;
    margin: 0 2px;
    border-radius: 6px;
    cursor: pointer;
    background: transparent;
    line-height: 20px;
    white-space: nowrap;
    overflow: hidden;
}

.qr-suggest-item.is-active {
    background: #f2f7ff;
}

.qr-suggest-item-title {
    flex-shrink: 0;
    font-size: 12px;
    font-weight: 500;
    color: #1d2129;
    max-width: 140px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.qr-suggest-item-content {
    flex: 1;
    min-width: 0;
    font-size: 12px;
    color: #4e5969;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.qr-suggest-item-thumb {
    width: 20px;
    height: 20px;
    object-fit: cover;
    border-radius: 4px;
    flex-shrink: 0;
    background: #e7eaf0;
}

.qr-suggest-item-tag {
    padding: 0 6px;
    height: 18px;
    line-height: 18px;
    border-radius: 4px;
    background: #f0f2f7;
    color: #86909c;
    font-size: 11px;
    flex-shrink: 0;
}

.qr-suggest-empty {
    padding: 10px 14px;
    color: rgba(0, 0, 0, 0.4);
    font-size: 13px;
}
</style>
