import { fetchEventSource } from '@microsoft/fetch-event-source' import { useEffect, useRef } from 'react' import { useAuthStore } from '../store/auth' interface SSEHandlers { onTaskEvent?: (data: { message: string; level: string; ts: string }) => void onTaskResult?: (data: { device_id: number; device_ip: string; status: string; duration_ms: number }) => void onTaskStatus?: (data: { status: string; total: number; ok: number; failed: number }) => void } export function useSSE(taskId: string | null | undefined, handlers: SSEHandlers) { const accessToken = useAuthStore((s) => s.accessToken) const handlersRef = useRef(handlers) handlersRef.current = handlers useEffect(() => { if (!taskId || !accessToken) return const ctrl = new AbortController() fetchEventSource(`/api/v1/events?task_id=${taskId}`, { headers: { Authorization: `Bearer ${accessToken}` }, signal: ctrl.signal, onmessage(ev) { try { const data = JSON.parse(ev.data) if (ev.event === 'task_event') handlersRef.current.onTaskEvent?.(data) else if (ev.event === 'task_result') handlersRef.current.onTaskResult?.(data) else if (ev.event === 'task_status') handlersRef.current.onTaskStatus?.(data) } catch { // ignore parse errors } }, onerror() { ctrl.abort() }, }) return () => ctrl.abort() }, [taskId, accessToken]) }