import { useState, useEffect, useCallback, useRef } from 'react'; import type { CalcuttaCompetitionProps, CalcuttaAuctionItemProps, CalcuttaBidProps, } from '@bettoredge/types'; import { useSocket } from '@bettoredge/socket'; export interface CalcuttaPresencePlayer { player_id: string; username?: string; profile_pic?: string; } export interface CalcuttaPresence { count: number; players: CalcuttaPresencePlayer[]; } export interface CalcuttaSocketCallbacks { onBidUpdate?: (data: { item: CalcuttaAuctionItemProps; bid: CalcuttaBidProps; item_deadline?: string; escrow_snapshot?: any }) => void; onItemActive?: (data: { item: CalcuttaAuctionItemProps; item_deadline?: string }) => void; onItemSold?: (data: { item: CalcuttaAuctionItemProps; winning_bid: CalcuttaBidProps; winning_player_id: string }) => void; onItemUnsold?: (data: { item: CalcuttaAuctionItemProps }) => void; onAuctionPaused?: () => void; onAuctionResumed?: (data: { item?: CalcuttaAuctionItemProps; item_deadline?: string }) => void; onAuctionClosed?: (data: { competition: CalcuttaCompetitionProps }) => void; /** Triggered when another client requests all clients to refresh their data */ onRefresh?: () => void; } export const useCalcuttaSocket = ( calcutta_competition_id: string, access_token?: string, device_id?: string, player_data?: { username?: string; profile_pic?: string }, callbacks?: CalcuttaSocketCallbacks, ) => { const { on, send, joinRoom, leaveRoom, ready, state } = useSocket({ access_token, device_id, autoConnect: !!access_token && !!device_id, }); const [presence, setPresence] = useState({ count: 0, players: [] }); const callbacksRef = useRef(callbacks); callbacksRef.current = callbacks; // Join room + subscribe to events useEffect(() => { if (!ready || !calcutta_competition_id) return; joinRoom('JOIN_CALCUTTA_AUCTION', { access_token, device_id, calcutta_competition_id, player_data: player_data || {}, }); const unsubs = [ on('CALCUTTA_PRESENCE_UPDATE', (data: any) => { if (data.calcutta_competition_id === calcutta_competition_id) { setPresence({ count: data.count, players: data.players || [] }); } }), on('V1_SOCKET_JOIN_CALCUTTA', (data: any) => { if (data.status === 'success' && data.players) { setPresence({ count: data.count, players: data.players }); } }), on('CALCUTTA_BID_UPDATE', (data: any) => { if (data.calcutta_competition_id === calcutta_competition_id) { callbacksRef.current?.onBidUpdate?.(data); } }), on('CALCUTTA_ITEM_ACTIVE', (data: any) => { if (data.calcutta_competition_id === calcutta_competition_id) { callbacksRef.current?.onItemActive?.(data); } }), on('CALCUTTA_ITEM_SOLD', (data: any) => { if (data.calcutta_competition_id === calcutta_competition_id) { callbacksRef.current?.onItemSold?.(data); } }), on('CALCUTTA_ITEM_UNSOLD', (data: any) => { if (data.calcutta_competition_id === calcutta_competition_id) { callbacksRef.current?.onItemUnsold?.(data); } }), on('CALCUTTA_AUCTION_PAUSED', (data: any) => { if (data.calcutta_competition_id === calcutta_competition_id) { callbacksRef.current?.onAuctionPaused?.(); } }), on('CALCUTTA_AUCTION_RESUMED', (data: any) => { if (data.calcutta_competition_id === calcutta_competition_id) { callbacksRef.current?.onAuctionResumed?.(data); } }), on('CALCUTTA_AUCTION_CLOSED', (data: any) => { if (data.calcutta_competition_id === calcutta_competition_id) { callbacksRef.current?.onAuctionClosed?.(data); } }), on('CALCUTTA_REFRESH', (data: any) => { if (data.calcutta_competition_id === calcutta_competition_id) { callbacksRef.current?.onRefresh?.(); } }), ]; return () => { unsubs.forEach(u => u()); leaveRoom('LEAVE_CALCUTTA_AUCTION', { access_token, device_id, calcutta_competition_id }); }; }, [ready, calcutta_competition_id]); /** Broadcast an event to all other clients in this calcutta room (bypasses RabbitMQ) */ const broadcast = useCallback((event: Record) => { send({ type: 'CALCUTTA_BROADCAST', calcutta_competition_id, event: { ...event, calcutta_competition_id }, }); }, [send, calcutta_competition_id]); return { connected: ready, presence, socketState: state, broadcast }; };