import nodemailer from "nodemailer";
import { openStore } from "@/lib/data/store";
import type { MailSettings } from "@/lib/types";

/**
 * Sending is deliberately forgiving: if no server is configured, or the send
 * fails, the caller carries on. A signup shouldn't fail because the mail
 * server is down.
 */
export async function sendMail(opts: {
  to: string;
  subject: string;
  heading: string;
  body: string;
  action?: { label: string; url: string };
}): Promise<{ sent: boolean; reason?: string }> {
  const store = await openStore();
  const m = await store.small<MailSettings>("mailSettings", {} as MailSettings);
  const site = await store.settings();

  if (!m.enabled || !m.host || !m.fromAddress) {
    return { sent: false, reason: "Email isn't configured" };
  }
  if (!opts.to) return { sent: false, reason: "No address to send to" };

  try {
    const transport = nodemailer.createTransport({
      host: m.host,
      port: m.port,
      secure: m.secure,
      auth: m.username ? { user: m.username, pass: m.password } : undefined,
    });

    await transport.sendMail({
      from: `"${m.fromName}" <${m.fromAddress}>`,
      to: opts.to,
      subject: opts.subject,
      text: `${opts.heading}\n\n${opts.body}${
        opts.action ? `\n\n${opts.action.label}: ${opts.action.url}` : ""
      }`,
      html: template(opts, String(site.siteName ?? "")),
    });

    return { sent: true };
  } catch (err) {
    return { sent: false, reason: err instanceof Error ? err.message : "Send failed" };
  }
}

/** One plain, readable layout for every message the site sends. */
function template(
  opts: { heading: string; body: string; action?: { label: string; url: string } },
  siteName: string
) {
  return `<!doctype html>
<html>
  <body style="margin:0;padding:24px;background:#f4f6fa;font-family:system-ui,-apple-system,'Segoe UI',sans-serif;">
    <table role="presentation" style="max-width:520px;margin:0 auto;background:#fff;border-radius:16px;overflow:hidden;border:1px solid #e6e8ef;">
      <tr>
        <td style="padding:26px 30px 0;">
          <p style="margin:0;font-size:13px;font-weight:800;letter-spacing:.4px;text-transform:uppercase;color:#7c3aed;">${escape(siteName)}</p>
          <h1 style="margin:12px 0 0;font-size:21px;font-weight:800;color:#18181b;">${escape(opts.heading)}</h1>
        </td>
      </tr>
      <tr>
        <td style="padding:14px 30px 0;">
          <p style="margin:0;font-size:15px;line-height:1.65;color:#52525b;">${escape(opts.body).replace(/\n/g, "<br>")}</p>
        </td>
      </tr>
      ${
        opts.action
          ? `<tr><td style="padding:22px 30px 0;">
               <a href="${escape(opts.action.url)}" style="display:inline-block;padding:12px 24px;border-radius:10px;background:#7c3aed;color:#fff;font-size:14px;font-weight:700;text-decoration:none;">${escape(opts.action.label)}</a>
             </td></tr>`
          : ""
      }
      <tr>
        <td style="padding:26px 30px 28px;">
          <p style="margin:0;font-size:12px;color:#a1a1aa;">You're receiving this because you have an account on ${escape(siteName)}.</p>
        </td>
      </tr>
    </table>
  </body>
</html>`;
}

/** Values go into HTML, so they're escaped rather than trusted. */
function escape(s: string) {
  return String(s)
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;");
}
