import config from 'config';
import { Resend } from 'resend';

import { emailTemplates } from './email-templates.js';
import initLogger from './logger.js';

const logger = initLogger();

const resend = (() => {
	if (config.email.enabled) {
		try {
			return new Resend(config.email.apiKey);
		}
		catch (error) {
			logger.error(`Failed to initialize Resend: ${error.message}`);
		}
	}

	return null;
})();

export async function renderEmail(template, { to, subject, props }) {
	const { html, text } = await emailTemplates.render(`${template}.vue`, {
		props: {
			...props,
			address: config.web.address,
		},
	});

	return {
		from: config.email.from,
		to,
		subject,
		html,
		text,
	};
}

// always batches, even for a single item: Resend's batch endpoint accepts a batch of one,
// and passing batchValidation: 'permissive' means one bad recipient among many doesn't
// sink the rest of the batch (the default 'strict' mode fails the whole call instead)
export async function sendEmails(items) {
	if (!config.email.enabled) {
		return null;
	}

	if (!resend) {
		logger.warn('E-mails are enabled, but Resend is not initialized');
		return null;
	}

	const rendered = await Promise.all(items.map(async (item) => {
		try {
			return await renderEmail(item.template, item);
		}
		catch (error) {
			logger.error(`Failed to render '${item.template}' e-mail for '${item.to}': ${error.message} — ${JSON.stringify(item.props)}`);
			return null;
		}
	}));

	const sentItems = items.filter((item, index) => rendered[index]);
	const emails = rendered.filter(Boolean);

	if (emails.length === 0) {
		return null;
	}

	const { data, error } = await resend.batch.send(emails, { batchValidation: 'permissive' });

	if (error) {
		logger.error(`Failed to send ${emails.length} e-mail(s) (${error.statusCode} ${error.name}): ${error.message}`);
		return null;
	}

	data.errors?.forEach(({ index, message }) => {
		const item = sentItems[index];
		logger.error(`Failed to send '${item.template}' e-mail to '${item.to}': ${message} — ${JSON.stringify(item.props)}`);
	});

	logger.info(`Sent ${emails.length - (data.errors?.length || 0)}/${items.length} e-mail(s)`);

	return data;
}
