<template>
    <div 
        class="search-result"
        :class="{'-height': menuData?.blocks?.[1]?.fields?.event_list?.length > 0}"
    >
        <!-- <ElementsBack /> -->
        <ElementsHome />
        <div class="container">
            <!-- 搜尋標題 -->
            <section class="search-result__top">
                <h1>
                    {{ searchText }} {{ catText }}的搜尋結果 ({{ searchTotalCount || 0 }})
                    <ClientOnly>
                        <span v-if="env === 'dev' || env === 'sit'">Debug用，搜尋詞組：{{ searchTextToTokenizer.replace(/,$/g, '') }}
                            <Teleport to="body">
                                <div class="debug__tokenizer" v-if="showDebugTokenizer">
                                    <div @click="showDebugTokenizer = false">詞庫數量：{{ tokenizerData.length }}，點擊關閉</div>
                                    <div v-for="item in tokenizerData" :key="item">
                                        {{ item }}
                                    </div>
                                </div>
                            </Teleport>
                            <button @click="showDebugTokenizer = !showDebugTokenizer">{{ showDebugTokenizer ? '隱藏' : '顯示' }}詞庫</button>
                        </span>
                        
                        
                    </ClientOnly>
                </h1>
            </section>

            <!-- 標籤列 + 搜尋結果列表（同時被 loading 覆蓋） -->
            <div class="search-result__body">
                <div v-if="!allFetched" class="search-result__body-overlay">
                    <div class="loading-spinner"></div>
                </div>
                <div 
                    class="search-result__top-navs"
                    :class="{ '-loading': searchLoading }"
                >
                    <ul>
                        <li
                            v-for="item in searchNavList"
                            :key="item.link"
                        >
                            <NuxtLink 
                                :to="{
                                    path: '/search/result',
                                    query: {
                                        limit: 12,
                                        type: item.type,
                                        keyword: searchText
                                    }
                                }" 
                                :class="{ 
                                    active: item.active,
                                    '-disabled': allFetched && allTotals[item.type] === 0
                                }"
                            >
                                {{ item.text }}
                                <span class="nav-count">({{ allTotals[item.type] }})</span>
                            </NuxtLink>
                        </li>
                    </ul>
                    <ElementsDropdownlist 
                        v-if="queryType !== 'post'"
                        :orderlist="orderList"
                        @update:order="handleOrderChange"
                    />
                </div>
            <section class="search-result__list">
                <div v-if="searchResult?.length > 0" 
                    class="search-result__items"
                >
                
                    <div class="list-3" v-if="queryType === 'post'">
                        <CardPost
                            v-for="item in searchResult" 
                            :key="item.id"
                            :data="item"
                        />
                    </div>
                    <div class="list-3" v-else-if="queryType === 'fund'">
                        <CardProdFund v-for="item in searchResult" :key="item.FUND_ID" :data="item" />
                    </div>
                    <div class="list-3" v-else-if="queryType === 'bond'">
                        <CardProdBond v-for="item in searchResult" :key="item.BOND_ID + item.manual_info.TICKER" :data="item" />
                    </div>
                    <div class="list-3" v-else-if="queryType === 'stock'">
                        <CardProdStock v-for="item in searchResult" :key="item.FUND_ID" :data="item" />
                    </div>
                    <div class="list-3" v-else-if="queryType === 'etf'">
                        <CardProdEtf v-for="item in searchResult" :key="item.FUND_ID" :data="item" />
                    </div>
                </div>
                <div v-else-if="allFetched">
                    <div class="search-result__noresult">
                        該分類無搜尋結果，你可以逛逛其他分類
                    </div>
                </div>
            </section>
            </div>
            <div 
                class="search-result__more"
                v-if="limit < searchTotalCount && !readMoreLoading"
            >
                <ElementsButton
                    :data="{
                        text: '查看更多',
                    }" 
                    @click="readMoreSearchResult"
                />
            </div>
            <div class="search-result__more-loading" v-if="readMoreLoading">
                <div class="loading-spinner"></div>
            </div>
        </div>
        <Footer />
    </div>
</template>
<script setup>
    const showDebugTokenizer = ref(false)

    const { $LCscroll } = useNuxtApp()
    const siteInfoData = useSiteInfoData()
    const menuData = computed(() => siteInfoData.value.header)
    const route = useRoute()
    const searchText = ref(route.query.keyword.trim())
    const tokenizerData = ref((siteInfoData.value?.tagStrings?.split(',')) || [])
    const currentOrder = ref(route.query.order ? route.query.order : '')
    // 優先級：URL type > 前頁商品類別(from) > 基金
    const queryType = ref(route.query.type || route.query.from || 'fund')
    const orderList = useProductOrderList(queryType.value) // 拿到排序
    const catText = ref('基金')
    const env = ref('')
    const resultPerPage = 12

    // 每個分類各自的狀態
    const allTypes = ['fund', 'stock', 'etf', 'bond', 'post']
    const allResults = ref(Object.fromEntries(allTypes.map(t => [t, []])))
    const allTotals = ref(Object.fromEntries(allTypes.map(t => [t, 0])))
    const allLoading = ref(Object.fromEntries(allTypes.map(t => [t, true])))
    const allReadMoreLoading = ref(Object.fromEntries(allTypes.map(t => [t, false])))
    const allLimits = ref(Object.fromEntries(allTypes.map(t => [t, resultPerPage])))

    // 當前分類的 computed
    const searchResult = computed(() => allResults.value[queryType.value] || [])
    const searchTotalCount = computed(() => allTotals.value[queryType.value] || 0)
    const searchLoading = computed(() => allLoading.value[queryType.value])
    const limit = computed(() => allLimits.value[queryType.value])
    const readMoreLoading = computed(() => allReadMoreLoading.value[queryType.value])
    const allFetched = computed(() => allTypes.every(t => !allLoading.value[t]))

    /* --------------------------------
    搜尋標題選單
    -------------------------------- */
    const searchNavList = ref([
        {
            text: '基金',
            link: '/fund',
            type: 'fund',
            active: false
        }, {
            text: '海外股票',
            link: '/overseas-stock',
            type: 'stock',
            active: false
        }, {
            text: 'ETF',
            link: '/etf',
            type: 'etf',
            active: false
        }, {
            text: '債券',
            link: '/bond',
            type: 'bond',
            active: false
        }, {
            text: '文章',
            link: '/article',
            type: 'post',
            active: false
        }
    ])
    
    /* --------------------------------
    更換時重新初始資料
    -------------------------------- */
    const changeActive = () => {
        queryType.value = route.query.type || route.query.from || 'fund'
        searchNavList.value.forEach(nav => nav.active = false)
        searchNavList.value.find(item => item.type === queryType.value).active = true

        // 初始化排序
        if (queryType.value !== 'post') {
            orderList.value = useProductOrderList(queryType.value).value
            orderList.value = orderList.value.filter(item => item.value !== 'CUS_RANK') // 移除 CUS_RANK

            if (!route.query.order) {
                orderList.value[0].active = true // 第一個排序啟動
                currentOrder.value = orderList.value[0].value
            } else {
                orderList.value.forEach(item => {
                    item.active = item.value === currentOrder.value
                })
            }
        }
    }

    /* --------------------------------
    同義詞資料 API
    -------------------------------- */
    const { data: phrasesData } = await useAsyncData('relatedPhreasesData', () => 
        $fetch('/api/get_single_type', {
            params: {
                id: 'related_phrases',
            },
        }), {
            transform: (res) => {
                if (!res?.blocks?.[0]?.fields) {
                    return []
                }
                return {
                    phrases: res.blocks[0].fields.related_phrases_info,
                    noPhrases: res.blocks[1].fields.no_search_list
                }
            }
        }
    )

    /* --------------------------------
    將同義詞加入到詞庫
    (如果 phrase 包含 ` 符號，拆分成陣列)
    -------------------------------- */
    const forPushPhrases = phrasesData.value?.phrases?.map(item => {
        if (item.phrase.includes('`')) {
            return item.phrase.split('`')
        }
        return item.phrase
    }).flat() || []
    tokenizerData.value = [...new Set([...tokenizerData.value, ...forPushPhrases])]

    // 產品 TAG 加入到詞組
    const { data: tagsData } = await useAsyncData('tagListData', () => 
        $fetch('/api/get_single_type', {
            params: {
                id: 'product_tag',
            },
        }), {
            transform: (res) => {
                const tags = res.blocks[0].fields.tag_list.map(tag => tag.title)
                return tags
            }
        }
    )
    tokenizerData.value = [...new Set([...tokenizerData.value, ...(tagsData.value || [])])]
    
    /* --------------------------------
    分詞器
    將資料丟入分詞邏輯裡面處理
    -------------------------------- */
    const searchTextToTokenizer = computed(() => keywordTokenizer({
        searchText: searchText.value,
        phrasesData: phrasesData.value,
        tokenizerData: tokenizerData.value
    }))

    /* --------------------------------
    排序切換
    -------------------------------- */
    const handleOrderChange = (order) => {
        currentOrder.value = order
        orderList.value.forEach(item => {
            item.active = item.value === order
        })
        navigateTo({
            path: '/search/result',
            query: {
                ...route.query,
                order: order
            }
        })
        console.log('order', order, orderList.value)
    }
    

    /* --------------------------------
    單一分類搜尋
    -------------------------------- */
    const fetchSingleType = async (type, isReadMore = false) => {
        if (!isReadMore) {
            allResults.value[type] = []
            allLoading.value[type] = true
        } else {
            allReadMoreLoading.value[type] = true
        }

        const typeLimit = allLimits.value[type]
        const typeOrder = type === queryType.value ? currentOrder.value : ''

        try {
            if (type === 'post') {
                const res = await $fetch('/api/get_search_post', {
                    method: 'GET',
                    params: {
                        id: 'markets,resources',
                        page: 1,
                        limit: typeLimit,
                        search: encodeURIComponent(searchTextToTokenizer?.value?.replace(/,$/g, ''))
                    }
                })
                console.log('文章搜尋結果', res)
                allResults.value[type] = res.postList
                allTotals.value[type] = res.total
            } else {
                const res = await $fetch('/api/get_search_product', {
                    method: 'GET',
                    params: {
                        product: type === 'stock' ? 'equity' : type,
                        page: 1,
                        limit: typeLimit,
                        sortingType: typeOrder,
                        search: encodeURIComponent(searchTextToTokenizer.value.replace(/,$/g, ''))
                    }
                })
                console.log(`[${type}] 搜尋結果`, res.productList.length, '筆，看更仔細請自己去 Network 看')
                allResults.value[type] = res.productList
                allTotals.value[type] = res.total
            }
        } catch (err) {
            console.log(`[${type}] 搜尋錯誤`, err)
            allResults.value[type] = []
        } finally {
            allLoading.value[type] = false
            allReadMoreLoading.value[type] = false
        }
    }

    /* --------------------------------
    一次撈取所有分類
    -------------------------------- */
    const searchFetch = async () => {
        $LCscroll.stop() // 防止畫面亂亂跳
        changeActive()
        searchText.value = route.query.keyword

        // 重置所有分類的 limit
        allTypes.forEach(t => { allLimits.value[t] = resultPerPage })

        // 並行撈取所有分類
        await Promise.all(allTypes.map(type => fetchSingleType(type)))
        $LCscroll.start()
    }


    /* --------------------------------
    查看更多（只針對當前分類）
    -------------------------------- */
    const readMoreSearchResult = () => {
        allLimits.value[queryType.value] += resultPerPage
        fetchSingleType(queryType.value, true)
    }

    /* --------------------------------
    撈取完畢後自動跳轉至第一個有結果的商品分類
    （文章不列入自動跳轉順序）
    若有 from 參數，以 from 分類為優先，再依預設順序遍歷
    -------------------------------- */
    const baseJumpOrder = ['fund', 'stock', 'etf', 'bond']
    watch(allFetched, (fetched) => {
        if (!fetched) return
        if (allTotals.value[queryType.value] > 0) return
        if (!baseJumpOrder.includes(queryType.value)) return

        // 若有前頁類別，以該類別為首，其餘依預設順序補齊
        const fromType = route.query.from
        const jumpOrder = fromType
            ? [fromType, ...baseJumpOrder.filter(t => t !== fromType)]
            : baseJumpOrder

        const target = jumpOrder.find(t => allTotals.value[t] > 0)
        if (!target) return

        queryType.value = target
        changeActive()
        catText.value = searchNavList.value.find(item => item.type === target)?.text || ''
        navigateTo({
            path: '/search/result',
            query: { ...route.query, type: target }
        })
    })

    /* --------------------------------
    監聽 Router 變化
    -------------------------------- */
    watch(() => route.query, (newQuery, oldQuery) => {
        const isOnlyTypeChanged =
            newQuery.keyword === oldQuery.keyword &&
            newQuery.type !== oldQuery.type &&
            Object.keys({ ...newQuery, ...oldQuery })
                .filter(k => k !== 'type')
                .every(k => newQuery[k] === oldQuery[k])

        const isOnlyOrderChanged =
            newQuery.order !== oldQuery.order &&
            newQuery.keyword === oldQuery.keyword &&
            newQuery.type === oldQuery.type

        if (isOnlyTypeChanged) {
            // 切換分類 tab：只更新 active 狀態，直接顯示已快取資料
            queryType.value = newQuery.type || 'fund'
            changeActive()
            catText.value = searchNavList.value.find(item => item.type === queryType.value)?.text || '基金'
            return
        }

        if (isOnlyOrderChanged) {
            // 排序變更：只重新撈當前分類
            currentOrder.value = newQuery.order || ''
            changeActive()
            fetchSingleType(queryType.value)
            catText.value = searchNavList.value.find(item => item.type === queryType.value)?.text || '基金'
            return
        }

        // 關鍵字變更：重新撈取所有分類
        searchFetch()
        catText.value = searchNavList.value.find(item => item.type === queryType.value)?.text || '基金'
    }, {
        deep: true
    })

    /* --------------------------------
    初始化
    -------------------------------- */
    onMounted(() => {
        searchFetch()
        
        const activeType = route?.query?.type || route?.query?.from
        if (activeType) {
            catText.value = searchNavList.value.find(item => item.type === activeType)?.text || '基金'
        }

        // 延遲設定環境
        setTimeout(() => {
            env.value = window.ENV
        }, 1000)
    })

    useHead({
        title: '搜尋結果'
    })
</script>
<style lang="scss">
    $class-name: search-result;
    .#{$class-name} {
        padding-top: 12rem;
        background-color: map-get($colors, gray-3);


        @include media-breakpoint-down(tablet) {
            padding-top: 16.2rem;
        }

        &.-height {
            padding-top: 18rem;
        }

        &__top {
            display: flex;
            flex-direction: column;
            gap: 3.6rem;

            @include media-breakpoint-down(tablet) {
                gap: 3.2rem;
            }

            h1 {
                @include typo('head', 18);
                padding-bottom: 3.6rem;
                border-bottom: 1px solid map-get($colors, gray-1);
                position: relative;

                @include media-breakpoint-down(tablet) {
                    padding-bottom: 3.2rem;
                }

                // debug 用
                > span {
                    display: none;
                    position: absolute;
                    bottom: 1rem;
                    left: 0;
                    font-size: 1.4rem;
                    opacity: .5;

                    > button {
                        border: 1px solid rgba(0, 0, 0, 0.2);
                        background-color: #fff;
                        padding: .4rem .8rem;
                        border-radius: 4rem;
                        font-size: 1.2rem;
                        margin-left: 1rem;

                        &:hover {
                            opacity: .5;
                        }
                    }
                }

                &:hover {
                    > span {
                        display: block;
                    }
                }
            }

            &-navs {
                display: flex;
                align-items: center;
                justify-content: space-between;
                padding-top: 3.6rem;

                &.-loading {
                    pointer-events: none;
                }

                @include media-breakpoint-down(tablet) {
                    flex-direction: column;
                    align-items: flex-start;
                    gap: 2.4rem;
                    padding-top: 3.2rem;
                }

                ul {
                    display: flex;
                    gap: .8rem;
                    align-items: center;
                    min-height: 5.559rem;

                    @include media-breakpoint-down(tablet) {
                        max-width: 100%;
                        overflow-x: auto;
                        padding: 0;
                        min-height: 3.559rem;
                    }
                    

                    li {
                        a {
                            padding: .6rem 1.6rem .8rem;
                            border-radius: 4rem;
                            border: 1px solid rgba(0, 0, 0, 0);
                            transition: all .3s ;
                            white-space: nowrap;

                            @include media-breakpoint-down(tablet) {
                                @include typo('head', 14);

                                padding: .4rem 1rem .5rem;
                            }

                            &:hover,
                            &.active {
                                border-color: map-get($colors, black-1);
                                background-color: #fff;
                            }

                            &.-disabled {
                                opacity: .35;
                                pointer-events: none;
                                cursor: default;
                            }

                            .nav-count {
                                opacity: .6;
                            }
                        }

                        &:last-child {
                            position: relative;
                            padding-left: 1.6rem;

                            &::before {
                                content: '';
                                @include size(1px, 100%);
                                position: absolute;
                                top: 0;
                                left: .3rem;
                                background-color: map-get($colors, black-1);
                            }
                        }
                    }
                }
            }
        }

        &__list {
            min-height: 50rem;
            padding-top: 2.4rem;
            padding-bottom: 8rem;
        }

        &__loading,
        &__noresult {
            @include typo('head', 28);
            text-align: center;
            padding: 20rem 0 40vh;
            display: flex;
            align-items: center;
            justify-content: center;

            @include media-breakpoint-down(tablet) {
                @include typo('head', 24);
                padding: 16rem 0 20vh;
            }
        }

        &__more {
            display: flex;
            justify-content: center;
            padding: 2.4rem 0 10rem;

            &-loading {
                display: flex;
                align-items: center;
                justify-content: center;
                padding: 2.4rem 0 10rem;
            }
        }

        &__body {
            position: relative;
            min-height: 50rem;

            &-overlay {
                position: absolute;
                inset: 0;
                background-color: map-get($colors, gray-3);
                display: flex;
                align-items: center;
                justify-content: center;
                z-index: 1;
            }
        }
    }

    .debug__tokenizer {
        position: fixed;
        bottom: 5%;
        left: 5%;
        z-index: 9999;
        background-color: rgba(255, 255, 255, 0.9);
        padding: 1.6rem;
        border-radius: 1.6rem;
        box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
        display: flex;
        flex-wrap: wrap;
        gap: .5rem;
        font-size: 1.2rem;
        width: 90%;

        > div {
            padding: 0rem .4rem;
            border: 1px solid rgba(0, 0, 0, 0.2);
            background-color: #fff;
        }
        
    }
</style>