import { useState, useEffect, useCallback, useRef } from 'react'; import { DisplayAd } from '../../core/types'; import { useEarnLayerClient } from '../providers/EarnLayerProvider'; export interface UseDisplayAdOptions { conversationId?: string; adType?: 'banner' | 'popup' | 'video' | 'thinking'; placement?: string; autoFetch?: boolean; debug?: boolean; thinkingAdTimeout?: number; onAdFetched?: (ad: DisplayAd) => void; onError?: (error: Error) => void; } export interface UseDisplayAdReturn { ad: DisplayAd | null; isLoading: boolean; error: Error | null; refetch: () => Promise; refetchWithRefresh: () => Promise; } export function useDisplayAd(options: UseDisplayAdOptions = {}): UseDisplayAdReturn { const { conversationId: propConversationId, adType, autoFetch = true, debug = false, thinkingAdTimeout, onAdFetched, onError, } = options; const { client, conversationId: contextConversationId } = useEarnLayerClient(); const activeConversationId = propConversationId || contextConversationId; const [ad, setAd] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const onAdFetchedRef = useRef(onAdFetched); const onErrorRef = useRef(onError); const hasFetchedRef = useRef(false); useEffect(() => { onAdFetchedRef.current = onAdFetched; onErrorRef.current = onError; }, [onAdFetched, onError]); const fetchAd = useCallback(async (refresh: boolean = false) => { if (!activeConversationId) { return; } setIsLoading(true); setError(null); try { const fetchedAd = await client.getDisplayAd(activeConversationId, adType, thinkingAdTimeout, refresh); setAd(fetchedAd); if (fetchedAd && onAdFetchedRef.current) { onAdFetchedRef.current(fetchedAd); } } catch (err) { const error = err instanceof Error ? err : new Error('Failed to fetch ad'); setError(error); if (debug) { console.error('[EarnLayer SDK - useDisplayAd] Error fetching ad:', { conversationId: activeConversationId, adType, refresh, error: error.message, timestamp: new Date().toISOString() }); } if (onErrorRef.current) { onErrorRef.current(error); } } finally { setIsLoading(false); } }, [activeConversationId, adType, thinkingAdTimeout, client, debug]); const refetchWithRefresh = useCallback(async () => { await fetchAd(true); }, [fetchAd]); useEffect(() => { if (autoFetch && activeConversationId && !hasFetchedRef.current) { hasFetchedRef.current = true; fetchAd(); } }, [autoFetch, activeConversationId, fetchAd]); return { ad, isLoading, error, refetch: () => fetchAd(false), refetchWithRefresh, }; }