'use client' import { useEffect, useRef, useCallback, useState } from 'react' export interface VoteUpdate { projectId: string totalVotes: number averageScore: number | null latestVote: { score: number; isAudienceVote: boolean; votedAt: string } | null timestamp: string } export interface AudienceVoteUpdate { projectId: string audienceVotes: number audienceAverage: number | null timestamp: string } export interface SessionStatusUpdate { status: string timestamp: string } export interface ProjectChangeUpdate { projectId: string | null projectIndex: number timestamp: string } interface SSECallbacks { onVoteUpdate?: (data: VoteUpdate) => void onAudienceVote?: (data: AudienceVoteUpdate) => void onSessionStatus?: (data: SessionStatusUpdate) => void onProjectChange?: (data: ProjectChangeUpdate) => void onConnected?: () => void onError?: (error: Event) => void } export function useLiveVotingSSE( sessionId: string | null, callbacks: SSECallbacks ) { const [isConnected, setIsConnected] = useState(false) const eventSourceRef = useRef(null) const callbacksRef = useRef(callbacks) callbacksRef.current = callbacks const connect = useCallback(() => { if (!sessionId) return // Close any existing connection if (eventSourceRef.current) { eventSourceRef.current.close() } const baseUrl = typeof window !== 'undefined' ? window.location.origin : '' const url = `${baseUrl}/api/live-voting/stream?sessionId=${sessionId}` const es = new EventSource(url) eventSourceRef.current = es es.addEventListener('connected', () => { setIsConnected(true) callbacksRef.current.onConnected?.() }) es.addEventListener('vote_update', (event) => { try { const data = JSON.parse(event.data) as VoteUpdate callbacksRef.current.onVoteUpdate?.(data) } catch { // Ignore parse errors } }) es.addEventListener('audience_vote', (event) => { try { const data = JSON.parse(event.data) as AudienceVoteUpdate callbacksRef.current.onAudienceVote?.(data) } catch { // Ignore parse errors } }) es.addEventListener('session_status', (event) => { try { const data = JSON.parse(event.data) as SessionStatusUpdate callbacksRef.current.onSessionStatus?.(data) } catch { // Ignore parse errors } }) es.addEventListener('project_change', (event) => { try { const data = JSON.parse(event.data) as ProjectChangeUpdate callbacksRef.current.onProjectChange?.(data) } catch { // Ignore parse errors } }) es.onerror = (event) => { setIsConnected(false) callbacksRef.current.onError?.(event) // Auto-reconnect after 3 seconds setTimeout(() => { if (eventSourceRef.current === es) { connect() } }, 3000) } }, [sessionId]) const disconnect = useCallback(() => { if (eventSourceRef.current) { eventSourceRef.current.close() eventSourceRef.current = null setIsConnected(false) } }, []) useEffect(() => { connect() return () => disconnect() }, [connect, disconnect]) return { isConnected, reconnect: connect, disconnect } }