let socket = null;
let reconnectTimer = null;
let reconnectDelay = 1000;
let currentToken = null;
let currentHandlers = null;

function wsUrl(token) {
  const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
  const base = import.meta.env.BASE_URL || '/';
  const path = (base.endsWith('/') ? base : base + '/') + 'ws';
  const normalized = path.startsWith('/') ? path : '/' + path;
  return `${proto}//${location.host}${normalized}?token=${encodeURIComponent(token)}`;
}

function scheduleReconnect() {
  if (reconnectTimer) return;
  reconnectTimer = setTimeout(() => {
    reconnectTimer = null;
    if (currentToken && currentHandlers) openSocket();
  }, reconnectDelay);
  reconnectDelay = Math.min(reconnectDelay * 2, 15000);
}

function openSocket() {
  try {
    socket = new WebSocket(wsUrl(currentToken));
  } catch {
    scheduleReconnect();
    return;
  }

  socket.addEventListener('open', () => {
    reconnectDelay = 1000;
    currentHandlers?.onOpen?.();
  });

  socket.addEventListener('message', (event) => {
    let msg;
    try { msg = JSON.parse(event.data); } catch { return; }
    if (!msg || typeof msg !== 'object') return;
    currentHandlers?.onMessage?.(msg);
  });

  socket.addEventListener('close', () => {
    socket = null;
    currentHandlers?.onClose?.();
    if (currentToken) scheduleReconnect();
  });

  socket.addEventListener('error', () => {
    try { socket?.close(); } catch { /* ignore */ }
  });
}

export function connectTeacher({ token, onMessage, onOpen, onClose }) {
  disconnectTeacher();
  currentToken = token;
  currentHandlers = { onMessage, onOpen, onClose };
  reconnectDelay = 1000;
  openSocket();
}

export function disconnectTeacher() {
  currentToken = null;
  currentHandlers = null;
  if (reconnectTimer) {
    clearTimeout(reconnectTimer);
    reconnectTimer = null;
  }
  if (socket) {
    try { socket.close(); } catch { /* ignore */ }
    socket = null;
  }
}

export function sendTeacher(obj) {
  if (!socket || socket.readyState !== WebSocket.OPEN) return false;
  try {
    socket.send(JSON.stringify(obj));
    return true;
  } catch { return false; }
}
