import { render } from "@react-email/render";
import { TRPCError } from "@trpc/server";
import ContattoAdminEmail, {
	type ContattoAdmin_NewMail,
} from "emails/contatto";
import type { ContattoAnnuncio_NewMail } from "emails/contatto_annuncio";
import ContattoAnnuncioEmail from "emails/contatto_annuncio";
import EmailContattoInteressato, {
	type ContattoInteressato_NewMail,
} from "emails/email-interessato";
import type { Generic_NewMail } from "emails/gereric-email";
import Generic from "emails/gereric-email";
import type { Invito_NewMail } from "emails/invito";
import Invito from "emails/invito";
import OnboardingServizio, {
	type OnboardingServizio_NewMail,
} from "emails/onboarding-servizio";
import type { PagamentoConferma_NewMail } from "emails/pagamento-conferma";
import PagamentoConferma from "emails/pagamento-conferma";
import type { PagamentoErrore_NewMail } from "emails/pagamento-errore";
import PagamentoErrore from "emails/pagamento-errore";
import type { PagamentoRicezione_NewMail } from "emails/pagamento-ricezione";
import PagamentoRicezione from "emails/pagamento-ricezione";
import type { PwResetLink_NewMail } from "emails/pw-reset-link";
import PwResetLink from "emails/pw-reset-link";
import type { Recesso_NewMail } from "emails/recesso";
import Recesso from "emails/recesso";
import type { RegistrazioneAvvenuta_NewMail } from "emails/registrazione-avvenuta";
import RegistrazioneAvvenuta from "emails/registrazione-avvenuta";
import EmailSchedaContatto, {
	type SchedaContatto_NewMail,
} from "emails/scheda-annuncio";
import VerificaEmail, {
	type VerificaEmail_NewMail,
} from "emails/VerificaEmail";
import { createTransport } from "nodemailer";
import type { Options } from "nodemailer/lib/mailer";
import { htmlToText } from "nodemailer-html-to-text";
import type { JSX } from "react";
import { env } from "~/env";
import type { UsersId } from "~/schemas/public/Users";
import { GetFlagValueHandler } from "~/server/controllers/flags.controller";
import { db } from "~/server/db";
import { StoreEmail } from "~/server/services/email.service";

const mailer = async (options: Options) => {
	const smtpTransport = createTransport({
		auth: {
			pass: env.ARUBA_PASS,
			user: env.ARUBA_USER,
		},
		debug: false,
		host: "smtps.aruba.it",
		logger: false,
		port: 465,
		secure: true,
		tls: {
			ciphers: "HIGH:MEDIUM:!aNULL:!eNULL:@STRENGTH:!DH:!kEDH",
			minVersion: "TLSv1",
		},
	});
	smtpTransport.use("compile", htmlToText());

	const message: Options = {
		from: `"InfoAlloggi" <${env.ARUBA_USER}>`,
		...options,
	};
	smtpTransport.sendMail(message, (err, info) => {
		if (err) {
			throw new Error(err.message);
		}
		return info;
	});
};

export type NewMailProps = {
	template?: MailsTemplates;
	userId?: UsersId;
	mail: Options;
};
export type MailsTemplates =
	| ContattoAdmin_NewMail
	| ContattoAnnuncio_NewMail
	| ContattoInteressato_NewMail
	| PagamentoConferma_NewMail
	| PagamentoErrore_NewMail
	| PagamentoRicezione_NewMail
	| PwResetLink_NewMail
	| Recesso_NewMail
	| RegistrazioneAvvenuta_NewMail
	| VerificaEmail_NewMail
	| OnboardingServizio_NewMail
	| Generic_NewMail
	| SchedaContatto_NewMail
	| Invito_NewMail;

export const genMail = async ({ ...mail }: MailsTemplates) => {
	let mailComponent: JSX.Element | null = null;
	let title = "";

	switch (mail.mailType) {
		case "contattoAdminEmail":
			mailComponent = ContattoAdminEmail({
				...mail.props,
			});
			title = "Contatto amministratore";
			break;
		case "contattoAnnuncioEmail":
			mailComponent = ContattoAnnuncioEmail({
				...mail.props,
			});
			title = "Contatto annuncio";
			break;

		case "emailContattoInteressato":
			mailComponent = EmailContattoInteressato({
				...mail.props,
			});
			title = "Contatto interessato";
			break;

		case "pagamentoConferma":
			mailComponent = PagamentoConferma({
				...mail.props,
			});
			title = "Conferma pagamento";
			break;

		case "pagamentoErrore":
			mailComponent = PagamentoErrore();
			title = "Errore pagamento";
			break;

		case "pagamentoRicezione":
			mailComponent = PagamentoRicezione();
			title = "Ricezione pagamento";
			break;

		case "pwResetLink":
			mailComponent = PwResetLink({
				...mail.props,
			});
			title = "Reset password";
			break;

		case "recesso":
			mailComponent = Recesso();
			title = "Recesso";
			break;

		case "registrazioneAvvenuta":
			mailComponent = RegistrazioneAvvenuta();
			title = "Registrazione avvenuta";
			break;

		case "verificaEmail":
			mailComponent = VerificaEmail({
				...mail.props,
			});
			title = "Verifica email";
			break;

		case "onboardingServizio":
			mailComponent = OnboardingServizio({
				...mail.props,
			});
			title = "Onboarding Servizio";
			break;
		case "generic":
			mailComponent = Generic({
				...mail.props,
			});
			title = mail.props.title || "Email Generica";
			break;
		case "emailSchedaContatto":
			mailComponent = EmailSchedaContatto({
				...mail.props,
			});
			title = "Scheda Contatto Annuncio";
			break;
		case "invito":
			mailComponent = Invito({
				...mail.props,
			});
			title = "Invito al sito";
			break;
		default:
			mailComponent = null;
			break;
	}
	if (mailComponent === null) {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: "Errore nella creazione dell'email",
		});
	}

	return { html: await render(mailComponent), title };
};

export const NewMail = async ({ template, userId, mail }: NewMailProps) => {
	const emailFlag = await GetFlagValueHandler({
		db: db,
		id: "EMAIL_ENABLED",
	});
	if (emailFlag) {
		try {
			if (template) {
				const { html } = await genMail({ ...template });
				await mailer({
					html,
					...mail,
				});
			} else {
				await mailer({
					...mail,
				});
			}
		} catch (e) {
			throw new TRPCError({
				code: "INTERNAL_SERVER_ERROR",
				message: `Errore nell'invio dell'email: ${(e as Error).message}`,
			});
		}
	} else {
		console.warn(
			`Email sending is disabled to:${mail.to} subj:${mail.subject} msgType: ${template?.mailType}`,
		);
	}

	if (userId && template) {
		// Store the email in the database if userId is provided
		await StoreEmail({ data: template, userId });
	}
};
