const twilio = require("twilio");
const { phone } = require("phone");
const { INSERT_MESSAGE } = require("../graphql-client/queries");
const client = twilio(process.env.TWILIO_AUTH_TOKEN, process.env.TWILIO_AUTH_KEY);
const gqlClient = require("../graphql-client/graphql-client").client;

/**
 * Send an outbound SMS message
 * @param req
 * @param res
 * @returns {Promise<void>}
 */
const send = async (req, res) => {
  const { to, messagingServiceSid, body, conversationid, selectedMedia } = req.body;
  const {
    ioRedis,
    logger,
    ioHelpers: { getBodyshopRoom, getBodyshopConversationRoom }
  } = req;

  logger.log("sms-outbound", "DEBUG", req.user.email, null, {
    messagingServiceSid,
    to: phone(to).phoneNumber,
    mediaUrl: selectedMedia.map((i) => i.src),
    text: body,
    conversationid,
    isoutbound: true,
    userid: req.user.email,
    image: selectedMedia.length > 0,
    image_path: selectedMedia.length > 0 ? selectedMedia.map((i) => i.src) : []
  });

  if (!to || !messagingServiceSid || (!body && selectedMedia.length === 0) || !conversationid) {
    logger.log("sms-outbound-error", "ERROR", req.user.email, null, {
      type: "missing-parameters",
      messagingServiceSid,
      to: phone(to).phoneNumber,
      text: body,
      conversationid,
      isoutbound: true,
      userid: req.user.email,
      image: selectedMedia.length > 0,
      image_path: selectedMedia.length > 0 ? selectedMedia.map((i) => i.src) : []
    });
    res.status(400).json({ success: false, message: "Missing required parameter(s)." });
    return;
  }

  try {
    const message = await client.messages.create({
      body,
      messagingServiceSid,
      to: phone(to).phoneNumber,
      mediaUrl: selectedMedia.map((i) => i.src)
    });

    const newMessage = {
      msid: message.sid,
      text: body,
      conversationid,
      isoutbound: true,
      userid: req.user.email,
      image: selectedMedia.length > 0,
      image_path: selectedMedia.length > 0 ? selectedMedia.map((i) => i.src) : [],
      is_system: false
    };

    try {
      const gqlResponse = await gqlClient.request(INSERT_MESSAGE, {
        msg: newMessage,
        conversationid
      });

      logger.log("sms-outbound-success", "DEBUG", req.user.email, null, {
        msid: message.sid,
        conversationid
      });

      const insertedMessage = gqlResponse.insert_messages.returning[0];
      const broadcastRoom = getBodyshopRoom(insertedMessage.conversation.bodyshop.id);
      const conversationRoom = getBodyshopConversationRoom({
        bodyshopId: insertedMessage.conversation.bodyshop.id,
        conversationId: insertedMessage.conversation.id
      });

      ioRedis.to(broadcastRoom).emit("new-message-summary", {
        isoutbound: true,
        conversationId: conversationid,
        updated_at: insertedMessage.updated_at,
        msid: message.sid,
        summary: true
      });

      ioRedis.to(conversationRoom).emit("new-message-detailed", {
        newMessage: insertedMessage,
        conversationId: conversationid,
        summary: false
      });

      res.sendStatus(200);
    } catch (gqlError) {
      logger.log("sms-outbound-error", "ERROR", req.user.email, null, {
        msid: message.sid,
        conversationid,
        error: gqlError.message,
        stack: gqlError.stack
      });
      res.status(500).json({ success: false, message: "Failed to insert message into database." });
    }
  } catch (twilioError) {
    logger.log("sms-outbound-error", "ERROR", req.user.email, null, {
      conversationid,
      error: twilioError.message,
      stack: twilioError.stack
    });
    res.status(500).json({ success: false, message: "Failed to send message through Twilio." });
  }
};

module.exports = {
  send
};
