import { useEffect, useRef, useState } from "react";
import {
  tradingClient,
  riskClient,
  monitoringClient,
  mlClient,
  mlTrainingClient,
  configClient,
} from "../lib/grpc";

// ---------------------------------------------------------------------------
// Generic server-streaming hook
// ---------------------------------------------------------------------------

/** Hook that consumes a server-streaming gRPC RPC and accumulates messages. */
export function useServerStream<T>(
  streamFn: (signal: AbortSignal) => AsyncIterable<T>,
  deps: unknown[] = [],
) {
  const [lastMessage, setLastMessage] = useState<T | null>(null);
  const [messages, setMessages] = useState<T[]>([]);
  const [connected, setConnected] = useState(false);
  const mountedRef = useRef(true);

  useEffect(() => {
    mountedRef.current = true;
    const controller = new AbortController();
    setConnected(true);

    (async () => {
      try {
        for await (const msg of streamFn(controller.signal)) {
          if (!mountedRef.current) break;
          setLastMessage(msg);
          setMessages((prev) => [...prev.slice(-99), msg]);
        }
      } catch {
        // Stream ended, aborted, or encountered an error
      } finally {
        if (mountedRef.current) setConnected(false);
      }
    })();

    return () => {
      mountedRef.current = false;
      controller.abort();
    };
  }, deps); // eslint-disable-line react-hooks/exhaustive-deps

  return { lastMessage, messages, connected };
}

// ---------------------------------------------------------------------------
// Typed stream hooks
// ---------------------------------------------------------------------------

export function useMarketDataStream() {
  return useServerStream((signal) =>
    tradingClient.streamMarketData({}, { signal }),
  );
}

export function useOrderUpdatesStream() {
  return useServerStream((signal) =>
    tradingClient.streamOrders({}, { signal }),
  );
}

export function usePositionUpdatesStream() {
  return useServerStream((signal) =>
    tradingClient.streamPositions({}, { signal }),
  );
}

export function useRiskAlertsStream() {
  return useServerStream((signal) =>
    riskClient.streamRiskAlerts({}, { signal }),
  );
}

export function useRiskMetricsStream() {
  return useServerStream((signal) =>
    riskClient.streamRiskMetrics({}, { signal }),
  );
}

export function useMetricsStream() {
  return useServerStream((signal) =>
    monitoringClient.streamMetrics({}, { signal }),
  );
}

export function useMlPredictionStream() {
  return useServerStream((signal) =>
    mlClient.streamPredictions({}, { signal }),
  );
}

export function useTrainingStatusStream() {
  return useServerStream((signal) =>
    mlTrainingClient.subscribeToTrainingStatus({}, { signal }),
  );
}

export function useConfigChangesStream() {
  return useServerStream((signal) =>
    configClient.streamConfigChanges({}, { signal }),
  );
}
