import { useState, useEffect, useCallback, useRef } from 'react'; import { getCalcuttaAuctionStatus } from '@bettoredge/api'; import type { CalcuttaCompetitionProps, CalcuttaAuctionItemProps, CalcuttaBidProps, } from '@bettoredge/types'; export interface CalcuttaAuctionState { loading: boolean; competition?: CalcuttaCompetitionProps; items: CalcuttaAuctionItemProps[]; bids: CalcuttaBidProps[]; my_bids: CalcuttaBidProps[]; paused: boolean; escrow_summaries: Record; total_escrow_balance: number; } export const useCalcuttaAuction = (calcutta_competition_id?: string, poll_interval: number = 5000, player_id?: string) => { const [state, setState] = useState({ loading: false, items: [], bids: [], my_bids: [], paused: false, escrow_summaries: {}, total_escrow_balance: 0, }); const intervalRef = useRef | null>(null); const fetchStatus = useCallback(async () => { if (!calcutta_competition_id) return; try { const resp = await getCalcuttaAuctionStatus(calcutta_competition_id); setState({ loading: false, competition: resp.competition, items: resp.items, bids: resp.bids, my_bids: resp.my_bids, paused: resp.competition?.auction_status === 'paused', escrow_summaries: resp.escrow_summaries || {}, total_escrow_balance: resp.total_escrow_balance || 0, }); } catch { // Silently fail on poll } }, [calcutta_competition_id]); useEffect(() => { if (!calcutta_competition_id) return; setState(prev => ({ ...prev, loading: true })); fetchStatus(); // Start polling intervalRef.current = setInterval(fetchStatus, poll_interval); return () => { if (intervalRef.current) clearInterval(intervalRef.current); }; }, [calcutta_competition_id, poll_interval, fetchStatus]); const stopPolling = useCallback(() => { if (intervalRef.current) { clearInterval(intervalRef.current); intervalRef.current = null; } }, []); // Socket event handlers for live mode — update local state directly const handleBidUpdate = useCallback((data: { item: CalcuttaAuctionItemProps; bid: CalcuttaBidProps; item_deadline?: string; outbid_player_id?: string }) => { setState(prev => { const newState = { ...prev, items: prev.items.map(i => i.calcutta_auction_item_id === data.item.calcutta_auction_item_id ? data.item : i ), bids: [...prev.bids.filter(b => b.calcutta_bid_id !== data.bid.calcutta_bid_id), data.bid], my_bids: [...prev.my_bids], }; // Update my_bids if this bid belongs to the current user if (player_id && data.bid.player_id === player_id) { newState.my_bids = [ ...prev.my_bids.filter(b => b.calcutta_auction_item_id !== data.bid.calcutta_auction_item_id), data.bid, ]; } // If I was outbid, mark my bid on this item as 'outbid' if (player_id && data.outbid_player_id === player_id) { newState.my_bids = newState.my_bids.map(b => b.calcutta_auction_item_id === data.item.calcutta_auction_item_id && b.bid_status === 'active' ? { ...b, bid_status: 'outbid' } : b ); } return newState; }); }, [player_id]); const handleItemActive = useCallback((data: { item: CalcuttaAuctionItemProps; item_deadline?: string }) => { setState(prev => ({ ...prev, competition: prev.competition ? { ...prev.competition, current_auction_item_id: data.item.calcutta_auction_item_id } : prev.competition, items: prev.items.map(i => i.calcutta_auction_item_id === data.item.calcutta_auction_item_id ? data.item : i ), })); }, []); const handleItemSold = useCallback((data: { item: CalcuttaAuctionItemProps; winning_bid: CalcuttaBidProps; winning_player_id: string }) => { setState(prev => ({ ...prev, items: prev.items.map(i => i.calcutta_auction_item_id === data.item.calcutta_auction_item_id ? { ...data.item, winning_bid: data.winning_bid?.bid_amount ?? data.item.winning_bid, winning_player_id: data.winning_player_id } : i ), })); }, []); const handleItemUnsold = useCallback((data: { item: CalcuttaAuctionItemProps }) => { setState(prev => ({ ...prev, items: prev.items.map(i => i.calcutta_auction_item_id === data.item.calcutta_auction_item_id ? data.item : i ), })); }, []); const handleAuctionPaused = useCallback(() => { setState(prev => ({ ...prev, paused: true, competition: prev.competition ? { ...prev.competition, auction_status: 'paused' } : prev.competition, // Clear item deadline on active item items: prev.items.map(i => i.calcutta_auction_item_id === prev.competition?.current_auction_item_id ? { ...i, item_deadline: null } : i ), })); }, []); const handleAuctionResumed = useCallback((data: { item?: CalcuttaAuctionItemProps; item_deadline?: string }) => { setState(prev => ({ ...prev, paused: false, competition: prev.competition ? { ...prev.competition, auction_status: 'in_progress' } : prev.competition, items: data.item ? prev.items.map(i => i.calcutta_auction_item_id === data.item!.calcutta_auction_item_id ? data.item! : i ) : prev.items, })); }, []); const handleAuctionClosed = useCallback((data: { competition: CalcuttaCompetitionProps }) => { setState(prev => ({ ...prev, competition: data.competition, paused: false, })); }, []); return { ...state, refresh: fetchStatus, stopPolling, // Socket event handlers for CalcuttaAuction to wire up handleBidUpdate, handleItemActive, handleItemSold, handleItemUnsold, handleAuctionPaused, handleAuctionResumed, handleAuctionClosed, }; };