type phrases = {
    key: string,
    phrase: string,
    syn_id: string
}
type phrasesData = {
    noPhrases: string,
    phrases: phrases[]
}

export const keywordTokenizer = ({
    searchText, phrasesData, tokenizerData
}: {
    searchText: string,
    phrasesData: phrasesData,
    tokenizerData: string[]
}) => {
    if (!searchText || !tokenizerData?.length) return []

    /* --------------------------------
    step 1
    -------------------------------- */
    // 清除搜尋前後空白
    searchText = searchText.trim()
    console.log('輸入的詞清除前後空白', searchText)

    // 保存使用者輸入的原字串（trim 後），最後會用 || 串接回詞組
    const originalText = searchText

    /* --------------------------------
    step 2
    -------------------------------- */
    // 移除廢詞
    let removedUselessText = searchText
    const uselessPhrasesAry = (phrasesData?.noPhrases?.split(',') || []).sort((a: string, b: string) => b.length - a.length)
    console.log('廢棄詞列表', uselessPhrasesAry)

    for (const phrase of uselessPhrasesAry) {
        removedUselessText = removedUselessText.replace(phrase, '')
    }
    console.log('移除廢棄詞', removedUselessText)

    /* --------------------------------
    step 3 - 1
    -------------------------------- */
    // 從詞庫中找到相符的詞 (有重複就不加入，詞庫比對要以最長的開始比)
    let foundedInPhrases: string[] = []
    let noFoundedInPhrases: string = ''
    let noFoundedInPhrasesAry: string[] = []
    
    if (tokenizerData?.length > 0) { 
        const sortedTokens = [...tokenizerData].sort((a: string, b: string) => b.length - a.length) // 將詞庫按照長度排序，最長的先比對
        
        // 使用陣列來追蹤未匹配的文字片段
        let tempTextArray = [removedUselessText.toLowerCase()] // 初始化為包含整個文字的陣列
        
        for (const token of sortedTokens) {
            const phrase = token.toLowerCase() // 將詞庫轉換為小寫
            
            // 用於儲存新的陣列（拆分後的結果）
            const newTempTextArray: string[] = []
            let foundInThisRound = false
            
            // 遍歷當前陣列中的每個元素
            for (const text of tempTextArray) {
                // 檢查此元素是否包含此詞
                if (text.includes(phrase)) {
                    foundInThisRound = true
                    
                    // 將文字以找到的詞為分隔符拆分
                    const parts = text.split(phrase)
                    
                    // 將拆分後的部分加入新陣列（過濾空字串）
                    newTempTextArray.push(...parts.filter(part => part.trim() !== ''))
                } else {
                    // 如果不包含此詞，原樣保留
                    newTempTextArray.push(text)
                }
            }
            
            // 如果這輪有找到詞，更新陣列並記錄找到的詞
            if (foundInThisRound && !foundedInPhrases.includes(token)) {
                tempTextArray = newTempTextArray
                foundedInPhrases.push(token)
                
                /* --------------------------------
                step 3 - 1 - 1
                -------------------------------- */
                // 找到的詞接著再去 Phrases.phrases 中比對，找到的話，看是否有 syn_id，有 syn_id 的話，就加入 foundedInPhrases 並且用 || 組裝起來
                
                if (phrasesData?.phrases?.length > 0) {
                    // 在 phrasesData.phrases 中找到相同的詞
                    const matchedPhrase = phrasesData.phrases.find(
                        phraseItem => phraseItem.phrase.toLowerCase() === token.toLowerCase()
                    )
                    if (matchedPhrase && matchedPhrase.syn_id) {
                        console.log(`找到同義詞 syn_id ${matchedPhrase.syn_id}`, matchedPhrase.phrase)
                        
                        // 找到所有相同 syn_id 的詞
                        const synonyms = phrasesData.phrases
                            .filter(phraseItem => phraseItem.syn_id === matchedPhrase.syn_id)
                            .map(phraseItem => phraseItem.phrase)
                        
                        // 用 || 組裝同義詞
                        const synonymsString = synonyms.join('||')
                        
                        // 移除原本加入的單個詞，改為加入同義詞組
                        const lastIndex = foundedInPhrases.lastIndexOf(token)
                        if (lastIndex !== -1) {
                            foundedInPhrases.splice(lastIndex, 1)
                        }
                        
                        // 檢查是否已經有相同的同義詞組，避免重複
                        if (!foundedInPhrases.includes(synonymsString)) {
                            foundedInPhrases.push(synonymsString)
                        }
                        
                        console.log('組裝後的同義詞', synonymsString)
                    }
                }
            }
        }
        
        // 將剩餘未匹配的文字陣列組合回字串
        noFoundedInPhrases = tempTextArray.join(' ').trim()
        console.log('未匹配的文字陣列', tempTextArray)
    } else {
        // 如果沒有詞庫，整個搜尋文字都算是未找到的
        noFoundedInPhrases = removedUselessText
    }

    /* --------------------------------
    step 3 - 2
    -------------------------------- */
    // 處理沒找到的詞
    if (noFoundedInPhrases) {
        // 中英文混雜斷詞處理
        const segmentMixedText = (text: string): string[] => {
            const result: string[] = []
            let currentSegment = ''
            let currentType = '' // 'chinese', 'english', 'space'
            
            for (let i = 0; i < text.length; i++) {
                const char = text[i]
                let charType = ''
                
                // 判斷字符類型
                if (/[\u4e00-\u9fff]/.test(char)) {
                    // 中文字符
                    charType = 'chinese'
                } else if (/\s/.test(char)) {
                    // 空格
                    charType = 'space'
                } else {
                    // 英文、數字、符號都算英文
                    charType = 'english'
                }
                
                // 如果字符類型改變或遇到空格，結束當前片段
                if (charType !== currentType || charType === 'space') {
                    if (currentSegment.trim()) {
                        result.push(currentSegment.trim())
                    }
                    currentSegment = ''
                    currentType = charType
                }
                
                // 空格不加入片段，其他字符加入
                if (charType !== 'space') {
                    currentSegment += char
                }
            }
            
            // 處理最後一個片段
            if (currentSegment.trim()) {
                result.push(currentSegment.trim())
            }
            
            return result.filter(segment => segment.length > 0)
        }
        noFoundedInPhrasesAry = segmentMixedText(noFoundedInPhrases)
    }

    console.log('從詞庫中找到的詞，以及同義詞', foundedInPhrases)
    console.log('沒有找到的詞', noFoundedInPhrases)
    console.log('沒有找到的詞(斷詞後)', noFoundedInPhrasesAry)
    
    /* --------------------------------
    step 3 - 2 - 1 沒有找到的詞(斷詞後)，要移除只剩下一個中文字的詞
    -------------------------------- */
    const specialChars = ['-', '、', '，', ',', '.', '。', '!', '！', '?', '？', ':', '：', ';', '；', 
        '「', '」', '『', '』', '（', '）', '(', ')', '［', '］', '【', '】', 
        '《', '》', '〈', '〉', '＜', '＞', '<', '>', '～', '~',
        '@', '#', '$', '%', '^', '&', '*'];
    noFoundedInPhrasesAry = noFoundedInPhrasesAry.filter(item => item.length > 1) // 移除只剩下一個字的詞
    console.log('移除只剩下一個字的詞', noFoundedInPhrasesAry)
    noFoundedInPhrasesAry = noFoundedInPhrasesAry.map(item => { // 接著再移除前後符號
        // 將 specialChars 轉換為正則表達式的字符集
        const escapedChars = specialChars.map(char => char.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
        const charPattern = `[${escapedChars.join('')}]`
        
        // 只移除開頭和結尾的特殊符號
        const startPattern = new RegExp(`^${charPattern}+`)
        const endPattern = new RegExp(`${charPattern}+$`)
        
        return item.replace(startPattern, '').replace(endPattern, '')
    })
    console.log('移除前後符號', noFoundedInPhrasesAry)
    
    /* --------------------------------
    step 4 將找到的詞、同義詞、以及沒有找到的詞斷詞後，使用,組裝
    -------------------------------- */
    let searchResult = [...foundedInPhrases, ...noFoundedInPhrasesAry].join(',')
    console.log('😆 組裝後的搜尋結果 😆', searchResult)

    /* --------------------------------
    step 5 加入原字串
    將使用者輸入的完整原字串用 || 串接回詞組（例如 VR -> VR||VRT），
    讓後端也能比對到完整原字串，避免分詞後漏掉如 VRT 這類完整字。
    若原字串已存在於詞組中（不分大小寫）則不重複加入。
    -------------------------------- */
    const existingTokens = searchResult
        .split(/,|\|\|/)
        .map(token => token.trim().toLowerCase())
    if (originalText && !existingTokens.includes(originalText.toLowerCase())) {
        searchResult = searchResult ? `${searchResult}||${originalText}` : originalText
    }
    console.log('😆 加入原字串後的搜尋結果 😆', searchResult)

    return searchResult
}