/**
 * Nodemailer transport + Handlebars rendering (PLANNING.md §2).
 *
 * When SMTP_HOST is unset the transport is null and sendMail() is a logged
 * no-op — local dev and CI need no mail server. A real SMTP failure throws;
 * callers that must not fail on it (the enquiry flow, §9) catch and continue.
 */
import nodemailer, { type Transporter } from 'nodemailer';
import Handlebars from 'handlebars';
import { env } from '../env';
import { logger } from './logger';

const transport: Transporter | null = env.SMTP_HOST
  ? nodemailer.createTransport({
      host: env.SMTP_HOST,
      port: env.SMTP_PORT ?? 465,
      secure: (env.SMTP_PORT ?? 465) === 465,
      auth: env.SMTP_USER ? { user: env.SMTP_USER, pass: env.SMTP_PASSWORD } : undefined,
    })
  : null;

const compiledCache = new Map<string, Handlebars.TemplateDelegate>();

/** Compile (and cache) a Handlebars source string, then render it. */
export function renderTemplate(source: string, data: Record<string, unknown>): string {
  let tpl = compiledCache.get(source);
  if (!tpl) {
    tpl = Handlebars.compile(source, { noEscape: false });
    compiledCache.set(source, tpl);
  }
  return tpl(data);
}

export interface SendMailInput {
  to: string;
  subject: string;
  html: string;
  /** Where a human reply from `to` should land (e.g. the team inbox). */
  replyTo?: string;
}

export async function sendMail(input: SendMailInput): Promise<{ skipped: boolean }> {
  if (!transport) {
    logger.info({ to: input.to, subject: input.subject }, 'mail skipped (no SMTP configured)');
    return { skipped: true };
  }
  await transport.sendMail({
    from: env.MAIL_FROM ?? env.SMTP_USER,
    to: input.to,
    subject: input.subject,
    html: input.html,
    ...(input.replyTo ? { replyTo: input.replyTo } : {}),
  });
  return { skipped: false };
}
