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

export class WebRTCService {
  private socket: Socket | null = null;
  private peerConnections: Map<string, RTCPeerConnection> = new Map();

  constructor(socket: Socket) {
    this.socket = socket;
    this.setupSocketListeners();
  }

  private setupSocketListeners() {
    if (!this.socket) return;

    this.socket.on('offer', (data: any) => {
      console.log('Received offer from:', data.from);
      this.handleOffer(data);
    });

    this.socket.on('answer', (data: any) => {
      console.log('Received answer from:', data.from);
      this.handleAnswer(data);
    });

    this.socket.on('ice-candidate', (data: any) => {
      console.log('Received ICE candidate from:', data.from);
      this.handleIceCandidate(data);
    });
  }

  async startCall(recipientId: string): Promise<void> {
    try {
      const peerConnection = this.createPeerConnection(recipientId);
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });

      stream.getTracks().forEach((track) => {
        peerConnection.addTrack(track, stream);
      });

      const offer = await peerConnection.createOffer();
      await peerConnection.setLocalDescription(offer);

      this.socket?.emit('offer', {
        to: recipientId,
        offer: offer,
      });
    } catch (error) {
      console.error('Error starting call:', error);
    }
  }

  private createPeerConnection(peerId: string): RTCPeerConnection {
    if (this.peerConnections.has(peerId)) {
      return this.peerConnections.get(peerId)!;
    }

    const iceServers = [
      { urls: ['stun:stun.l.google.com:19302', 'stun:stun1.l.google.com:19302'] },
    ];

    const peerConnection = new RTCPeerConnection({
      iceServers,
    });

    peerConnection.onicecandidate = (event) => {
      if (event.candidate) {
        this.socket?.emit('ice-candidate', {
          to: peerId,
          candidate: event.candidate,
        });
      }
    };

    peerConnection.ontrack = (event) => {
      console.log('Received remote track:', event.track);
    };

    this.peerConnections.set(peerId, peerConnection);
    return peerConnection;
  }

  private async handleOffer(data: any) {
    const peerConnection = this.createPeerConnection(data.from);
    await peerConnection.setRemoteDescription(new RTCSessionDescription(data.offer));

    const answer = await peerConnection.createAnswer();
    await peerConnection.setLocalDescription(answer);

    this.socket?.emit('answer', {
      to: data.from,
      answer: answer,
    });
  }

  private async handleAnswer(data: any) {
    const peerConnection = this.peerConnections.get(data.from);
    if (peerConnection) {
      await peerConnection.setRemoteDescription(new RTCSessionDescription(data.answer));
    }
  }

  private async handleIceCandidate(data: any) {
    const peerConnection = this.peerConnections.get(data.from);
    if (peerConnection && data.candidate) {
      await peerConnection.addIceCandidate(new RTCIceCandidate(data.candidate));
    }
  }

  endCall(peerId: string): void {
    const peerConnection = this.peerConnections.get(peerId);
    if (peerConnection) {
      peerConnection.close();
      this.peerConnections.delete(peerId);
    }
  }
}
