import { io, Socket } from 'socket.io-client';

const WS_URL = import.meta.env.VITE_WS_URL || 'http://localhost:3000/market';

export class MarketWebSocket {
  private socket: Socket | null = null;
  private subscribers: Map<string, Set<(data: any) => void>> = new Map();
  private subscribedSymbols: Set<string> = new Set();

  connect(token?: string): void {
    if (this.socket?.connected) return;

    this.socket = io(WS_URL, {
      auth: token ? { token } : undefined,
      reconnection: true,
      reconnectionAttempts: 5,
      reconnectionDelay: 1000,
    });

    this.socket.on('connect', () => {
      console.log('WebSocket已连接');
      if (this.subscribedSymbols.size > 0) {
        this.subscribe(Array.from(this.subscribedSymbols), ['tick']);
      }
    });

    this.socket.on('disconnect', () => {
      console.log('WebSocket已断开');
    });

    this.socket.on('tick', (data) => {
      this.notifySubscribers(`tick:${data.symbol}`, data);
    });

    this.socket.on('market:overview', (data) => {
      this.notifySubscribers('market:overview', data);
    });
  }

  disconnect(): void {
    if (this.socket) {
      this.socket.disconnect();
      this.socket = null;
    }
  }

  subscribe(symbols: string[], channels: string[] = ['tick']): void {
    if (!this.socket?.connected) return;
    symbols.forEach((symbol) => this.subscribedSymbols.add(symbol));
    this.socket.emit('subscribe', { symbols, channels });
  }

  unsubscribe(symbols: string[]): void {
    if (!this.socket?.connected) return;
    symbols.forEach((symbol) => this.subscribedSymbols.delete(symbol));
    this.socket.emit('unsubscribe', { symbols });
  }

  on(event: string, callback: (data: any) => void): () => void {
    if (!this.subscribers.has(event)) {
      this.subscribers.set(event, new Set());
    }
    this.subscribers.get(event)!.add(callback);
    return () => this.subscribers.get(event)?.delete(callback);
  }

  private notifySubscribers(event: string, data: any): void {
    this.subscribers.get(event)?.forEach((cb) => {
      try { cb(data); } catch (e) {}
    });
  }

  onTick(symbol: string, callback: (data: any) => void): () => void {
    return this.on(`tick:${symbol}`, callback);
  }

  onMarketOverview(callback: (data: any) => void): () => void {
    return this.on('market:overview', callback);
  }

  isConnected(): boolean {
    return this.socket?.connected || false;
  }
}

export const marketWS = new MarketWebSocket();
export default marketWS;