import nodemailer from 'nodemailer';
import { db } from '@server/db/drizzle';
import { sql } from 'drizzle-orm';

import { childLogger } from '@server/logger';
import { redactEmail } from '@server/logger/redact';
const log = childLogger('svc.email');

interface SmtpConfig {
  host: string;
  port: number;
  user: string;
  pass: string;
  from: string;
}

function defaultNoReplyAddress(): string {
  const appUrl = process.env.NEXT_PUBLIC_APP_URL;
  if (appUrl) {
    try {
      const host = new URL(appUrl).hostname;
      if (host && host !== 'localhost') return `noreply@${host}`;
    } catch { /* fall through */ }
  }
  return 'noreply@localhost';
}

function buildTransport(cfg: SmtpConfig) {
  return nodemailer.createTransport({
    host: cfg.host,
    port: cfg.port,
    secure: cfg.port === 465,
    auth: { user: cfg.user, pass: cfg.pass },
  });
}

function getEnvSmtpConfig(): SmtpConfig | null {
  const host = process.env.SMTP_HOST;
  const port = parseInt(process.env.SMTP_PORT ?? '587', 10);
  const user = process.env.SMTP_USER;
  const pass = process.env.SMTP_PASS;
  if (!host || !user || !pass) return null;
  const from = process.env.SMTP_FROM || user || defaultNoReplyAddress();
  return { host, port, user, pass, from };
}

async function getBranchSmtpConfig(branchId: string, restaurantId?: string): Promise<SmtpConfig | null> {
  try {
    /* raw: SELECT smtp_host, smtp_port, smtp_user, smtp_pass, smtp_from FROM branches WHERE id = $1 [AND restaurant_id = $2] */
    const { rows } = restaurantId
      ? await db.execute(sql`SELECT smtp_host, smtp_port, smtp_user, smtp_pass, smtp_from FROM branches WHERE id = ${branchId} AND restaurant_id = ${restaurantId}`)
      : await db.execute(sql`SELECT smtp_host, smtp_port, smtp_user, smtp_pass, smtp_from FROM branches WHERE id = ${branchId}`);
    const row = rows[0] as Record<string, unknown> | undefined;
    if (!row) return null;
    const host = row.smtp_host as string | null;
    const user = row.smtp_user as string | null;
    const pass = row.smtp_pass as string | null;
    if (!host || !user || !pass) return null;
    const port = (row.smtp_port as number | null) ?? 587;
    const from = (row.smtp_from as string | null) || user || defaultNoReplyAddress();
    return { host, port, user, pass, from };
  } catch {
    return null;
  }
}

async function resolveSmtpConfig(branchId?: string, restaurantId?: string): Promise<{ transport: ReturnType<typeof nodemailer.createTransport>; from: string } | null> {
  let cfg: SmtpConfig | null = null;
  if (branchId) {
    cfg = await getBranchSmtpConfig(branchId, restaurantId);
  }
  if (!cfg) {
    cfg = getEnvSmtpConfig();
  }
  if (!cfg) return null;
  return { transport: buildTransport(cfg), from: cfg.from };
}

export interface SendPasswordResetEmailOptions {
  to: string;
  userName: string;
  resetLink: string;
}

function escapeHtml(text: string): string {
  return text
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
}

function buildPasswordResetHtml(userName: string, resetLink: string): string {
  if (!/^https?:\/\//i.test(resetLink)) throw new Error('Invalid reset link URL');
  const safeLink = resetLink.replace(/"/g, '%22');
  return `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Reset your RestroAgent password</title>
</head>
<body style="margin:0;padding:0;background-color:#f4f4f5;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
  <table width="100%" cellpadding="0" cellspacing="0" style="background-color:#f4f4f5;padding:32px 16px;">
    <tr>
      <td align="center">
        <table width="560" cellpadding="0" cellspacing="0" style="max-width:560px;width:100%;">
          <tr>
            <td align="center" style="padding-bottom:24px;">
              <span style="font-size:20px;font-weight:700;color:#111827;letter-spacing:-0.5px;">
                &#127374; RestroAgent
              </span>
            </td>
          </tr>
          <tr>
            <td style="background-color:#ffffff;border-radius:16px;padding:40px 36px;box-shadow:0 1px 3px rgba(0,0,0,0.08);">
              <h1 style="margin:0 0 8px;font-size:22px;font-weight:700;color:#111827;">
                Reset your password
              </h1>
              <p style="margin:0 0 24px;font-size:15px;color:#6b7280;line-height:1.6;">
                Hi ${escapeHtml(userName)},<br/>
                We received a request to reset the password for your RestroAgent account.
                Click the button below to choose a new password. This link expires in
                <strong>30 minutes</strong>.
              </p>
              <table width="100%" cellpadding="0" cellspacing="0">
                <tr>
                  <td align="center" style="padding-bottom:28px;">
                    <a href="${safeLink}"
                       style="display:inline-block;padding:13px 32px;background-color:#f97316;color:#ffffff;font-size:15px;font-weight:600;text-decoration:none;border-radius:10px;">
                      Reset Password
                    </a>
                  </td>
                </tr>
              </table>
              <p style="margin:0 0 8px;font-size:13px;color:#9ca3af;line-height:1.5;">
                If the button above doesn't work, copy and paste this link into your browser:
              </p>
              <p style="margin:0 0 28px;font-size:13px;word-break:break-all;">
                <a href="${safeLink}" style="color:#f97316;text-decoration:none;">${escapeHtml(resetLink)}</a>
              </p>
              <div style="background-color:#fef9f0;border:1px solid #fed7aa;border-radius:8px;padding:14px 16px;">
                <p style="margin:0;font-size:13px;color:#92400e;line-height:1.5;">
                  <strong>Didn't request this?</strong> If you didn't request a password reset,
                  you can safely ignore this email. Your password will not be changed.
                </p>
              </div>
            </td>
          </tr>
          <tr>
            <td align="center" style="padding-top:20px;">
              <p style="margin:0;font-size:12px;color:#9ca3af;line-height:1.6;">
                &copy; ${new Date().getFullYear()} RestroAgent &mdash; AI-powered restaurant management<br/>
                You received this email because a password reset was requested for your account.
              </p>
            </td>
          </tr>
        </table>
      </td>
    </tr>
  </table>
</body>
</html>`;
}

export interface SendOrderConfirmationOptions {
  to: string;
  customerName: string;
  orderNumber: number | string;
  items: { name: string; quantity: number; price?: number }[];
  total: number;
  deliveryType: string;
  restaurantName: string;
}

function buildOrderConfirmationHtml(opts: SendOrderConfirmationOptions): string {
  const { customerName, orderNumber, items, total, deliveryType, restaurantName } = opts;
  const itemRows = items.map(i =>
    `<tr><td style="padding:6px 0;border-bottom:1px solid #f3f4f6;font-size:14px;color:#374151;">${escapeHtml(i.name)}</td><td style="padding:6px 0;border-bottom:1px solid #f3f4f6;font-size:14px;color:#374151;text-align:center;">${escapeHtml(String(i.quantity))}</td><td style="padding:6px 0;border-bottom:1px solid #f3f4f6;font-size:14px;color:#374151;text-align:right;">${i.price != null ? '$' + escapeHtml((i.price * i.quantity).toFixed(2)) : ''}</td></tr>`
  ).join('');
  const dtLabel = deliveryType === 'dine-in' ? 'Dine-In' : deliveryType === 'takeaway' ? 'Takeaway' : 'Delivery';
  return `<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><title>Order Confirmation</title></head>
<body style="margin:0;padding:0;background-color:#f4f4f5;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
  <table width="100%" cellpadding="0" cellspacing="0" style="background-color:#f4f4f5;padding:32px 16px;">
    <tr><td align="center">
      <table width="560" cellpadding="0" cellspacing="0" style="max-width:560px;width:100%;">
        <tr><td align="center" style="padding-bottom:24px;"><span style="font-size:20px;font-weight:700;color:#111827;">&#127374; ${escapeHtml(restaurantName)}</span></td></tr>
        <tr><td style="background-color:#ffffff;border-radius:16px;padding:40px 36px;box-shadow:0 1px 3px rgba(0,0,0,0.08);">
          <div style="background:#f0fdf4;border:1px solid #bbf7d0;border-radius:10px;padding:14px 18px;margin-bottom:24px;text-align:center;">
            <span style="font-size:28px;">&#9989;</span>
            <h2 style="margin:8px 0 4px;font-size:18px;font-weight:700;color:#15803d;">Order Confirmed!</h2>
            <p style="margin:0;font-size:14px;color:#166534;">Order <strong>#${escapeHtml(String(orderNumber))}</strong> &bull; ${escapeHtml(dtLabel)}</p>
          </div>
          <p style="margin:0 0 20px;font-size:15px;color:#374151;">Hi ${escapeHtml(customerName)}, thank you for your order! Here's a summary:</p>
          <table width="100%" cellpadding="0" cellspacing="0" style="margin-bottom:16px;">
            <tr><th style="text-align:left;font-size:12px;color:#9ca3af;padding-bottom:8px;border-bottom:2px solid #e5e7eb;">ITEM</th><th style="text-align:center;font-size:12px;color:#9ca3af;padding-bottom:8px;border-bottom:2px solid #e5e7eb;">QTY</th><th style="text-align:right;font-size:12px;color:#9ca3af;padding-bottom:8px;border-bottom:2px solid #e5e7eb;">PRICE</th></tr>
            ${itemRows}
          </table>
          <p style="text-align:right;font-size:16px;font-weight:700;color:#111827;margin:12px 0 24px;">Total: $${escapeHtml(total.toFixed(2))}</p>
          <p style="margin:0;font-size:13px;color:#6b7280;">Our team has received your order and will prepare it shortly. You'll be notified when it's ready.</p>
        </td></tr>
        <tr><td align="center" style="padding-top:20px;"><p style="margin:0;font-size:12px;color:#9ca3af;">&copy; ${new Date().getFullYear()} ${escapeHtml(restaurantName)} &mdash; Powered by RestroAgent</p></td></tr>
      </table>
    </td></tr>
  </table>
</body></html>`;
}

export async function sendOrderConfirmationEmail(opts: SendOrderConfirmationOptions, branchId?: string, restaurantId?: string): Promise<void> {
  const smtp = await resolveSmtpConfig(branchId, restaurantId);
  if (!smtp) {
    log.warn('SMTP not configured — skipping order confirmation email');
    return;
  }
  await smtp.transport.sendMail({
    from: smtp.from,
    to: opts.to,
    subject: `Order Confirmed! #${opts.orderNumber} — ${opts.restaurantName}`,
    html: buildOrderConfirmationHtml(opts),
  });
  log.info({ to: redactEmail(opts.to), orderNumber: opts.orderNumber }, 'order confirmation email sent');
}

export interface SendBookingConfirmationOptions {
  to: string;
  guestName: string;
  bookingRef: string;
  date: string;
  time: string;
  partySize: number | string;
  restaurantName: string;
  occasion?: string;
}

function buildBookingConfirmationHtml(opts: SendBookingConfirmationOptions): string {
  const { guestName, bookingRef, date, time, partySize, restaurantName, occasion } = opts;
  return `<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><title>Booking Confirmation</title></head>
<body style="margin:0;padding:0;background-color:#f4f4f5;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
  <table width="100%" cellpadding="0" cellspacing="0" style="background-color:#f4f4f5;padding:32px 16px;">
    <tr><td align="center">
      <table width="560" cellpadding="0" cellspacing="0" style="max-width:560px;width:100%;">
        <tr><td align="center" style="padding-bottom:24px;"><span style="font-size:20px;font-weight:700;color:#111827;">&#127374; ${escapeHtml(restaurantName)}</span></td></tr>
        <tr><td style="background-color:#ffffff;border-radius:16px;padding:40px 36px;box-shadow:0 1px 3px rgba(0,0,0,0.08);">
          <div style="background:#eff6ff;border:1px solid #bfdbfe;border-radius:10px;padding:14px 18px;margin-bottom:24px;text-align:center;">
            <span style="font-size:28px;">&#128197;</span>
            <h2 style="margin:8px 0 4px;font-size:18px;font-weight:700;color:#1d4ed8;">Table Booking Confirmed!</h2>
            <p style="margin:0;font-size:13px;color:#1e40af;">Ref: <strong>${escapeHtml(bookingRef)}</strong></p>
          </div>
          <p style="margin:0 0 20px;font-size:15px;color:#374151;">Hi ${escapeHtml(guestName)}, your reservation has been confirmed. Here are your details:</p>
          <table width="100%" cellpadding="0" cellspacing="0" style="margin-bottom:24px;">
            <tr><td style="padding:10px 0;border-bottom:1px solid #f3f4f6;font-size:14px;color:#6b7280;width:40%;">&#128197; Date</td><td style="padding:10px 0;border-bottom:1px solid #f3f4f6;font-size:14px;color:#111827;font-weight:600;">${escapeHtml(date)}</td></tr>
            <tr><td style="padding:10px 0;border-bottom:1px solid #f3f4f6;font-size:14px;color:#6b7280;">&#128336; Time</td><td style="padding:10px 0;border-bottom:1px solid #f3f4f6;font-size:14px;color:#111827;font-weight:600;">${escapeHtml(time)}</td></tr>
            <tr><td style="padding:10px 0;border-bottom:1px solid #f3f4f6;font-size:14px;color:#6b7280;">&#128101; Guests</td><td style="padding:10px 0;border-bottom:1px solid #f3f4f6;font-size:14px;color:#111827;font-weight:600;">${escapeHtml(String(partySize))}</td></tr>
            ${occasion ? `<tr><td style="padding:10px 0;font-size:14px;color:#6b7280;">&#127881; Occasion</td><td style="padding:10px 0;font-size:14px;color:#111827;font-weight:600;">${escapeHtml(occasion)}</td></tr>` : ''}
          </table>
          <p style="margin:0;font-size:13px;color:#6b7280;">We look forward to seeing you! If you need to make any changes, please contact us directly.</p>
        </td></tr>
        <tr><td align="center" style="padding-top:20px;"><p style="margin:0;font-size:12px;color:#9ca3af;">&copy; ${new Date().getFullYear()} ${escapeHtml(restaurantName)} &mdash; Powered by RestroAgent</p></td></tr>
      </table>
    </td></tr>
  </table>
</body></html>`;
}

export async function sendBookingConfirmationEmail(opts: SendBookingConfirmationOptions, branchId?: string, restaurantId?: string): Promise<void> {
  const smtp = await resolveSmtpConfig(branchId, restaurantId);
  if (!smtp) {
    log.warn('SMTP not configured — skipping booking confirmation email');
    return;
  }
  await smtp.transport.sendMail({
    from: smtp.from,
    to: opts.to,
    subject: `Booking Confirmed! Ref: ${opts.bookingRef} — ${opts.restaurantName}`,
    html: buildBookingConfirmationHtml(opts),
  });
  log.info({ to: redactEmail(opts.to), bookingRef: opts.bookingRef }, 'booking confirmation email sent');
}

export async function sendInvoiceNotificationEmail(opts: {
  to: string;
  restaurantName: string;
  invoiceNumber: string;
  amount: string;
  currency: string;
  periodStart: string;
  periodEnd: string;
  hostedUrl?: string;
  pdfUrl?: string;
}, restaurantId?: string): Promise<void> {
  const smtp = await resolveSmtpConfig(undefined, restaurantId);
  if (!smtp) {
    log.warn('SMTP not configured — skipping billing contact invoice notification');
    return;
  }
  const { to, restaurantName, invoiceNumber, amount, currency, periodStart, periodEnd, hostedUrl, pdfUrl } = opts;
  const viewLink = hostedUrl ? `<p style="margin:16px 0 0"><a href="${escapeHtml(hostedUrl)}" style="color:#4f46e5;">View invoice online</a>${pdfUrl ? ` &middot; <a href="${escapeHtml(pdfUrl)}" style="color:#4f46e5;">Download PDF</a>` : ''}</p>` : '';
  const html = `<!DOCTYPE html><html><body style="margin:0;padding:32px;background:#f4f4f5;font-family:sans-serif;">
<table width="560" style="margin:auto;background:#fff;border-radius:12px;padding:32px;"><tr><td>
  <h2 style="margin:0 0 4px;font-size:18px;color:#111827;">${escapeHtml(restaurantName)}</h2>
  <p style="margin:0 0 24px;color:#6b7280;font-size:13px;">Invoice notification for your billing contact</p>
  <table width="100%" style="border-top:2px solid #e5e7eb;border-bottom:2px solid #e5e7eb;padding:16px 0;margin-bottom:16px;">
    <tr><td style="color:#6b7280;font-size:13px;">Invoice</td><td style="text-align:right;font-weight:600;font-size:13px;">${escapeHtml(invoiceNumber)}</td></tr>
    <tr><td style="color:#6b7280;font-size:13px;">Period</td><td style="text-align:right;font-size:13px;">${escapeHtml(periodStart)} – ${escapeHtml(periodEnd)}</td></tr>
    <tr><td style="color:#6b7280;font-size:13px;">Amount</td><td style="text-align:right;font-size:16px;font-weight:700;color:#111827;">${escapeHtml(currency.toUpperCase())} ${escapeHtml(amount)}</td></tr>
  </table>
  ${viewLink}
</td></tr></table>
</body></html>`;
  await smtp.transport.sendMail({
    from: smtp.from,
    to,
    subject: `Invoice ${invoiceNumber} — ${restaurantName}`,
    html,
  });
  log.info({ to: redactEmail(to), invoiceNumber }, 'billing contact invoice notification sent');
}

export async function sendPasswordResetEmail(
  opts: SendPasswordResetEmailOptions
): Promise<void> {
  const smtp = await resolveSmtpConfig();

  if (!smtp) {
    log.warn(
      '[Email] SMTP not configured (SMTP_HOST / SMTP_USER / SMTP_PASS missing) — skipping email delivery'
    );
    return;
  }

  const info = await smtp.transport.sendMail({
    from: smtp.from,
    to: opts.to,
    subject: 'Reset your RestroAgent password',
    html: buildPasswordResetHtml(opts.userName, opts.resetLink),
  });

  log.info({ to: redactEmail(opts.to), messageId: info.messageId }, 'password reset email sent');
}
