import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { db } from "../../../../database/dbclient.js";
import { settings } from "../../../../database/schema/settings.js";
import nodemailer from "nodemailer";
import type { Transporter } from "nodemailer";
import type SMTPTransport from "nodemailer/lib/smtp-transport/index.js";
import type Mail from "nodemailer/lib/mailer/index.js";
import type { Address } from "nodemailer/lib/mailer/index.js";
import path from "path";
import { fileURLToPath } from "url";
import hbs from "nodemailer-express-handlebars";
import { promisify } from "util";
import { createLog } from "../../logger/logger.js";
import { installed } from "../../../index.js";

interface HandlebarsMailOptions extends Mail.Options {
    template: string;
    context: Record<string, unknown>; // Use a generic object for context
}

interface EmailData {
    email: string;
    subject: string;
    template: string;
    context: [];
}

export const sendEmail = async (data: any): Promise<any> => {
    if (!installed) {
        createLog("error", "notify", "notify", "server not installed.");
        return;
    }
    let transporter: Transporter;
    let fromEmail: string | Address;
    const { data: settingData, error: settingError } = await tryCatch(
        db.select().from(settings)
    );

    if (settingError) {
        return {
            success: false,
            message: "There was an error getting the settings.",
            settingError,
        };
    }
    // get the plantToken
    const server = settingData.filter((n) => n.name === "server");

    if (
        server[0].value === "localhost" &&
        process.env.EMAIL_USER &&
        process.env.EMAIL_PASSWORD
    ) {
        transporter = nodemailer.createTransport({
            service: "gmail",
            auth: {
                user: process.env.EMAIL_USER,
                pass: process.env.EMAIL_PASSWORD,
            },
            //debug: true,
        });

        // update the from email
        fromEmail = process.env.EMAIL_USER;
    } else {
        // convert to the correct plant token.
        const plantToken = settingData.filter((s) => s.name === "plantToken");

        let host = `${plantToken[0].value}-smtp.alpla.net`;

        const testServers = ["test1", "test2", "test3"];

        if (testServers.includes(plantToken[0].value)) {
            host = "USMCD1-smtp.alpla.net";
        }

        if (plantToken[0].value === "usiow2") {
            host = "USIOW1-smtp.alpla.net";
        }

        transporter = nodemailer.createTransport({
            host: host,
            port: 25,
            rejectUnauthorized: false,
            //secure: false,
            // auth: {
            //   user: "alplaprod",
            //   pass: "obelix",
            // },
            debug: true,
        } as SMTPTransport.Options);

        // update the from email
        fromEmail = `noreply@alpla.com`;
    }

    // creating the handlbar options
    const viewPath = path.resolve(
        path.dirname(fileURLToPath(import.meta.url)),
        "../utils/views/"
    );

    const handlebarOptions = {
        viewEngine: {
            extname: ".hbs",
            //layoutsDir: path.resolve(viewPath, "layouts"), // Path to layouts directory
            defaultLayout: "", // Specify the default layout
            partialsDir: viewPath,
        },
        viewPath: viewPath,
        extName: ".hbs", // File extension for Handlebars templates
    };

    transporter.use("compile", hbs(handlebarOptions));

    const mailOptions: HandlebarsMailOptions = {
        from: fromEmail,
        to: data.email,
        subject: data.subject,
        //text: "You will have a reset token here and only have 30min to click the link before it expires.",
        //html: emailTemplate("BlakesTest", "This is an example with css"),
        template: data.template, // Name of the Handlebars template (e.g., 'welcome.hbs')
        context: data.context,
    };

    // now verify and send the email
    const sendMailPromise = promisify(transporter.sendMail).bind(transporter);

    try {
        // Send email and await the result
        const info = await sendMailPromise(mailOptions);
        createLog(
            "info",
            "notification",
            "system",
            `Email was sent to: ${data.email}`
        );
        return { success: true, message: "Email sent.", data: info };
    } catch (err) {
        console.log(err);
        createLog(
            "error",
            "notification",
            "system",
            `Error sending Email: ${JSON.stringify(err)}`
        );
        return { success: false, message: "Error sending email.", error: err };
    }
};
