import type { MentionInfo, ChatMessage, EmojiInfo } from '../types'
import { encryptWsPayload } from '../../../../utils/wsCrypto'

/** 進入直播間系統訊息（不顯示於聊天室） */
export function isEnterRoomSystemMessage(
    m: Pick<ChatMessage, 'isSystem' | 'systemMessageType' | 'text'>
): boolean {
    if (m.systemMessageType === 'userEntered') return true
    if (!m.isSystem) return false
    const text = m.text || ''
    return /進入直播間|加入直播間|已進入直播間|entered the (stream|room)/i.test(text)
}

/**
 * 從 contentEditable 元素中提取文本、mention 和表情符號資訊
 * @param element contentEditable 的 HTML 元素
 * @returns 包含文本、mentions 和 emojis 的對象
 */
export function extractMentions(element: HTMLElement): { text: string; mentions: MentionInfo[]; emojis: EmojiInfo[] } {
    const mentions: MentionInfo[] = []
    const emojis: EmojiInfo[] = []
    let text = ''
    let currentIndex = 0

    const walkNodes = (node: Node) => {
        if (node.nodeType === Node.TEXT_NODE) {
            const textContent = node.textContent || ''
            text += textContent
            currentIndex += textContent.length
        } else if (node.nodeType === Node.ELEMENT_NODE) {
            const el = node as HTMLElement
            if (el.getAttribute('data-mention') === 'true') {
                const userId = el.getAttribute('data-user-id') || ''
                const userName = el.getAttribute('data-user-name') || ''
                const mentionText = `@${userName}`
                const startIndex = currentIndex
                text += mentionText
                currentIndex += mentionText.length
                mentions.push({
                    userId,
                    userName,
                    startIndex,
                    endIndex: currentIndex,
                })
            } else if (el.tagName === 'IMG' && el.getAttribute('data-emoji-code')) {
                const emojiCode = el.getAttribute('data-emoji-code') || ''
                const emojiSrc = el.getAttribute('data-emoji-src') || ''
                const startIndex = currentIndex
                text += emojiCode
                currentIndex += emojiCode.length
                emojis.push({
                    code: emojiCode,
                    src: emojiSrc,
                    startIndex,
                    endIndex: currentIndex,
                })
            } else {
                for (let i = 0; i < el.childNodes.length; i++) {
                    walkNodes(el.childNodes[i])
                }
            }
        }
    }

    for (let i = 0; i < element.childNodes.length; i++) {
        walkNodes(element.childNodes[i])
    }

    return { text: text.trim(), mentions, emojis }
}

/**
 * 處理聊天消息發送
 * @param params 發送消息所需的參數
 */
export interface SendChatParams {
    writeAreaRef: React.RefObject<HTMLDivElement>
    currentUserId: string | null | undefined
    currentUserDisplayName: string | null | undefined
    streamUserId: string
    wsRef: React.RefObject<WebSocket | null>
    setMessages: React.Dispatch<React.SetStateAction<ChatMessage[]>>
    setChatDraftDesktop: (value: string) => void
    setChatDraftMobile: (value: string) => void
    chatWriteAreaRefDesktop: React.RefObject<HTMLDivElement>
    chatWriteAreaRefMobile: React.RefObject<HTMLDivElement>
    mode: 'desktop' | 'mobile'
    superAdminUserIdsRef?: React.MutableRefObject<Set<string>>
    modUserIdsRef?: React.MutableRefObject<Set<string>>
    /** 本地暫存訊息用：與 WS authorPublicPathKey 一致（有 display_id 則傳 display_id） */
    authorPublicPathKey?: string | null
}

export function sendChat(params: SendChatParams): boolean {
    const {
        writeAreaRef,
        currentUserId,
        currentUserDisplayName,
        streamUserId,
        wsRef,
        setMessages,
        setChatDraftDesktop,
        setChatDraftMobile,
        chatWriteAreaRefDesktop,
        chatWriteAreaRefMobile,
        mode,
        superAdminUserIdsRef,
        modUserIdsRef,
        authorPublicPathKey: senderPublicPathKey,
    } = params
    if (!currentUserId) {
        return false
    }
    if (!writeAreaRef.current) return false
    const { text, mentions, emojis } = extractMentions(writeAreaRef.current)
    if (!text) return false
    let userType: 'streamer' | 'manager' | 'superAdmin' | undefined = undefined
    if (currentUserId === streamUserId) {
        userType = 'streamer'
    } else if (superAdminUserIdsRef?.current.has(currentUserId)) {
        userType = 'superAdmin'
    } else if (modUserIdsRef?.current.has(currentUserId)) {
        userType = 'manager'
    }
    if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
        const tempId = `temp-${Date.now()}`
        setMessages((prev) => [
            ...prev,
            {
                id: tempId,
                author: currentUserDisplayName || '我',
                text,
                userId: currentUserId || null,
                userType,
                time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
                mentions: mentions.length > 0 ? mentions : undefined,
                emojis: emojis.length > 0 ? emojis : undefined,
                ...(senderPublicPathKey != null && String(senderPublicPathKey).trim()
                    ? { authorPublicPathKey: String(senderPublicPathKey).trim() }
                    : {}),
            },
        ])
        wsRef.current.send(
            encryptWsPayload({
                type: 'chat',
                text,
                mentions: mentions.length > 0 ? mentions : undefined,
                emojis: emojis.length > 0 ? emojis : undefined,
            })
        )
    } else {
        setMessages((prev) => [
            ...prev,
            {
                id: `m-${Date.now()}`,
                author: currentUserDisplayName || '我',
                text,
                time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
                mentions: mentions.length > 0 ? mentions : undefined,
                emojis: emojis.length > 0 ? emojis : undefined,
            },
        ])
    }
    if (mode === 'desktop') {
        setChatDraftDesktop('')
        if (chatWriteAreaRefDesktop.current) chatWriteAreaRefDesktop.current.textContent = ''
    } else {
        setChatDraftMobile('')
        if (chatWriteAreaRefMobile.current) chatWriteAreaRefMobile.current.textContent = ''
    }

    return true
}

/**
 * 解析聊天指令
 * @param text 輸入的文本
 * @returns 解析結果，如果不是指令則返回 null
 */
export interface ChatCommand {
    type: 'user'
    args: string[]
    rawText: string
}

export function parseChatCommand(text: string): ChatCommand | null {
    const trimmed = text.trim()
    if (!trimmed.startsWith('/')) return null
    const parts = trimmed.split(/\s+/)
    const command = parts[0].substring(1).toLowerCase()
    switch (command) {
        case 'user':
            if (parts.length < 2) return null
            return {
                type: 'user',
                args: parts.slice(1),
                rawText: trimmed,
            }
        default:
            return null
    }
}

