import { formatPrice, formatDate } from "./format";
import { computeTaxBreakdown } from "@einfach-produktiv/invoicing";
import type { CompanySettings } from "./payload";

// Pure string-building functions, no server-only or client-only imports —
// used both server-side for the actual email send (app/lib/orderEmail.ts,
// app/api/checkout/route.ts) and client-side for the Live Preview page
// (app/email-preview/[type]/page.tsx's client component), so a Live
// Preview edit and the real sent email are guaranteed to render
// identically — same function, same input shape, just different data
// (real order vs. SAMPLE_ORDER below).
//
// Inline-styled HTML, not Tailwind classes or a <style> block — most email
// clients strip external/embedded CSS and only reliably honor inline
// `style` attributes. Structure (this file) is fixed; only the wording
// (heading/bodyText/footerText, edited in Payload's email-templates
// collection) is admin-editable — see that collection's own comment for why.
//
// Visual language deliberately echoes /bestellbestaetigung (the on-screen
// confirmation page, app/bestellbestaetigung/components/BestellbestaetigungContent.tsx)
// rather than being a generic transactional-email template: same brand
// color/warm cream background, the same circular success-icon treatment,
// the same thin brand-colored divider under the headline, a serif display
// heading. Not literally shared code (that component is React+Tailwind,
// this is plain inline-styled HTML for email-client compatibility — no
// external fonts/CSS, no flexbox reliance), just matched by eye so a
// customer doesn't get a starkly different "brand voice" between the page
// they just saw and the email that follows it.

export type EmailTemplateContent = {
  subject: string;
  heading: string;
  bodyText: string;
  footerText: string | null;
};

// Same hex values as app/globals.css's --color-* tokens — kept as literal
// constants here rather than imported, since this file has no build-time
// access to CSS custom properties (email clients wouldn't resolve `var()`
// either, even if it did).
const BRAND = "#f6a701";
const BG_BASE = "#f8f5f1";
const BG_MUTED = "#f3efe9";
const TEXT_PRIMARY = "#1a1a18";
const TEXT_MUTED = "#6b6b69";
const BORDER = "#e5e0d8";
const SUCCESS = "#2f8f4e";
// Georgia, not a web font — most email clients strip @font-face/external
// font requests, so this is the closest reliably-available serif to
// Playfair Display/Lora's editorial feel rather than an attempt to load
// the real thing.
const FONT_SERIF = "Georgia,'Times New Roman',serif";
const FONT_SANS = "-apple-system,Helvetica,Arial,sans-serif";

function paragraphs(text: string, align: "center" | "left" = "left"): string {
  return text
    .split(/\n{2,}/)
    .map(
      (p) =>
        `<p style="margin:0 0 12px;line-height:1.6;font-size:15px;color:${TEXT_MUTED};text-align:${align};">${escapeHtml(p).replace(/\n/g, "<br/>")}</p>`,
    )
    .join("");
}

function escapeHtml(s: string): string {
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}

// Vorkasse (Überweisung/manual) instruction — the invoice PDF already
// shows this same information (see @einfach-produktiv/invoicing's own
// unpaidNoticeText), but a customer often only glances at the email body
// itself, not the attached PDF, so it's repeated here in plain text too.
// Own full-width block, margin-top matching the other section gaps in
// this template (16px) — not squeezed into the narrow Gesamtsumme table
// like an initial draft of the invoice version was before that got
// widened per feedback.
function vorkasseNotice(orderNumber: string, seller: CompanySettings | null, hasOnlinePaymentOption: boolean): string {
  const bankLine = seller && (seller.iban || seller.bic)
    ? [seller.bankName, seller.iban && `IBAN ${seller.iban}`, seller.bic && `BIC ${seller.bic}`].filter(Boolean).join(" · ")
    : null;
  return `
    <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin-top:20px;background:${BG_MUTED};border-radius:8px;padding:16px 20px;">
      <tr>
        <td style="font-size:13px;line-height:1.6;color:${TEXT_MUTED};text-align:center;">
          <p style="margin:0 0 8px;">Bitte überweise den Rechnungsbetrag unter Angabe der Bestellnummer ${escapeHtml(orderNumber)} auf ${bankLine ? "folgende Bankverbindung:" : "die dir genannte Bankverbindung."}</p>
          ${bankLine ? `<p style="margin:0 0 12px;font-weight:700;color:${TEXT_PRIMARY};">${escapeHtml(bankLine)}</p>` : ""}
          <p style="margin:0;">Deine Bestellung wird nach Zahlungseingang bearbeitet (in der Regel innerhalb von 1–2 Werktagen).</p>
          ${hasOnlinePaymentOption ? `<p style="margin:8px 0 0;">Zahlungsart geändert? Solange die Überweisung noch nicht bei uns eingegangen ist, kannst du in deinem Konto jederzeit auf Kreditkarte/PayPal umsteigen.</p>` : ""}
        </td>
      </tr>
    </table>
  `;
}

// Live-Preview-only fallback (no real order/company-settings fetch there,
// see /email-preview/[type]) — the actual send always passes the real
// seller (company-settings) through buildLegalFooterLines() below. Email
// deliberately doesn't match the real admin@mk360.de send address, so this
// never reads as a hardcoded real value in the preview — it's a visibly
// fake placeholder, same spirit as "Musterstraße 12".
export const DEFAULT_LEGAL_FOOTER_LINES: string[] = [
  "einfach produktiv",
  "Musterstraße 12",
  "12345 Musterstadt",
  "E-Mail: kontakt@musterfirma.de",
];

// Every business email needs an Anbieterkennzeichnung (§5 DDG-equivalent
// minimum for business correspondence: full name, postal address, contact,
// plus VAT ID once assigned) — not just a friendly "brand · email" line.
// Built from the same company-settings fields the invoice PDFs already
// render (app/lib/invoicePdf.tsx), so there is exactly one source of truth
// for this business's legal identity.
//
// registerCourt/registerNumber/managingDirector are conditionally required
// on the Payload side (CompanySettings.ts, gated by legalForm) — only
// appended here when actually present, so a sole proprietorship's footer
// stays exactly as short as before this field set existed. Keep this in
// sync with the Payload backend's own copy in src/lib/sellerInfo.ts.
// `shareCapital` deliberately does NOT appear here even though it's a
// company-settings field — see CompanySettings.ts's own comment: it's a
// voluntary disclosure, not something safe to auto-inject into every
// outgoing email regardless of whether the business actually wants that
// disclosure made.
export function buildLegalFooterLines(seller: CompanySettings | null): string[] {
  if (!seller) return DEFAULT_LEGAL_FOOTER_LINES;
  const lines = [
    seller.sellerName,
    seller.sellerStreet,
    `${seller.sellerZip} ${seller.sellerCity}${seller.sellerCountry && seller.sellerCountry !== "Deutschland" ? `, ${seller.sellerCountry}` : ""}`,
    `E-Mail: ${seller.sellerEmail}`,
  ];
  if (seller.vatId) lines.push(`USt-IdNr.: ${seller.vatId}`);
  if (seller.registerCourt && seller.registerNumber) lines.push(`${seller.registerCourt} · ${seller.registerNumber}`);
  if (seller.managingDirector) lines.push(`Geschäftsführung: ${seller.managingDirector}`);
  return lines;
}

// `icon`: a single glyph rendered inside the brand-tinted circle up top —
// "✓" for order-confirmation, "✉" for password-reset. Same circular
// treatment as the confirmation page's own success icon and its delivery-
// status panel icon. `footerLines`: the legal Anbieterkennzeichnung from
// buildLegalFooterLines() above — required on every email, not optional.
function emailShell(icon: string, headingHtml: string, bodyHtml: string, footerText: string | null, footerLines: string[]): string {
  return `<body style="margin:0;padding:32px 16px;background:${BG_BASE};font-family:${FONT_SANS};">
  <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="max-width:560px;margin:0 auto;">
    <tr>
      <td style="padding-bottom:20px;text-align:center;">
        <span style="font-family:${FONT_SERIF};font-weight:700;font-size:15px;color:${TEXT_PRIMARY};letter-spacing:0.02em;">einfach produktiv.</span>
      </td>
    </tr>
    <tr>
      <td style="background:#ffffff;border:1px solid ${BORDER};border-radius:12px;padding:40px 32px;">
        <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
          <tr>
            <td style="text-align:center;padding-bottom:20px;">
              <table role="presentation" cellpadding="0" cellspacing="0" style="margin:0 auto;">
                <tr>
                  <td width="56" height="56" style="width:56px;height:56px;background:${BRAND}1a;border-radius:50%;text-align:center;vertical-align:middle;font-size:24px;color:${BRAND};">
                    ${icon}
                  </td>
                </tr>
              </table>
            </td>
          </tr>
          <tr>
            <td style="text-align:center;padding-bottom:8px;">
              <span style="font-family:${FONT_SERIF};font-weight:700;font-size:26px;color:${TEXT_PRIMARY};">${headingHtml}</span>
            </td>
          </tr>
          <tr>
            <td style="text-align:center;padding-bottom:20px;">
              <div style="width:32px;height:2px;background:${BRAND};margin:0 auto;"></div>
            </td>
          </tr>
          <tr>
            <td>${bodyHtml}</td>
          </tr>
        </table>
      </td>
    </tr>
    <tr>
      <td style="padding-top:24px;text-align:center;">
        ${footerText ? `<p style="margin:0 0 8px;font-size:13px;color:${TEXT_MUTED};">${escapeHtml(footerText)}</p>` : ""}
        ${footerLines.map((line) => `<p style="margin:0;font-size:11px;line-height:1.6;color:${TEXT_MUTED};">${escapeHtml(line)}</p>`).join("")}
      </td>
    </tr>
  </table>
</body>`;
}

export type OrderConfirmationItem = {
  productName: string;
  quantity: number;
  unitPrice: number;
  imageUrl?: string | null;
  bundleContents?: string | null;
  variantName?: string | null;
  taxRatePercent: number;
  sku?: string | null;
};
export type OrderConfirmationData = {
  orderNumber: string;
  createdAt: string;
  items: OrderConfirmationItem[];
  subtotal: number;
  shippingCost: number;
  discountAmount: number;
  discountCode: string | null;
  total: number;
  // Explicit boolean set by each caller (checkout route's manual branch:
  // true; the Stripe webhook path: always false, since only a *paid*
  // Stripe order ever reaches this send) — not derived from
  // paymentMethodTitle here, since that string ("Online-Zahlung",
  // "Kreditkarte", "Überweisung (Vorkasse)", ...) is exactly the kind of
  // fragile thing a payment-methods rename already broke once this
  // session (see @einfach-produktiv/invoicing's isPaidImmediately()).
  isManualPayment: boolean;
  // Only meaningful when isManualPayment is true — whether at least one
  // Stripe-backed payment method is currently active, so the Vorkasse
  // notice can mention the option to switch instead of promising it
  // unconditionally. Set by the checkout route from the same
  // getPaymentMethods() call it already makes.
  hasOnlinePaymentOption?: boolean;
};

export const SAMPLE_ORDER: OrderConfirmationData = {
  orderNumber: "#EP-0001-A7K2",
  createdAt: new Date().toISOString(),
  items: [
    {
      productName: "ToDo-Karten – Set",
      quantity: 1,
      unitPrice: 12.9,
      imageUrl: "https://payload.mk360.de/api/media/file/product-todo-karten.png",
      bundleContents: null,
      taxRatePercent: 19,
    },
    { productName: "Wochenplaner – Überblick", quantity: 2, unitPrice: 14.9, imageUrl: null, taxRatePercent: 19 },
  ],
  subtotal: 42.7,
  shippingCost: 0,
  discountAmount: 5,
  discountCode: "WILLKOMMEN10",
  total: 37.7,
  isManualPayment: false,
};

// Second preview fixture — demonstrates the Vorkasse/Überweisung branch
// (vorkasseNotice(), incl. the "switch to Kreditkarte/PayPal" mention)
// that SAMPLE_ORDER's own isManualPayment: false never shows. Used by
// LiveEmailPreviewClient.tsx's toggle, not by any real send — a real
// order-confirmation email always computes both flags live per order.
export const SAMPLE_ORDER_MANUAL: OrderConfirmationData = {
  ...SAMPLE_ORDER,
  isManualPayment: true,
  hasOnlinePaymentOption: true,
};

export function renderOrderConfirmationHtml(template: EmailTemplateContent, order: OrderConfirmationData, seller: CompanySettings | null): string {
  const rows = order.items
    .map(
      (item) => `<tr>
        <td width="52" style="padding:10px 0;border-bottom:1px solid ${BORDER};">
          ${
            item.imageUrl
              ? `<img src="${item.imageUrl}" width="44" height="44" alt="" style="display:block;width:44px;height:44px;border-radius:6px;object-fit:cover;border:1px solid ${BORDER};" />`
              : `<div style="width:44px;height:44px;border-radius:6px;background:${BG_MUTED};"></div>`
          }
        </td>
        <td style="padding:10px 0 10px 12px;border-bottom:1px solid ${BORDER};font-size:14px;color:${TEXT_PRIMARY};">${escapeHtml(item.productName)}${item.variantName ? ` (${escapeHtml(item.variantName)})` : ""} <span style="color:${TEXT_MUTED};">× ${item.quantity}</span>${item.bundleContents ? `<br/><span style="font-size:12px;color:${TEXT_MUTED};">${escapeHtml(item.bundleContents)}</span>` : ""}${item.sku ? `<br/><span style="font-size:12px;color:${TEXT_MUTED};">Art.-Nr. ${escapeHtml(item.sku)}</span>` : ""}</td>
        <td style="padding:10px 0;border-bottom:1px solid ${BORDER};text-align:right;white-space:nowrap;font-size:14px;color:${TEXT_PRIMARY};">${formatPrice(item.quantity * item.unitPrice)}</td>
      </tr>`,
    )
    .join("");

  const summaryRow = (label: string, value: string, color = TEXT_PRIMARY) =>
    `<tr><td style="padding:4px 0;font-size:14px;color:${color};">${label}</td><td style="padding:4px 0;text-align:right;font-size:14px;color:${color};">${value}</td></tr>`;

  const vatRow = (label: string, value: string) =>
    `<tr><td style="padding-top:4px;font-size:12px;color:${TEXT_MUTED};">${label}</td><td style="padding-top:4px;text-align:right;font-size:12px;color:${TEXT_MUTED};">${value}</td></tr>`;

  // Actual VAT amount included in the total, broken down per rate when the
  // order spans more than one — mirrors /bestellbestaetigung's own
  // VatBreakdown component (not shared code, this file is plain
  // inline-styled HTML for email-client compatibility, see the top-of-file
  // comment) and the same lib/taxBreakdown.ts math the invoice PDF uses.
  const taxBreakdown = computeTaxBreakdown(
    order.items.map((item) => ({ quantity: item.quantity, unitPrice: item.unitPrice, taxRatePercent: item.taxRatePercent })),
    order.subtotal,
    order.discountAmount,
    order.shippingCost,
  );
  const taxRows =
    taxBreakdown.length <= 1
      ? taxBreakdown[0]
        ? vatRow(`enthält ${taxBreakdown[0].rate}% MwSt.`, formatPrice(taxBreakdown[0].tax))
        : ""
      : taxBreakdown.map((g) => vatRow(`davon ${g.rate}% MwSt.`, formatPrice(g.tax))).join("");

  const body = `
    ${paragraphs(template.bodyText, "center")}
    <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin-top:16px;background:${BG_MUTED};border-radius:8px;padding:20px;">
      <tr><td colspan="3" style="padding-bottom:10px;font-size:12px;color:${TEXT_MUTED};">Bestellnummer <strong style="color:${TEXT_PRIMARY};">${escapeHtml(order.orderNumber)}</strong> · ${formatDate(order.createdAt)}</td></tr>
      ${rows}
    </table>
    <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin-top:16px;">
      ${summaryRow("Zwischensumme", formatPrice(order.subtotal))}
      ${order.discountAmount > 0 ? summaryRow(`Rabattcode${order.discountCode ? ` (${escapeHtml(order.discountCode)})` : ""}`, `-${formatPrice(order.discountAmount)}`, SUCCESS) : ""}
      ${summaryRow("Versand", order.shippingCost === 0 ? "Kostenlos" : formatPrice(order.shippingCost))}
    </table>
    <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin-top:12px;padding-top:12px;border-top:1px solid ${BORDER};">
      <tr>
        <td style="font-family:${FONT_SERIF};font-weight:700;font-size:17px;color:${TEXT_PRIMARY};">Gesamtsumme</td>
        <td style="text-align:right;font-weight:700;font-size:17px;color:${TEXT_PRIMARY};">${formatPrice(order.total)}</td>
      </tr>
      ${taxRows}
    </table>
    ${order.isManualPayment ? vorkasseNotice(order.orderNumber, seller, Boolean(order.hasOnlinePaymentOption)) : ""}
  `;

  return emailShell("✓", escapeHtml(template.heading), body, template.footerText, buildLegalFooterLines(seller));
}

// Icon shown per status — matches the Payload-side send exactly (see
// STATUS_EMAIL in the backend repo's src/collections/Orders.ts), kept here
// only for the Live Preview approximation (the real send happens from
// Payload itself, not this repo — see that file's own comment on why the
// two aren't pixel-identical, same established gap as password-reset).
export const ORDER_STATUS_EMAIL_ICON: Record<string, string> = {
  "order-shipped": "→",
  "order-cancelled": "✕",
  "order-return-requested": "↩",
  "order-returned": "✓",
  "order-tracking-added": "📦",
  "order-tracking-corrected": "📦",
  "order-delivered": "🎉",
  "payment-method-switched": "💳",
  "back-in-stock": "🔔",
};

export function renderOrderStatusHtml(
  template: EmailTemplateContent,
  icon: string,
  orderNumber: string,
  orderUrl: string,
  seller: CompanySettings | null,
): string {
  const body = `
    ${paragraphs(template.bodyText, "center")}
    <p style="text-align:center;font-size:13px;color:${TEXT_MUTED};margin:0 0 4px;">Bestellnummer ${escapeHtml(orderNumber)}</p>
    <table role="presentation" cellpadding="0" cellspacing="0" style="margin:20px auto 8px;">
      <tr>
        <td style="background:${BRAND};border-radius:6px;">
          <a href="${orderUrl}" style="display:inline-block;padding:13px 28px;font-weight:700;font-size:15px;color:${TEXT_PRIMARY};text-decoration:none;">Bestellung ansehen</a>
        </td>
      </tr>
    </table>
  `;

  return emailShell(icon, escapeHtml(template.heading), body, template.footerText, buildLegalFooterLines(seller));
}

// Separate from renderOrderStatusHtml — a back-in-stock mail has no order
// at all (it fires from a "notify me" signup, not a purchase), so no
// "Bestellnummer" line, and the CTA points at the product page, not
// /konto/bestellungen. Mirrors lib/jobs/sendBackInStockEmails.ts on the
// Payload backend, which is where the real send actually happens (see
// this file's own top-of-file comment on why the two aren't literally
// shared code).
export function renderBackInStockHtml(
  template: EmailTemplateContent,
  productLabel: string,
  productUrl: string,
  seller: CompanySettings | null,
  productImageUrl: string | null = null,
): string {
  const body = `
    ${paragraphs(template.bodyText, "center")}
    ${productImageUrl ? `<p style="text-align:center;margin:0 0 12px;"><img src="${productImageUrl}" width="64" height="64" alt="" style="display:inline-block;width:64px;height:64px;border-radius:8px;object-fit:cover;border:1px solid ${BORDER};" /></p>` : ""}
    <p style="text-align:center;font-size:13px;color:${TEXT_MUTED};margin:0 0 12px;">${escapeHtml(productLabel)}</p>
    <table role="presentation" cellpadding="0" cellspacing="0" style="margin:20px auto 8px;">
      <tr>
        <td style="background:${BRAND};border-radius:6px;">
          <a href="${productUrl}" style="display:inline-block;padding:13px 28px;font-weight:700;font-size:15px;color:${TEXT_PRIMARY};text-decoration:none;">Zum Produkt</a>
        </td>
      </tr>
    </table>
  `;

  return emailShell("🔔", escapeHtml(template.heading), body, template.footerText, buildLegalFooterLines(seller));
}

export function renderPasswordResetHtml(template: EmailTemplateContent, resetUrl: string, seller: CompanySettings | null): string {
  const body = `
    ${paragraphs(template.bodyText, "center")}
    <table role="presentation" cellpadding="0" cellspacing="0" style="margin:20px auto 8px;">
      <tr>
        <td style="background:${BRAND};border-radius:6px;">
          <a href="${resetUrl}" style="display:inline-block;padding:13px 28px;font-weight:700;font-size:15px;color:${TEXT_PRIMARY};text-decoration:none;">Neues Passwort vergeben</a>
        </td>
      </tr>
    </table>
    <p style="text-align:center;font-size:12px;color:${TEXT_MUTED};word-break:break-all;">${resetUrl}</p>
    <p style="text-align:center;font-size:12px;color:${TEXT_MUTED};">Der Link ist 1 Stunde gültig.</p>
  `;

  return emailShell("✉", escapeHtml(template.heading), body, template.footerText, buildLegalFooterLines(seller));
}

// Not a Payload-editable template like the others above (see alertAdmin.ts's
// own comment on why this one send path exists outside the email-templates
// collection) — wording is fixed in code, but it still goes through the
// same emailShell()/buildLegalFooterLines() so the resend-verification email
// carries the same branding and legally required footer as every other
// email this app sends.
export function renderVerificationEmailHtml(firstName: string, verifyUrl: string, seller: CompanySettings | null): string {
  const body = `
    ${paragraphs(`Hallo ${firstName},\n\nbitte bestätige deine E-Mail-Adresse für dein Konto bei einfach produktiv.`, "center")}
    <table role="presentation" cellpadding="0" cellspacing="0" style="margin:20px auto 8px;">
      <tr>
        <td style="background:${BRAND};border-radius:6px;">
          <a href="${verifyUrl}" style="display:inline-block;padding:13px 28px;font-weight:700;font-size:15px;color:${TEXT_PRIMARY};text-decoration:none;">E-Mail-Adresse bestätigen</a>
        </td>
      </tr>
    </table>
    <p style="text-align:center;font-size:12px;color:${TEXT_MUTED};word-break:break-all;">${verifyUrl}</p>
    <p style="text-align:center;font-size:12px;color:${TEXT_MUTED};">Der Link ist 24 Stunden gültig.</p>
  `;

  return emailShell("✉", "Bitte bestätige deine E-Mail-Adresse", body, null, buildLegalFooterLines(seller));
}
