import { readySendChat } from './render';

const socketUrl = 'wss://seller-push-ws.shopee.vn/socket.io/?region=vn&EIO=3&transport=websocket';

const parseChatMessage = (message) => {
  try {
    const prase = JSON.parse(message.replace(/^(\d*?)\[/, '['));
    return {
      event: prase[0] || '',
      data: prase[1] || {},
    };
  } catch (error) {
    return {
      event: '',
      data: {},
    };
  }
};

const getAuthSocket = async () => {
  const { userId, token } = await readySendChat();

  return [
    '420',
    JSON.stringify([
      'login',
      {
        token,
        account_id: `0-${userId}`,
        app_id: 'pmminichat',
      },
    ]),
  ].join('');
};

const configConnect = {
  intervalPing: 5000,
  sendLogin: 2000,
};

/**
 *
 * @param {Function} onMessageCallback
 * @param {Function} onConnectCallback
 * @param {Function} onDisconnectCallback
 * @returns
 */
export const socketConnectChat = async (onMessageCallback, onConnectCallback, onDisconnectCallback) => {
  let intervalPing = null;

  const socket = new WebSocket(socketUrl);

  const sendPing = () => {
    socket.send('2');
    socket.send(`42${JSON.stringify(['heartbeat', 'heart beat'])}`);
    socket.send(`42${JSON.stringify(['heartbeat', 'pmminichat|0|0'])}`);
  };

  const sendAuth = async () => {
    const payloadAuth = await getAuthSocket();
    return socket.send(payloadAuth);
  };

  const onMessage = (event) => {
    let message = event.data;

    if (!message) {
      return false;
    }

    message = message.trim();

    if (!message || ['3', '2'].includes(message)) {
      return false;
    }

    if (message === '40') {
      return setTimeout(sendAuth, configConnect.sendLogin);
    }

    const { event: eventMessage, data: dataMessage } = parseChatMessage(message);

    if (eventMessage && eventMessage === 'message' && dataMessage.message_content) {
      /** @type {ShopeeWebchatSocketMessage} */
      const chatLog = JSON.parse(dataMessage.message_content);

      if (!(chatLog && chatLog.request_id)) {
        return false;
      }

      if (onMessageCallback) {
        onMessageCallback(chatLog);
      }
    }
  };

  socket.onopen = () => {
    if (onConnectCallback) {
      onConnectCallback(socket);
    }

    intervalPing = setInterval(sendPing, configConnect.intervalPing);
  };

  socket.onclose = () => {
    if (onDisconnectCallback) {
      onDisconnectCallback('closed');
    }
    clearInterval(intervalPing);
  };

  socket.onerror = (error) => {
    if (onDisconnectCallback) {
      onDisconnectCallback(error);
    }

    clearInterval(intervalPing);
  };

  socket.onmessage = onMessage;

  return socket;
};
