// helper module to send emails with nodemailer

const fs = require("fs");
const path = require('path');
const { MailtrapClient } = require("mailtrap");
const nodemailer = require("nodemailer");
const CON = require("./const");
const { GenerateICS } = require("./calendar");
const common = require("./common");
const Handlebars = require('handlebars');

// const { google } = require("googleapis");
// const OAuth2 = google.auth.OAuth2;

const { Shift, Publisher, PrismaClient } = require("@prisma/client");
const { env } = require("../../next.config");
const SMTPTransport = require("nodemailer/lib/smtp-transport");

var transporter;
if (process.env.EMAIL_SERVICE.toLowerCase() === "mailtrap") {

  transporter = nodemailer.createTransport({
    host: process.env.MAILTRAP_HOST || "sandbox.smtp.mailtrap.io",
    port: process.env.MAILTRAP_PORT || 2525,
    auth: {
      user: process.env.MAILTRAP_USER,
      pass: process.env.MAILTRAP_PASS
    },
    pool: true, // use pooled connection
    rateLimit: true, // enable to make sure we are limiting
    maxConnections: 1, // set limit to 1 connection only
    maxMessages: 2 // send 2 emails per second
  });
}
else if (process.env.EMAIL_SERVICE.toLowerCase() === "gmail") {
  transporter = nodemailer.createTransport({
    service: "gmail",
    auth: {
      user: process.env.EMAIL_GMAIL_USERNAME,
      pass: process.env.EMAIL_GMAIL_APP_PASS
    }
  });
}


// ------------------  Email sending ------------------
var lastResult = null;
function setResult(result) {
  lastResult = result;
}
exports.GetLastResult = function () {
  return lastResult;
};

function normalizeEmailAddresses(to) {
  let emails = [];

  if (typeof to === 'string') {
    // Handle CSV string by splitting into an array
    if (to.includes(',')) emails = to.split(/\s*,\s*/);
    else emails = [to]; // Handle single email string
  } else if (Array.isArray(to)) {
    emails = to.map(item => {
      if (typeof item === 'string') return item;
      if (item.name && item.email) return `"${item.name}" <${item.email}>`;
      return JSON.stringify(item); // Handle unexpected object format
    });
  } else if (typeof to === 'object' && to.email) {
    // Handle single object
    emails = [`"${to.name}" <${to.email}>`];
  } else {
    // Fallback for other types
    emails = [String(to)];
  }

  return emails; // Always returns an array
}



/**
 * Final email sending function.
 *
 * @param {string|string[]} to - Email address or array of email addresses.
 * @param {string} subject - Email subject.
 * @param {string} text - Plain text version of the email.
 * @param {string} html - HTML version of the email.
 * @param {Object[]} [attachments=[]] - Array of attachment objects.
 * @returns {Promise} - A promise that resolves when the email is sent.
 */
exports.SendEmail = async function (to, subject, text, html, attachments = []) {
  let sender = process.env.EMAIL_SENDER || '"Специално Свидетелстване София" <sofia@mwitnessing.com>';
  let emailAddresses = normalizeEmailAddresses(to)

  const bypassEmailReccipients = process.env.EMAIL_BYPASS_TO || null;
  if (bypassEmailReccipients !== null && bypassEmailReccipients.length > 0) {
    emailAddresses = bypassEmailReccipients;
    console.log("Emails bypassed. All mails sent to: " + emailAddresses);
  }

  const message = {
    from: sender,
    to: emailAddresses,
    subject,
    text,
    html,
    attachments
  };

  let result = await transporter
    .sendMail(message)
    .then(console.log)
    .catch(console.error);

  return result;
};


exports.SendEmail_ValidateTemplate = async function (to, token, firstName, lastName) {
  let validateUrl = process.env.NEXTAUTH_URL + "/api/email?action=email_response&emailaction=validateEmail&token=" + token + "&email=" + to;
  return await this.SendEmailHandlebars(to, "emailValidate", {
    user: to,
    validateUrl: validateUrl,
    sentDate: common.getDateFormated(new Date())
  });
};


exports.SendEmailHandlebars = async function (to, templateName, model, attachments = []) {
  try {
    // Ensure the sender and mailtrapTestClient are correctly defined or imported

    // Load and compile the main template
    const mainTemplateSource = fs.readFileSync(path.join(process.cwd(), 'src', 'templates', 'emails', 'main.hbs'), 'utf8');
    const mainTemplate = Handlebars.compile(mainTemplateSource);

    // Dynamically load and compile the specified template
    const templateSource = fs.readFileSync(path.join(process.cwd(), 'src', 'templates', 'emails', `${templateName}.hbs`), 'utf8');

    // Extract subject and optional text version from the template source
    const subjectMatch = templateSource.match(/{{!--\s*Subject:\s*(.*?)\s*--}}/);
    const textMatch = templateSource.match(/{{!--\s*Text:\s*([\s\S]*?)\s*--}}/);

    let subject = subjectMatch ? subjectMatch[1].trim() : 'ССОМ: Известие';
    let textVersion = textMatch ? textMatch[1].trim() : null;

    // Remove the subject and text annotations from the template source
    const cleanTemplateSource = templateSource.replace(/{{!-- Subject: .* --}}/, '').replace(/{{!-- Text: [\s\S]*? --}}/, '');
    // const cleanTemplateSource = templateSource
    //   .replace(/{{!--\s*Subject:.*?--}}\s*/, '')
    //   .replace(/{{!--\s*Text:.*?--}}\s*/, '');
    // Compile the cleaned template
    const template = Handlebars.compile(cleanTemplateSource);

    // Render the specified template with the provided model
    const templateHtml = template(model);

    // Render the main template, inserting the specific template HTML
    const html = mainTemplate({ body: templateHtml });

    // Generate a plain text version if not explicitly provided
    let text = textVersion || html.replace(/<[^>]*>?/gm, ''); // Simple regex to strip HTML tags. Might need refinement.
    subject = Handlebars.compile(subject)(model);
    text = Handlebars.compile(text)(model);

    let results = this.SendEmail(to, subject, text, html, attachments);
    return results;

  } catch (error) {
    console.error(error);
    Handlebars.logger.error(error);
    return new Error('Error sending email');
  }
};


exports.SendEmail_NewShifts = async function (publisher, shifts) {
  if (shifts.length === 0) return;

  var date = new Date(shifts[0].startTime);

  // Generate ICS calendar links for all shifts
  const icsLink = CAL.GenerateICS(shifts);

  // Prepare the shifts string
  const shiftStr = shifts.map((s) => {
    return `${CON.weekdaysBG[s.startTime.getDay()]} ${CON.GetDateFormat(s.startTime)} at ${s.cartEvent.location.name} from ${CON.GetTimeFormat(s.startTime)} to ${CON.GetTimeFormat(s.endTime)}`;
  }).join("<br>");

  // Define the model for the Handlebars template
  const model = {
    publisherFirstName: publisher.firstName,
    publisherLastName: publisher.lastName,
    month: CON.monthNamesBG[date.getMonth()],
    shifts: shiftStr,
    sentDate: new Date().toLocaleDateString() // Assuming you want to include the sent date in the email
  };

  await exports.SendEmailHandlebars(publisher.email, "newShifts", model,
    [{
      filename: "calendar.ics",
      content: icsLink,
      contentType: 'text/calendar' // Ensure this is correctly set for the ICS file
    }]
  ).then(console.log).catch(console.error);
};




//----------------------- OLD -----------------------------

// exports.SendEmail_NewShifts = async function (publisher, shifts) {
//   if (shifts.length == 0) return;

//   var date = new Date(shifts[0].startTime);

//   //generate ICS calendar links for all shifts
//   const icsLink = CAL.GenerateICS(shifts);

//   const shftStr = shifts
//     .map((s) => {
//       return `    ${CON.weekdaysBG[s.startTime.getDay()]
//         } ${CON.GetDateFormat(s.startTime)}      ${s.cartEvent.location.name
//         }    ${CON.GetTimeFormat(s.startTime)} - ${CON.GetTimeFormat(
//           s.endTime
//         )}`;
//     })
//     .join("\n");

//   await client.send({
//     from: sender,
//     to: [
//       {
//         email: "dobromir.popov@gmail.com",//publisher.email,
//         name: publisher.firstName + " " + publisher.lastName,
//       },
//     ],
//     subject: "[CCC]: вашите смени през " + CON.monthNamesBG[date.getMonth()],
//     text:
//       "Здравей, " + publisher.firstName + " " + publisher.lastName + "!\n\n" +
//       "Ти регистриран да получавате известия за нови смени на количка.\n" +
//       `За месец ${CON.monthNamesBG[date.getMonth()]} имате следните смени:\n` +
//       ` ${shftStr} \n\n\n` +
//       "Поздрави,\n" +
//       "Специално Свидетелстване София",
//     attachments: [
//       {
//         filename: "calendar.ics",
//         content_id: "calendar.ics",
//         disposition: "inline",
//         content: icsLink,
//       },
//     ],
//   })
//     .then(console.log, console.error, setResult);
// };


// // https://mailtrap.io/blog/sending-emails-with-nodemailer/
// exports.SendEmail_Example = async function (to) {
//   const welcomeImage = fs.readFileSync(
//     path.join(CON.contentPath, "welcome.png")
//   );

//   await client
//     .send({
//       category: "test",
//       custom_variables: {
//         hello: "world",
//         year: 2022,
//         anticipated: true,
//       },
//       from: sender,
//       to: [{ email: to }],
//       subject: "Hello from Mailtrap!",
//       html: `<!doctype html>
//             <html>
//             <head>
//                 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
//             </head>
//             <body style="font-family: sans-serif;">
//                 <div style="display: block; margin: auto; max-width: 600px;" class="main">
//                 <h1 style="font-size: 18px; font-weight: bold; margin-top: 20px">Congrats for sending test email with Mailtrap!</h1>
//                 <p>Inspect it using the tabs you see above and learn how this email can be improved.</p>
//                 <img alt="Inspect with Tabs" src="cid:welcome.png" style="width: 100%;">
//                 <p>Now send your email using our fake SMTP server and integration of your choice!</p>
//                 <p>Good luck! Hope it works.</p>
//                 </div>
//                 <!-- Example of invalid for email html/css, will be detected by Mailtrap: -->
//                 <style>
//                 .main { background-color: white; }
//                 a:hover { border-left-width: 1em; min-height: 2em; }
//                 </style>
//             </body>
//             </html>`,
//       attachments: [
//         {
//           filename: "welcome.png",
//           content_id: "welcome.png",
//           disposition: "inline",
//           content: welcomeImage,
//         },
//       ],
//     })
//     .then(console.log, console.error, setResult);
// };
