import nodemailer, { type Transporter } from "nodemailer";
import { isProduction, smtp } from "./config";

/**
 * Outbound mail for confirmation links.
 *
 * Without SMTP credentials the behaviour splits by environment on purpose:
 * development logs the link to the server console so the flow stays testable,
 * while production throws — an unverifiable signup must fail loudly rather than
 * quietly creating accounts nobody can confirm.
 */

let cachedTransport: Transporter | null = null;

function getTransport(): Transporter {
  if (!cachedTransport) {
    cachedTransport = nodemailer.createTransport({
      host: smtp.host,
      port: smtp.port,
      secure: smtp.secure,
      auth: { user: smtp.user, pass: smtp.password },
    });
  }
  return cachedTransport;
}

export interface TransactionalMail {
  to: string;
  name?: string | null;
  link: string;
  lang: "de" | "en";
}

/** Kept as an alias so existing call sites read naturally. */
export type VerificationMail = TransactionalMail;

export interface MailResult {
  delivered: boolean;
  /** Present only in development when SMTP is unconfigured. */
  devLink?: string;
}

export async function sendVerificationEmail(mail: TransactionalMail): Promise<MailResult> {
  return deliver(mail, "confirmation", renderVerificationEmail(mail));
}

export async function sendPasswordResetEmail(mail: TransactionalMail): Promise<MailResult> {
  return deliver(mail, "password reset", renderPasswordResetEmail(mail));
}

interface RenderedMail {
  subject: string;
  html: string;
  text: string;
}

/**
 * Shared delivery path for every transactional mail, so the SMTP-missing policy
 * (throw in production, log the link in development) can only ever be decided
 * in one place.
 */
async function deliver(
  mail: TransactionalMail,
  label: string,
  rendered: RenderedMail
): Promise<MailResult> {
  if (!smtp.isConfigured) {
    if (isProduction) {
      throw new Error(
        `SMTP is not configured — set SMTP_HOST, SMTP_USER and SMTP_PASSWORD to send ${label} links.`
      );
    }
    console.info(`\n[auth] SMTP unconfigured. ${label} link for ${mail.to}:\n${mail.link}\n`);
    return { delivered: false, devLink: mail.link };
  }

  await getTransport().sendMail({
    from: smtp.from,
    to: mail.to,
    subject: rendered.subject,
    text: rendered.text,
    html: rendered.html,
  });

  return { delivered: true };
}

/** Verifies the SMTP credentials without sending anything. Used by the health check. */
export async function verifySmtpConnection(): Promise<boolean> {
  if (!smtp.isConfigured) return false;
  try {
    await getTransport().verify();
    return true;
  } catch {
    return false;
  }
}

function renderVerificationEmail({ name, link, lang }: TransactionalMail): RenderedMail {
  const isDe = lang === "de";
  const greeting = name ? (isDe ? `Hallo ${name},` : `Hi ${name},`) : isDe ? "Hallo," : "Hi,";

  const subject = isDe
    ? "Bestätige deine E-Mail-Adresse — ScanReceipts"
    : "Confirm your email address — ScanReceipts";

  const intro = isDe
    ? "bitte bestätige deine E-Mail-Adresse, um dein ScanReceipts-Konto zu aktivieren."
    : "please confirm your email address to activate your ScanReceipts account.";

  const cta = isDe ? "E-MAIL BESTÄTIGEN" : "CONFIRM EMAIL";

  const fallback = isDe
    ? "Falls der Button nicht funktioniert, kopiere diesen Link in deinen Browser:"
    : "If the button doesn't work, paste this link into your browser:";

  const expiry = isDe
    ? "Der Link ist 24 Stunden gültig."
    : "This link is valid for 24 hours.";

  const ignore = isDe
    ? "Du hast kein Konto angelegt? Dann ignoriere diese E-Mail einfach."
    : "Didn't create an account? You can safely ignore this email.";

  return renderShell({
    lang,
    subject,
    heading: isDe ? "E-Mail bestätigen" : "Confirm your email",
    greeting,
    intro,
    cta,
    link,
    fallback,
    footer: [expiry, ignore],
  });
}

function renderPasswordResetEmail({ name, link, lang }: TransactionalMail): RenderedMail {
  const isDe = lang === "de";
  const greeting = name ? (isDe ? `Hallo ${name},` : `Hi ${name},`) : isDe ? "Hallo," : "Hi,";

  return renderShell({
    lang,
    subject: isDe
      ? "Passwort zurücksetzen — ScanReceipts"
      : "Reset your password — ScanReceipts",
    heading: isDe ? "Passwort zurücksetzen" : "Reset your password",
    greeting,
    intro: isDe
      ? "du hast angefordert, dein ScanReceipts-Passwort zurückzusetzen. Über den Button legst du ein neues fest."
      : "you asked to reset your ScanReceipts password. Use the button below to choose a new one.",
    cta: isDe ? "NEUES PASSWORT WÄHLEN" : "CHOOSE NEW PASSWORD",
    link,
    fallback: isDe
      ? "Falls der Button nicht funktioniert, kopiere diesen Link in deinen Browser:"
      : "If the button doesn't work, paste this link into your browser:",
    footer: [
      isDe
        ? "Der Link ist 1 Stunde gültig und lässt sich nur einmal verwenden."
        : "This link is valid for 1 hour and can only be used once.",
      isDe
        ? "Du hast das nicht angefordert? Dann ignoriere diese E-Mail — dein Passwort bleibt unverändert."
        : "Didn't request this? Ignore this email — your password stays as it is.",
      isDe
        ? "Nach dem Zurücksetzen wirst du auf allen Geräten abgemeldet."
        : "Resetting signs you out on every device.",
    ],
  });
}

interface ShellInput {
  lang: "de" | "en";
  subject: string;
  heading: string;
  greeting: string;
  intro: string;
  cta: string;
  link: string;
  fallback: string;
  footer: string[];
}

/**
 * One markup shell for every transactional mail. Table layout and inline styles
 * throughout: email clients are not browsers.
 */
function renderShell(input: ShellInput): RenderedMail {
  const { lang, subject, heading, greeting, intro, cta, link, fallback, footer } = input;

  const text = [greeting, "", intro, "", link, "", ...footer, "", "— ScanReceipts"].join("\n");

  const footerHtml = footer
    .map(
      (line, index) =>
        `<p style="margin:${index === 0 ? "24px" : "6px"} 0 0 0;">${line}</p>`
    )
    .join("");

  const html = `<!doctype html>
<html lang="${lang}">
  <body style="margin:0;padding:0;background-color:#F6F9FF;">
    <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color:#F6F9FF;padding:32px 16px;">
      <tr>
        <td align="center">
          <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="max-width:520px;background-color:#ffffff;border:1px solid #E2E8F0;">
            <tr>
              <td style="padding:32px 32px 0 32px;">
                <div style="font-family:'JetBrains Mono',Consolas,monospace;font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:#475569;font-weight:700;">
                  SCANRECEIPTS
                </div>
                <h1 style="margin:16px 0 0 0;font-family:'Hanken Grotesk',Helvetica,Arial,sans-serif;font-size:26px;line-height:1.2;letter-spacing:-.02em;color:#000000;font-weight:700;">
                  ${heading}
                </h1>
              </td>
            </tr>
            <tr>
              <td style="padding:20px 32px 0 32px;font-family:Helvetica,Arial,sans-serif;font-size:15px;line-height:1.6;color:#334155;">
                <p style="margin:0 0 8px 0;">${greeting}</p>
                <p style="margin:0;">${intro}</p>
              </td>
            </tr>
            <tr>
              <td style="padding:28px 32px 0 32px;">
                <a href="${link}" style="display:block;background-color:#000000;color:#ffffff;text-decoration:none;text-align:center;padding:15px 24px;font-family:'JetBrains Mono',Consolas,monospace;font-size:12px;letter-spacing:.1em;text-transform:uppercase;font-weight:600;">
                  ${cta}
                </a>
              </td>
            </tr>
            <tr>
              <td style="padding:24px 32px 0 32px;font-family:Helvetica,Arial,sans-serif;font-size:12px;line-height:1.6;color:#64748B;">
                <p style="margin:0 0 6px 0;">${fallback}</p>
                <p style="margin:0;word-break:break-all;"><a href="${link}" style="color:#475569;">${link}</a></p>
              </td>
            </tr>
            <tr>
              <td style="padding:24px 32px 32px 32px;border-top:1px solid #E2E8F0;font-family:Helvetica,Arial,sans-serif;font-size:12px;line-height:1.6;color:#94A3B8;">
                ${footerHtml}
              </td>
            </tr>
          </table>
        </td>
      </tr>
    </table>
  </body>
</html>`;

  return { subject, html, text };
}
