'use client'; import { useState, useCallback } from 'react'; export interface SearchResult { category?: string; type?: string; description?: string; notes?: string; } export interface SearchState { isSearching: boolean; searchError: string | null; searchResults: SearchResult | null; searchStatus: 'idle' | 'searching' | 'success' | 'timeout' | 'error' | 'no_results' | 'skipped'; retryCount: number; } export function useItemSearch(options: { maxRetries?: number; timeout?: number } = {}) { const { maxRetries = 2, timeout = 30000 } = options; const [state, setState] = useState({ isSearching: false, searchError: null, searchResults: null, searchStatus: 'idle', retryCount: 0, }); const performSearch = useCallback( async (partNumber: string, category: string): Promise => { if (!partNumber || !category) { setState(prev => ({ ...prev, searchStatus: 'skipped', searchError: null })); return null; } setState(prev => ({ ...prev, isSearching: true, searchStatus: 'searching', searchError: null, retryCount: 0 })); try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeout); const response = await fetch('/api/onboarding/search', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ partNumber, category }), signal: controller.signal, }); clearTimeout(timeoutId); if (!response.ok) throw new Error(`Search failed: ${response.status}`); const results = await response.json(); setState(prev => ({ ...prev, isSearching: false, searchStatus: 'success', searchResults: results })); return results; } catch (error) { const errorMsg = error instanceof Error ? error.message : 'Search failed'; setState(prev => ({ ...prev, isSearching: false, searchStatus: errorMsg.includes('abort') ? 'timeout' : 'error', searchError: errorMsg, })); return null; } }, [timeout] ); const retrySearch = useCallback( async (partNumber: string, category: string) => { if (state.retryCount >= maxRetries) { setState(prev => ({ ...prev, searchStatus: 'error' })); return null; } setState(prev => ({ ...prev, retryCount: prev.retryCount + 1 })); return performSearch(partNumber, category); }, [state.retryCount, maxRetries, performSearch] ); const skipSearch = useCallback(() => { setState(prev => ({ ...prev, searchStatus: 'skipped', isSearching: false })); }, []); return { state, performSearch, retrySearch, skipSearch }; }