const path = require("path");
require("dotenv").config({
  path: path.resolve(
    process.cwd(),
    `.env.${process.env.NODE_ENV || "development"}`
  ),
});
const axios = require("axios");
let nodemailer = require("nodemailer");
let aws = require("aws-sdk");
const logger = require("../utils/logger");
const client = require("../graphql-client/graphql-client").client;
const queries = require("../graphql-client/queries");

const ses = new aws.SES({
  apiVersion: "latest",

  region: "ca-central-1",
});

let transporter = nodemailer.createTransport({
  SES: { ses, aws },
});

exports.sendServerEmail = async function ({ subject, text }) {
  try {
    transporter.sendMail(
      {
        from: `ImEX Online API - ${process.env.NODE_ENV} <noreply@imex.online>`,
        to: ["patrick@snapt.ca"],
        subject: subject,
        text: text,
        ses: {
          // optional extra arguments for SendRawEmail
          Tags: [
            {
              Name: "tag_name",
              Value: "tag_value",
            },
          ],
        },
      },
      (err, info) => {
        console.log(err || info);
      }
    );
  } catch (error) {
    console.log(error);
    logger.log("server-email-failure", "error", null, null, error);
    res.status(500).json(error);
  }
};
exports.sendTaskEmail = async function ({ to, subject, text, attachments }) {
  try {
    transporter.sendMail(
      {
        from: `ImEX Online <noreply@imex.online>`,
        to: to,
        subject: subject,
        text: text,
        attachments: attachments || null,
      },
      (err, info) => {
        console.log(err || info);
      }
    );
  } catch (error) {
    console.log(error);
    logger.log("server-email-failure", "error", null, null, error);
  }
};

exports.sendEmail = async (req, res) => {
  logger.log("send-email", "DEBUG", req.user.email, null, {
    from: `${req.body.from.name} <${req.body.from.address}>`,
    replyTo: req.body.ReplyTo.Email,
    to: req.body.to,
    cc: req.body.cc,
    subject: req.body.subject,
  });

  let downloadedMedia = [];
  if (req.body.media && req.body.media.length > 0) {
    downloadedMedia = await Promise.all(
      req.body.media.map((m) => {
        try {
          return getImage(m);
        } catch (error) {
          logger.log("send-email-error", "ERROR", req.user.email, null, {
            from: `${req.body.from.name} <${req.body.from.address}>`,
            replyTo: req.body.ReplyTo.Email,
            to: req.body.to,
            cc: req.body.cc,
            subject: req.body.subject,
            error,
          });
        }
      })
    );
  }

  transporter.sendMail(
    {
      from: `${req.body.from.name} <${req.body.from.address}>`,
      replyTo: req.body.ReplyTo.Email,
      to: req.body.to,
      cc: req.body.cc,
      subject: req.body.subject,
      attachments:
        [
          ...((req.body.attachments &&
            req.body.attachments.map((a) => {
              return {
                filename: a.filename,
                path: a.path,
              };
            })) ||
            []),
          ...downloadedMedia.map((a) => {
            return {
              path: a,
            };
          }),
        ] || null,
      html: req.body.html,
      ses: {
        // optional extra arguments for SendRawEmail
        Tags: [
          {
            Name: "tag_name",
            Value: "tag_value",
          },
        ],
      },
    },
    (err, info) => {
      console.log(err || info);
      if (info) {
        logger.log("send-email-success", "DEBUG", req.user.email, null, {
          from: `${req.body.from.name} <${req.body.from.address}>`,
          replyTo: req.body.ReplyTo.Email,
          to: req.body.to,
          cc: req.body.cc,
          subject: req.body.subject,
          // info,
        });
        logEmail(req, {
          to: req.body.to,
          cc: req.body.cc,
          subject: req.body.subject,
          messageId: info.response,
        });
        res.json({
          success: true, //response: info
        });
      } else {
        logger.log("send-email-failure", "ERROR", req.user.email, null, {
          from: `${req.body.from.name} <${req.body.from.address}>`,
          replyTo: req.body.ReplyTo.Email,
          to: req.body.to,
          cc: req.body.cc,
          subject: req.body.subject,
          error: err,
        });
        logEmail(req, {
          to: req.body.to,
          cc: req.body.cc,
          subject: req.body.subject,
          bodyshopid: req.body.bodyshopid,
        });
        res.status(500).json({ success: false, error: err });
      }
    }
  );
};

async function getImage(imageUrl) {
  let image = await axios.get(imageUrl, { responseType: "arraybuffer" });
  let raw = Buffer.from(image.data).toString("base64");
  return "data:" + image.headers["content-type"] + ";base64," + raw;
}

async function logEmail(req, email) {
  try {
    const insertresult = await client.request(queries.INSERT_EMAIL_AUDIT, {
      email: {
        to: email.to,
        cc: email.cc,
        subject: email.subject,
        bodyshopid: req.body.bodyshopid,
        useremail: req.user.email,
        contents: req.body.html,
        jobid: req.body.jobid,
        sesmessageid: email.messageId,
        status: "Sent",
      },
    });
    console.log(insertresult);
  } catch (error) {
    logger.log("email-log-error", "error", req.user.email, null, {
      from: `${req.body.from.name} <${req.body.from.address}>`,
      to: req.body.to,
      cc: req.body.cc,
      subject: req.body.subject,
      // info,
    });
  }
}

exports.emailBounce = async function (req, res, next) {
  try {
    const body = JSON.parse(req.body);
    if (body.Type === "SubscriptionConfirmation") {
      logger.log("SNS-message", "DEBUG", "api", null, {
        body: req.body,
      });
    }
    const message = JSON.parse(body.Message);
    if (message.notificationType === "Bounce") {
      let replyTo, subject, messageId;
      message.mail.headers.forEach((header) => {
        if (header.name === "Reply-To") {
          replyTo = header.value;
        } else if (header.name === "Subject") {
          subject = header.value;
        }
      });
      messageId = message.mail.messageId;
      if (replyTo === "noreply@imex.online") {
        res.sendStatus(200);
        return;
      }
      //If it's bounced, log it as bounced in audit log. Send an email to the user.
      const result = await client.request(queries.UPDATE_EMAIL_AUDIT, {
        sesid: messageId,
        status: "Bounced",
        context: message.bounce?.bouncedRecipients,
      });
      transporter.sendMail(
        {
          from: `ImEX Online <noreply@imex.online>`,
          to: replyTo,
          //bcc: "patrick@snapt.ca",
          subject: `ImEX Online Bounced Email - RE: ${subject}`,
          text: `ImEX Online has tried to deliver an email with the subject: ${subject} to the intended recipients but encountered an error.

${body.bounce?.bouncedRecipients.map(
  (r) =>
    `Recipient: ${r.emailAddress} | Status: ${r.action} | Code: ${r.diagnosticCode}
            `
)}
        `,
        },
        (err, info) => {
          console.log("***", err || info);
        }
      );
    }
  } catch (error) {
    logger.log("sns-error", "ERROR", "api", null, {
      error: JSON.stringify(error),
    });
  }
  res.sendStatus(200);
};
