'use client'

import { useEffect, useRef, type Dispatch, type MutableRefObject, type SetStateAction } from 'react'
import { parseChatWsMessageLoose } from '@/lib/chat/wsChat'
import { encryptWsPayload } from '@/utils/wsCrypto'

type ParticipantRow = { userId?: string | null }

/**
 * 依線上參與者同步 Mod／超管標記（僅對尚未查詢過的 userId 發 check_mod_status）。
 * 須在 useEffect cleanup 移除 message 監聽，避免 participants_update 反覆觸發時累積監聽與 WS 洪水。
 */
export function useSyncParticipantModStatus(
    wsRef: MutableRefObject<WebSocket | null>,
    onlineParticipants: ParticipantRow[],
    streamUserId: string,
    roomId: string,
    setModUserIds: Dispatch<SetStateAction<Set<string>>>,
    setSuperAdminUserIds: Dispatch<SetStateAction<Set<string>>>,
    modUserIdsRef: MutableRefObject<Set<string>>,
    superAdminUserIdsRef: MutableRefObject<Set<string>>
) {
    const checkedUserIdsRef = useRef<Set<string>>(new Set())

    useEffect(() => {
        checkedUserIdsRef.current = new Set()
    }, [roomId])

    useEffect(() => {
        const ws = wsRef.current
        if (!ws || ws.readyState !== WebSocket.OPEN) return

        const allUserIds = onlineParticipants
            .filter((p) => p.userId && p.userId !== streamUserId)
            .map((p) => p.userId!)

        if (allUserIds.length === 0) {
            return
        }

        const userIds = allUserIds.filter((id) => !checkedUserIdsRef.current.has(id))
        if (userIds.length === 0) return

        userIds.forEach((id) => checkedUserIdsRef.current.add(id))

        const pendingModChecks = new Map<string, boolean>()
        let completedCount = 0

        userIds.forEach((userId) => {
            ws.send(
                encryptWsPayload({
                    type: 'check_mod_status',
                    userId,
                })
            )
            pendingModChecks.set(userId, false)
        })

        const timeout = window.setTimeout(() => {
            const mods = new Set<string>()
            pendingModChecks.forEach((isMod, userId) => {
                if (isMod) mods.add(userId)
            })
            setModUserIds((prev) => {
                const next = new Set(prev)
                mods.forEach((id) => next.add(id))
                modUserIdsRef.current = next
                return next
            })
        }, 2000)

        const messageHandler = (event: MessageEvent) => {
            try {
                const data = parseChatWsMessageLoose(event.data as string)
                if (!data || data.type !== 'mod_status' || !data.data) return

                const userId = String(data.data.userId ?? '').trim()
                if (!userId || !pendingModChecks.has(userId)) return

                const isMod = Boolean(data.data.isMod)
                pendingModChecks.set(userId, isMod)
                completedCount++

                if (!isMod) {
                    setModUserIds((prev) => {
                        const next = new Set(prev)
                        next.delete(userId)
                        modUserIdsRef.current = next
                        return next
                    })
                }

                if (data.data.isSuperAdmin) {
                    setSuperAdminUserIds((prev) => {
                        const updated = new Set(prev)
                        updated.add(userId)
                        superAdminUserIdsRef.current = updated
                        return updated
                    })
                } else {
                    setSuperAdminUserIds((prev) => {
                        const updated = new Set(prev)
                        updated.delete(userId)
                        superAdminUserIdsRef.current = updated
                        return updated
                    })
                }

                if (completedCount < userIds.length) return

                window.clearTimeout(timeout)
                const mods = new Set<string>()
                pendingModChecks.forEach((isMod, uid) => {
                    if (isMod) mods.add(uid)
                })
                setModUserIds((prev) => {
                    const next = new Set(prev)
                    mods.forEach((id) => next.add(id))
                    modUserIdsRef.current = next
                    return next
                })
                ws.removeEventListener('message', messageHandler)
            } catch (error) {
                console.error('Failed to parse mod status response:', error)
            }
        }

        ws.addEventListener('message', messageHandler)

        return () => {
            window.clearTimeout(timeout)
            ws.removeEventListener('message', messageHandler)
        }
    }, [
        onlineParticipants,
        roomId,
        streamUserId,
        wsRef,
        setModUserIds,
        setSuperAdminUserIds,
        modUserIdsRef,
        superAdminUserIdsRef,
    ])
}
