import { useCallback, useEffect, useRef } from "react";
import { useWebSocket } from "./useWebSocket";
import { useMarketStore } from "../stores/marketStore";
import type { Ticker, OrderBook, Trade } from "../types/models";

interface UseMarketDataOptions {
  symbol?: string;
  url?: string;
  enabled?: boolean;
}

interface WebSocketMessage {
  type: "ticker" | "orderbook" | "trade" | "subscribed" | "error";
  data?: unknown;
  symbol?: string;
  message?: string;
}

export function useMarketData({
  symbol,
  url,
  enabled = true,
}: UseMarketDataOptions = {}) {
  const setTicker = useMarketStore((state) => state.setTicker);
  const setOrderBook = useMarketStore((state) => state.setOrderBook);
  const addRecentTrade = useMarketStore((state) => state.addRecentTrade);
  const setConnectionStatus = useMarketStore(
    (state) => state.setConnectionStatus,
  );
  const tickers = useMarketStore((state) => state.tickers);
  const orderBook = useMarketStore((state) => state.orderBook);
  const recentTrades = useMarketStore((state) => state.recentTrades);
  const isConnected = useMarketStore((state) => state.isConnected);
  const hasConnectedRef = useRef(false);

  const handleMessage = useCallback(
    (message: unknown) => {
      const msg = message as WebSocketMessage;

      switch (msg.type) {
        case "ticker": {
          const ticker = msg.data as Ticker;
          if (ticker) {
            setTicker(ticker);
          }
          break;
        }
        case "orderbook": {
          const book = msg.data as OrderBook;
          if (book) {
            setOrderBook(book);
          }
          break;
        }
        case "trade": {
          const trade = msg.data as Trade;
          if (trade) {
            addRecentTrade(trade);
          }
          break;
        }
        case "subscribed": {
          console.log("Subscribed to:", msg.symbol);
          break;
        }
        case "error": {
          console.error("WebSocket error:", msg.message);
          break;
        }
        default:
          break;
      }
    },
    [setTicker, setOrderBook, addRecentTrade],
  );

  const handleConnect = useCallback(() => {
    setConnectionStatus(true);
    hasConnectedRef.current = true;
  }, [setConnectionStatus]);

  const handleDisconnect = useCallback(() => {
    setConnectionStatus(false);
  }, [setConnectionStatus]);

  const handleError = useCallback((error: Event) => {
    // Only log errors after first successful connection to avoid transient errors
    if (hasConnectedRef.current) {
      console.error("WebSocket error:", error);
    }
  }, []);

  const {
    subscribe,
    unsubscribe,
    isConnecting,
    reconnectAttempts,
    connect,
    disconnect,
    sendMessage,
  } = useWebSocket({
    url:
      url ||
      (typeof window !== "undefined"
        ? process.env.NEXT_PUBLIC_WS_URL ||
          `ws://${window.location.hostname}:8000/ws/market`
        : "ws://localhost:8000/ws/market"),
    onMessage: handleMessage,
    onConnect: handleConnect,
    onDisconnect: handleDisconnect,
    onError: handleError,
    maxReconnectAttempts: 10,
    heartbeatInterval: 30000,
  });

  // Subscribe/unsubscribe when symbol changes
  useEffect(() => {
    if (!isConnected || !symbol) return;

    // Subscribe to new symbol channels
    subscribe(`ticker:${symbol}`);
    subscribe(`orderbook:${symbol}`);
    subscribe(`trades:${symbol}`);

    return () => {
      // Unsubscribe when component unmounts or symbol changes
      unsubscribe(`ticker:${symbol}`);
      unsubscribe(`orderbook:${symbol}`);
      unsubscribe(`trades:${symbol}`);
    };
  }, [symbol, isConnected, subscribe, unsubscribe]);

  // Auto-connect/disconnect based on enabled flag
  useEffect(() => {
    if (enabled) {
      connect();
    } else {
      disconnect();
    }
  }, [enabled, connect, disconnect]);

  return {
    // Data
    ticker: symbol ? tickers[symbol] : undefined,
    orderBook: symbol ? orderBook[symbol] : undefined,
    recentTrades: symbol
      ? recentTrades.filter((t) => t.symbol === symbol).slice(0, 50)
      : recentTrades.slice(0, 50),

    // Connection state
    isConnected,
    isConnecting,
    reconnectAttempts,

    // Actions
    connect,
    disconnect,
    sendMessage,
  };
}
