import { useEffect, useRef, useState, useCallback } from 'react' import * as SecureStore from 'expo-secure-store' import { API_BASE } from '../constants/Config' const WS_BASE = API_BASE.replace('https://', 'wss://').replace('http://', 'ws://') export interface WSEvent { event_type: string data: Record timestamp: string } export function useWebSocket(channels: string[] = []) { const [connected, setConnected] = useState(false) const [lastEvent, setLastEvent] = useState(null) const [events, setEvents] = useState([]) const ws = useRef(null) const retry = useRef | null>(null) const connect = useCallback(async () => { const token = await SecureStore.getItemAsync('grd_token') if (!token) return const url = `${WS_BASE}/ws/events?token=${token}` try { ws.current = new WebSocket(url) ws.current.onopen = () => { setConnected(true) // 채널 구독 메시지 전송 if (channels.length > 0 && ws.current) { ws.current.send(JSON.stringify({ subscribe: channels })) } } ws.current.onmessage = (e) => { try { const evt: WSEvent = JSON.parse(e.data) setLastEvent(evt) setEvents(prev => [evt, ...prev].slice(0, 50)) // 최근 50개 유지 } catch {} } ws.current.onclose = () => { setConnected(false) // 5초 후 재연결 retry.current = setTimeout(connect, 5000) } ws.current.onerror = () => { ws.current?.close() } } catch {} }, []) useEffect(() => { connect() return () => { if (retry.current) clearTimeout(retry.current) ws.current?.close() } }, [connect]) const send = useCallback((data: object) => { if (ws.current?.readyState === WebSocket.OPEN) { ws.current.send(JSON.stringify(data)) } }, []) return { connected, lastEvent, events, send } }