import { useState, useEffect, useRef, useCallback } from 'react';
import { BASE_URL } from '../api/client';

export interface FeedEvent {
  id: string;
  timestamp: string;
  skill_id: string | null;
  saving_pct: number | null;
  latency_ms: number | null;
  type?: string;
}

interface UseLiveFeedResult {
  events: FeedEvent[];
  connected: boolean;
}

const MAX_EVENTS = 100;
const RECONNECT_DELAY_MS = 3000;

export function useLiveFeed(): UseLiveFeedResult {
  const [events, setEvents] = useState<FeedEvent[]>([]);
  const [connected, setConnected] = useState<boolean>(false);
  const abortRef = useRef<AbortController | null>(null);
  const reconnectTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
  const mountedRef = useRef<boolean>(true);

  const connect = useCallback(async () => {
    if (!mountedRef.current) return;

    // Cancel any existing connection
    if (abortRef.current) {
      abortRef.current.abort();
    }

    const controller = new AbortController();
    abortRef.current = controller;

    try {
      const response = await fetch(`${BASE_URL}/bibividi/events`, {
        signal: controller.signal,
        headers: { Accept: 'text/event-stream' },
      });

      if (!response.ok || !response.body) {
        throw new Error(`SSE connection failed: ${response.status}`);
      }

      if (!mountedRef.current) return;
      setConnected(true);

      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      let buffer = '';

      while (mountedRef.current) {
        const { done, value } = await reader.read();
        if (done) break;

        buffer += decoder.decode(value, { stream: true });
        const lines = buffer.split('\n');
        buffer = lines.pop() ?? '';

        for (const line of lines) {
          if (line.startsWith('data:')) {
            const raw = line.slice(5).trim();
            if (!raw || raw === '[DONE]') continue;
            try {
              const parsed = JSON.parse(raw) as FeedEvent;
              if (!mountedRef.current) break;
              setEvents((prev) => {
                const updated = [parsed, ...prev];
                return updated.slice(0, MAX_EVENTS);
              });
            } catch {
              // Skip malformed events
            }
          }
        }
      }
    } catch (err) {
      if (err instanceof Error && err.name === 'AbortError') return;
      // Connection error — will reconnect below
    }

    if (!mountedRef.current) return;
    setConnected(false);

    // Schedule reconnect
    reconnectTimer.current = setTimeout(() => {
      if (mountedRef.current) connect();
    }, RECONNECT_DELAY_MS);
  }, []);

  useEffect(() => {
    mountedRef.current = true;
    connect();

    return () => {
      mountedRef.current = false;
      if (abortRef.current) {
        abortRef.current.abort();
      }
      if (reconnectTimer.current) {
        clearTimeout(reconnectTimer.current);
      }
    };
  }, [connect]);

  return { events, connected };
}
