import { io, Socket } from "socket.io-client";
import { getOrCreateGuestId } from "./guestId";

export interface ChatMessage {
  id: string;
  senderId: string;
  senderName?: string;
  content: string;
  timestamp: Date | string;
  type: "text" | "system";
}

export interface Participant {
  id: string;
  name?: string;
  stream?: MediaStream;
  peerConnection?: RTCPeerConnection;
  isMuted?: boolean;
  isVideoOff?: boolean;
  isSpeaking?: boolean;
  iceCandidateQueue?: RTCIceCandidate[];
}

export interface WebRTCCallbacks {
  onParticipantJoined?: (participant: Participant) => void;
  onParticipantLeft?: (participantId: string) => void;
  onLocalStreamReady?: (stream: MediaStream) => void;
  onRemoteStreamReady?: (participantId: string, stream: MediaStream) => void;
  onRoomParticipants?: (participantIds: string[]) => void;
  onChatMessage?: (message: ChatMessage) => void;
  onParticipantAudioToggle?: (
    participantId: string,
    isEnabled: boolean
  ) => void;
  onParticipantVideoToggle?: (
    participantId: string,
    isEnabled: boolean
  ) => void;
  onParticipantSpeakingChange?: (
    participantId: string,
    isSpeaking: boolean
  ) => void;
  onError?: (error: Error) => void;
}

interface WebRTCState {
  socket: Socket;
  localStream: MediaStream | null;
  participants: Map<string, Participant>;
  roomId: string | null;
  userId: string;
  isAudioEnabled: boolean;
  isVideoEnabled: boolean;
  callbacks: WebRTCCallbacks[]; // Изменено на массив
  chatMessages: ChatMessage[];
}

let state: WebRTCState | null = null;

const ICE_SERVERS = [
  {
    urls: "turn:185.173.176.83:3478",
    username: "username1",
    credential: "password1",
  },
  // {
  //   urls: "turn:openrelay.metered.ca:80",
  //   username: "openrelayproject",
  //   credential: "openrelayproject",
  // },
  // {
  //   urls: "turn:openrelay.metered.ca:443",
  //   username: "openrelayproject",
  //   credential: "openrelayproject",
  // },
  // {
  //   urls: "turn:openrelay.metered.ca:443?transport=tcp",
  //   username: "openrelayproject",
  //   credential: "openrelayproject",
  // },
];

// Для localhost можно использовать упрощенную конфигурацию
const isLocalhost =
  window.location.hostname === "localhost" ||
  window.location.hostname === "127.0.0.1" ||
  window.location.hostname === "[::1]";

if (isLocalhost) {
  console.log(
    "[WebRTC] Running on localhost - using TURN server for reliable connection"
  );
}

// Вспомогательная функция для вызова всех коллбэков
function callAllCallbacks<K extends keyof WebRTCCallbacks>(
  eventName: K,
  ...args: Parameters<NonNullable<WebRTCCallbacks[K]>>
) {
  if (!state) return;
  state.callbacks.forEach((callbacks) => {
    const callback = callbacks[eventName];
    if (callback) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (callback as any)(...args);
    }
  });
}

export function createWebRTCService(callbacks: WebRTCCallbacks = {}) {
  if (state) {
    cleanup();
  }

  console.log("Creating WebRTC service...");

  // Подключаемся к WebRTC серверу на порту 3001
  const serverUrl = import.meta.env.VITE_WEBRTC_URL || "http://localhost:3001";
  console.log("Connecting to WebRTC server:", serverUrl);

  const socket = io(serverUrl, {
    transports: ["websocket", "polling"],
  });
  const userId = getOrCreateGuestId();
  console.log("Using guest ID:", userId);

  state = {
    socket,
    localStream: null,
    participants: new Map(),
    roomId: null,
    userId,
    isAudioEnabled: true,
    isVideoEnabled: true,
    callbacks: [callbacks], // Массив коллбэков
    chatMessages: [],
  };

  setupSocketListeners();

  return {
    initializeLocalStream,
    joinRoom,
    toggleAudio,
    toggleVideo,
    leaveRoom,
    sendChatMessage,
    updateSpeakingState,
    updateUserId: (newUserId: string) => {
      if (state) {
        console.log("[WebRTC] Updating userId from", state.userId, "to", newUserId);
        state.userId = newUserId;
      }
    },
    getChatMessages: () => state?.chatMessages || [],
    getCurrentUserId: () => state?.userId || "",
    getParticipants: () => Array.from(state?.participants.values() || []),
    getLocalStream: () => state?.localStream || null,
    isAudioMuted: () => (state ? !state.isAudioEnabled : true),
    isVideoMuted: () => (state ? !state.isVideoEnabled : true),
    hasLocalStream: () => state?.localStream !== null,
    addCallbacks: (newCallbacks: WebRTCCallbacks) => {
      if (state) {
        state.callbacks.push(newCallbacks);
        console.log("Added callbacks, total count:", state.callbacks.length);
      }
      return () => {
        if (state) {
          const index = state.callbacks.indexOf(newCallbacks);
          if (index > -1) {
            state.callbacks.splice(index, 1);
            console.log(
              "Removed callbacks, remaining count:",
              state.callbacks.length
            );
          }
        }
      };
    },
    cleanup,
  };
}

function setupSocketListeners() {
  if (!state) return;

  const { socket } = state;
  console.log("Setting up socket listeners...");

  socket.on("connect", () => {
    console.log("Socket connected with ID:", socket.id);
  });

  socket.on("disconnect", (reason) => {
    console.log("Socket disconnected, reason:", reason);
  });

  socket.on("connect_error", (error) => {
    console.error("Socket connection error:", error);
  });

  socket.on("reconnect", (attemptNumber) => {
    console.log("Socket reconnected after", attemptNumber, "attempts");
  });

  socket.on("reconnect_error", (error) => {
    console.error("Socket reconnection error:", error);
  });

  socket.on("room-participants", (participants: string[]) => {
    console.log("Room participants received:", participants);
    console.log("Current user ID:", state?.userId);
    console.log(
      "[WebRTC] I am the new user, connecting to existing participants"
    );
    callAllCallbacks("onRoomParticipants", participants);

    // Новый пользователь (мы) инициируем соединения со всеми существующими участниками
    participants.forEach((participantId) => {
      addParticipant(participantId);
      createPeerConnection(participantId, true); // МЫ - инициаторы
    });
  });

  socket.on("user-joined", (userId: string) => {
    console.log("[WebRTC] User joined event received:", userId);
    console.log(
      "[WebRTC] New user will initiate connection to us, waiting for offer"
    );
    if (!state) return;

    // Только добавляем участника в UI, НЕ создаем peer connection
    // Новый пользователь сам инициирует соединение с нами
    addParticipant(userId);
    // НЕ вызываем createPeerConnection - ждем входящий offer
  });

  socket.on("user-left", (userId: string) => {
    console.log("User left event received:", userId);
    if (!state) return;

    const participant = state.participants.get(userId);
    if (participant) {
      participant.peerConnection?.close();
      state.participants.delete(userId);
      callAllCallbacks("onParticipantLeft", userId);
    }
  });

  socket.on(
    "offer",
    async ({
      offer,
      sender,
    }: {
      offer: RTCSessionDescriptionInit;
      sender: string;
    }) => {
      console.log("Received offer from:", sender);
      await handleOffer(sender, offer);
    }
  );

  socket.on(
    "answer",
    async ({
      answer,
      sender,
    }: {
      answer: RTCSessionDescriptionInit;
      sender: string;
    }) => {
      console.log("Received answer from:", sender);
      await handleAnswer(sender, answer);
    }
  );

  socket.on(
    "ice-candidate",
    async ({
      candidate,
      sender,
    }: {
      candidate: RTCIceCandidate;
      sender: string;
    }) => {
      console.log("Received ICE candidate from:", sender);
      await handleIceCandidate(sender, candidate);
    }
  );

  // Chat message handlers
  socket.on("chat-message", (message: ChatMessage) => {
    console.log("📨 Received chat message from Socket.IO:", message);
    if (!state) return;

    // Добавляем сообщение в локальное хранилище
    state.chatMessages.push(message);
    console.log(
      "📨 Added message to local state, total messages:",
      state.chatMessages.length
    );

    // Уведомляем все компоненты
    callAllCallbacks("onChatMessage", message);
  });

  socket.on("chat-error", (error: { message: string }) => {
    console.error("📨 Chat error received from server:", error);
    console.error("📨 Error message:", error.message);
    alert(`Ошибка при отправке сообщения: ${error.message}`);
    callAllCallbacks("onError", new Error(error.message));
  });

  // Audio/Video toggle handlers
  socket.on("audio-toggle", ({ userId, isEnabled }: { userId: string; isEnabled: boolean }) => {
    console.log(`[WebRTC] Received audio-toggle from ${userId}: ${isEnabled}`);
    if (!state) return;

    const participant = state.participants.get(userId);
    if (participant) {
      participant.isMuted = !isEnabled;
      callAllCallbacks("onParticipantAudioToggle", userId, isEnabled);
    }
  });

  socket.on("video-toggle", ({ userId, isEnabled }: { userId: string; isEnabled: boolean }) => {
    console.log(`[WebRTC] Received video-toggle from ${userId}: ${isEnabled}`);
    if (!state) return;

    const participant = state.participants.get(userId);
    if (participant) {
      participant.isVideoOff = !isEnabled;
      callAllCallbacks("onParticipantVideoToggle", userId, isEnabled);
    }
  });

  socket.on("speaking-state", ({ userId, isSpeaking }: { userId: string; isSpeaking: boolean }) => {
    if (!state) return;

    const participant = state.participants.get(userId);
    if (participant) {
      participant.isSpeaking = isSpeaking;
      // Уведомляем callback для обновления UI
      callAllCallbacks("onParticipantSpeakingChange", userId, isSpeaking);
    }
  });

  console.log("Socket listeners set up complete");
}

async function initializeLocalStream(): Promise<MediaStream | null> {
  if (!state) throw new Error("WebRTC service not initialized");

  try {
    // Проверяем доступность WebRTC API
    if (!navigator.mediaDevices) {
      throw new Error("WebRTC не поддерживается в этом браузере.");
    }

    if (!navigator.mediaDevices.getUserMedia) {
      throw new Error("getUserMedia не поддерживается в этом браузере.");
    }

    console.log("Requesting media access...");
    const stream = await navigator.mediaDevices.getUserMedia({
      video: true,
      audio: true,
    });

    console.log("Local stream:", stream);

    stream.getTracks().forEach((track) => {
      console.log("Track:", track.kind, track.label);
    });

    state.localStream = stream;
    callAllCallbacks("onLocalStreamReady", stream);
    return stream;
  } catch (error) {
    console.error("Error accessing media devices:", error);

    let errorMessage = "Не удалось получить доступ к камере или микрофону";

    if (error instanceof Error) {
      if (error.name === "NotAllowedError") {
        errorMessage =
          "Доступ к камере и микрофону запрещен. Вы можете продолжить без видео и аудио.";
      } else if (error.name === "NotFoundError") {
        errorMessage =
          "Камера или микрофон не найдены. Вы можете продолжить без видео и аудио.";
      } else if (error.name === "NotReadableError") {
        errorMessage =
          "Камера или микрофон заняты другим приложением. Вы можете продолжить без видео и аудио.";
      }
    }

    console.warn("Продолжаем без локального медиа-потока:", errorMessage);
    callAllCallbacks("onError", new Error(errorMessage));

    // Возвращаем null вместо выброса ошибки, чтобы пользователь мог продолжить
    return null;
  }
}

async function joinRoom(roomId: string): Promise<void> {
  if (!state) throw new Error("WebRTC service not initialized");

  console.log("Joining room:", roomId, "with user ID:", state.userId);
  state.roomId = roomId;
  state.socket.emit("join-room", { 
    roomId, 
    userId: state.userId,
    isAudioEnabled: state.isAudioEnabled,
    isVideoEnabled: state.isVideoEnabled,
  });
}

// Вспомогательная функция для добавления участника
function addParticipant(participantId: string): Participant {
  if (!state) throw new Error("WebRTC service not initialized");

  let participant = state.participants.get(participantId);
  if (!participant) {
    participant = { id: participantId };
    state.participants.set(participantId, participant);
    console.log("[WebRTC] Adding new participant:", participantId);
    callAllCallbacks("onParticipantJoined", participant);
  }
  return participant;
}

async function createPeerConnection(
  participantId: string,
  isInitiator: boolean
): Promise<void> {
  if (!state) return;

  const participant = state.participants.get(participantId);
  if (!participant) {
    console.error("[WebRTC] Participant not found:", participantId);
    return;
  }

  // Если peer connection уже существует, не создаем новый
  if (participant.peerConnection) {
    console.log("[WebRTC] Peer connection already exists for:", participantId);
    return;
  }

  console.log(
    "[WebRTC] Creating new peer connection for:",
    participantId,
    "isInitiator:",
    isInitiator
  );
  const peerConnection = new RTCPeerConnection({
    iceServers: ICE_SERVERS, // Используем TURN сервер для всех соединений
    iceTransportPolicy: "all", // Использовать все доступные транспорты
    bundlePolicy: "max-bundle", // Объединить все медиа в один транспорт
    rtcpMuxPolicy: "require", // Мультиплексировать RTP и RTCP
    iceCandidatePoolSize: 10, // Предварительно собрать candidates
  });
  participant.peerConnection = peerConnection;

  // Add local stream tracks if available
  if (state.localStream) {
    state.localStream.getTracks().forEach((track) => {
      peerConnection.addTrack(track, state!.localStream!);
    });
    console.log("[WebRTC] Added local stream tracks for:", participantId);
  } else {
    // Если нет локального потока, не добавляем треки
    // Будем использовать offerToReceiveAudio/Video для приема
    console.log(
      "[WebRTC] No local stream, will use offerToReceive options for:",
      participantId
    );
  }

  // Handle remote stream
  peerConnection.ontrack = (event) => {
    console.log(
      "🎥 Received remote track from:",
      participantId,
      `(${event.track.kind})`
    );
    const [remoteStream] = event.streams;
    if (remoteStream) {
      participant!.stream = remoteStream;
      callAllCallbacks("onRemoteStreamReady", participantId, remoteStream);
    } else {
      console.error("No remote stream in track event!");
    }
  };

  // Handle ICE candidates
  peerConnection.onicecandidate = (event) => {
    if (event.candidate && state) {
      const candidateStr = event.candidate.candidate || "";
      const type = candidateStr.includes("typ host")
        ? "host"
        : candidateStr.includes("typ srflx")
        ? "srflx"
        : candidateStr.includes("typ relay")
        ? "relay"
        : "unknown";
      console.log(
        `[WebRTC] Sending ICE candidate to ${participantId}: type=${type}, candidate=${candidateStr.substring(
          0,
          50
        )}...`
      );
      state.socket.emit("ice-candidate", {
        target: participantId,
        candidate: event.candidate,
      });
    } else if (!event.candidate) {
      console.log(`[WebRTC] ICE gathering complete for ${participantId}`);
    }
  };

  peerConnection.onicegatheringstatechange = () => {
    console.log(
      `[WebRTC] ICE gathering state for ${participantId}:`,
      peerConnection.iceGatheringState
    );
  };

  // Monitor connection state
  peerConnection.onconnectionstatechange = () => {
    console.log(
      `[WebRTC] Connection state for ${participantId}:`,
      peerConnection.connectionState
    );
  };

  peerConnection.oniceconnectionstatechange = () => {
    console.log(
      `[WebRTC] ICE connection state for ${participantId}:`,
      peerConnection.iceConnectionState
    );

    // Автоматический restart при failed
    if (peerConnection.iceConnectionState === "failed") {
      console.warn(
        `[WebRTC] ICE failed for ${participantId}, attempting restart...`
      );
      peerConnection.restartIce();
    }

    // Уведомляем о disconnected
    if (peerConnection.iceConnectionState === "disconnected") {
      console.warn(
        `[WebRTC] ICE disconnected for ${participantId}, may reconnect automatically`
      );
    }
  };

  // Create offer if initiator
  if (isInitiator) {
    try {
      console.log("[WebRTC] Creating offer for:", participantId);
      console.log(
        "[WebRTC] Current ICE gathering state:",
        peerConnection.iceGatheringState
      );
      console.log(
        "[WebRTC] Current signaling state:",
        peerConnection.signalingState
      );

      // Создаем offer с настройками на прием аудио и видео
      // Используем старый формат для совместимости с Firefox
      const offerOptions: RTCOfferOptions = {
        offerToReceiveAudio: true,
        offerToReceiveVideo: true,
      };

      const offer = await peerConnection.createOffer(offerOptions);
      console.log("[WebRTC] Offer created, SDP type:", offer.type);

      await peerConnection.setLocalDescription(offer);
      console.log(
        "[WebRTC] Local description set, ICE gathering state:",
        peerConnection.iceGatheringState
      );
      console.log("[WebRTC] hasLocalStream:", !!state.localStream);

      // Используем Trickle ICE - отправляем offer сразу, candidates отправятся отдельно
      console.log("[WebRTC] Sending offer to:", participantId);
      state.socket.emit("offer", {
        target: participantId,
        offer: offer,
      });
      console.log(
        "[WebRTC] Offer sent, waiting for ICE candidates to be gathered and sent..."
      );
    } catch (error) {
      console.error("Error creating offer:", error);
      callAllCallbacks("onError", error as Error);
    }
  }
}

async function handleOffer(
  senderId: string,
  offer: RTCSessionDescriptionInit
): Promise<void> {
  if (!state) return;

  console.log("[WebRTC] Received offer from:", senderId);

  // Добавляем участника, если его еще нет
  addParticipant(senderId);

  const participant = state.participants.get(senderId);
  if (!participant) {
    console.error("[WebRTC] Participant not found:", senderId);
    return;
  }

  // Создаем peer connection (мы НЕ инициаторы, отвечаем на offer)
  await createPeerConnection(senderId, false);

  if (!participant.peerConnection) {
    console.error("[WebRTC] Failed to create peer connection for:", senderId);
    return;
  }

  const peerConnection = participant.peerConnection;

  try {
    console.log("[WebRTC] Setting remote description (offer) from:", senderId);
    await peerConnection.setRemoteDescription(offer);
    console.log(
      "[WebRTC] Remote description set, ICE gathering state:",
      peerConnection.iceGatheringState
    );

    // Обрабатываем очередь ICE candidates
    if (
      participant.iceCandidateQueue &&
      participant.iceCandidateQueue.length > 0
    ) {
      console.log(
        "[WebRTC] Processing queued ICE candidates:",
        participant.iceCandidateQueue.length
      );
      for (const queuedCandidate of participant.iceCandidateQueue) {
        try {
          await peerConnection.addIceCandidate(queuedCandidate);
        } catch (error) {
          console.error("Error adding queued ICE candidate:", error);
        }
      }
      participant.iceCandidateQueue = [];
    }

    console.log("[WebRTC] Creating answer for:", senderId);
    const answer = await peerConnection.createAnswer();
    console.log("[WebRTC] Answer created");

    await peerConnection.setLocalDescription(answer);
    console.log(
      "[WebRTC] Local description (answer) set, ICE gathering state:",
      peerConnection.iceGatheringState
    );

    state.socket.emit("answer", {
      target: senderId,
      answer: answer,
    });
    console.log("[WebRTC] Answer sent to:", senderId);
  } catch (error) {
    console.error("Error handling offer:", error);
    callAllCallbacks("onError", error as Error);
  }
}

async function handleAnswer(
  senderId: string,
  answer: RTCSessionDescriptionInit
): Promise<void> {
  if (!state) return;

  console.log("[WebRTC] Received answer from:", senderId);

  const participant = state.participants.get(senderId);
  if (!participant?.peerConnection) {
    console.warn(
      "[WebRTC] No peer connection found for answer from:",
      senderId
    );
    return;
  }

  const signalingState = participant.peerConnection.signalingState;
  console.log("[WebRTC] Current signaling state:", signalingState);

  // Проверяем, что мы ожидаем answer
  if (signalingState !== "have-local-offer") {
    console.warn(
      "[WebRTC] Ignoring answer - not in have-local-offer state:",
      signalingState
    );
    return;
  }

  try {
    await participant.peerConnection.setRemoteDescription(answer);
    console.log("[WebRTC] Successfully set remote answer from:", senderId);

    // Обрабатываем очередь ICE candidates
    if (
      participant.iceCandidateQueue &&
      participant.iceCandidateQueue.length > 0
    ) {
      console.log(
        "[WebRTC] Processing queued ICE candidates:",
        participant.iceCandidateQueue.length
      );
      for (const queuedCandidate of participant.iceCandidateQueue) {
        try {
          await participant.peerConnection.addIceCandidate(queuedCandidate);
        } catch (error) {
          console.error("Error adding queued ICE candidate:", error);
        }
      }
      participant.iceCandidateQueue = [];
    }
  } catch (error) {
    console.error("Error handling answer:", error);
    callAllCallbacks("onError", error as Error);
  }
}

async function handleIceCandidate(
  senderId: string,
  candidate: RTCIceCandidate
): Promise<void> {
  if (!state) return;

  const participant = state.participants.get(senderId);
  if (!participant?.peerConnection) {
    console.warn(
      "[WebRTC] No peer connection found for ICE candidate from:",
      senderId
    );
    return;
  }

  // Проверяем, что у нас установлено remote description
  if (!participant.peerConnection.remoteDescription) {
    console.log("[WebRTC] Queuing ICE candidate - no remote description yet");
    // Добавляем в очередь для последующей обработки
    if (!participant.iceCandidateQueue) {
      participant.iceCandidateQueue = [];
    }
    participant.iceCandidateQueue.push(candidate);
    console.log(
      `[WebRTC] Queue size for ${senderId}:`,
      participant.iceCandidateQueue.length
    );
    return;
  }

  try {
    await participant.peerConnection.addIceCandidate(candidate);
    const candidateStr = candidate.candidate || "";
    const type = candidateStr.includes("typ host")
      ? "host"
      : candidateStr.includes("typ srflx")
      ? "srflx"
      : candidateStr.includes("typ relay")
      ? "relay"
      : "unknown";
    console.log(
      `[WebRTC] Added ICE candidate from ${senderId}, type: ${type}, candidate=${candidateStr.substring(
        0,
        50
      )}...`
    );
  } catch (error) {
    console.error("Error handling ICE candidate:", error);
    // Не выбрасываем ошибку в callback - это нормально при переподключениях
  }
}

function toggleAudio(): boolean {
  if (!state?.localStream) {
    console.warn("Cannot toggle audio: no local stream available");
    return false;
  }

  const audioTracks = state.localStream.getAudioTracks();
  if (audioTracks.length === 0) {
    console.warn("Cannot toggle audio: no audio tracks available");
    return false;
  }

  audioTracks.forEach((track) => {
    track.enabled = !track.enabled;
  });
  state.isAudioEnabled = !state.isAudioEnabled;
  
  // Отправляем обновление состояния аудио всем участникам
  if (state.roomId) {
    state.socket.emit("audio-toggle", {
      roomId: state.roomId,
      userId: state.userId,
      isEnabled: state.isAudioEnabled,
    });
    console.log(`[WebRTC] Sent audio-toggle: ${state.isAudioEnabled}`);
  }
  
  return state.isAudioEnabled;
}

function toggleVideo(): boolean {
  if (!state?.localStream) {
    console.warn("Cannot toggle video: no local stream available");
    return false;
  }

  const videoTracks = state.localStream.getVideoTracks();
  if (videoTracks.length === 0) {
    console.warn("Cannot toggle video: no video tracks available");
    return false;
  }

  videoTracks.forEach((track) => {
    track.enabled = !track.enabled;
  });
  state.isVideoEnabled = !state.isVideoEnabled;
  
  // Отправляем обновление состояния видео всем участникам
  if (state.roomId) {
    state.socket.emit("video-toggle", {
      roomId: state.roomId,
      userId: state.userId,
      isEnabled: state.isVideoEnabled,
    });
    console.log(`[WebRTC] Sent video-toggle: ${state.isVideoEnabled}`);
  }
  
  return state.isVideoEnabled;
}

function updateSpeakingState(isSpeaking: boolean): void {
  if (!state || !state.roomId) return;

  // Отправляем состояние speaking через Socket.IO
  state.socket.emit("speaking-state", {
    roomId: state.roomId,
    userId: state.userId,
    isSpeaking,
  });
}

function sendChatMessage(content: string, senderName?: string, isAuthenticated?: boolean): void {
  if (!state || !content.trim() || !state.roomId) return;

  console.log("📤 Sending message via Socket.IO:", content);
  console.log("📤 isAuthenticated:", isAuthenticated, "state.userId:", state.userId);

  // Определяем userId и guestId на основе реальной авторизации
  // Если пользователь авторизован, state.userId содержит настоящий userId
  // Если нет - state.userId содержит guestId
  const userId = isAuthenticated ? state.userId : null;
  const guestId = !isAuthenticated ? state.userId : null;

  console.log("📤 Sending with userId:", userId, "guestId:", guestId);

  // Отправляем сообщение через Socket.IO
  state.socket.emit("chat-message", {
    roomId: state.roomId,
    userId,
    guestId,
    content: content.trim(),
    senderName: senderName || null,
  });
}

function leaveRoom(): void {
  if (!state) return;

  // Close all peer connections
  state.participants.forEach((participant) => {
    participant.peerConnection?.close();
  });
  state.participants.clear();

  // Stop local stream
  if (state.localStream) {
    state.localStream.getTracks().forEach((track) => track.stop());
    state.localStream = null;
  }

  // Leave room via socket
  if (state.socket.connected && state.roomId) {
    state.socket.emit("leave-room", {
      roomId: state.roomId,
      userId: state.userId,
    });
  }

  state.roomId = null;
}

function cleanup(): void {
  if (state) {
    leaveRoom();
    state.socket.disconnect();
    state = null;
  }
}
