import { BadRequestException, Injectable, Logger } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service';
import { MailService } from 'src/mail/mail.service';
import { DEFAULT_STORE_CONFIG } from '../default-store-config';
import { leerConfigPublicada } from '../config-publicada';

export interface OrderNotificationVars {
  NRO_PEDIDO: string;
  CLIENTE_NOMBRE: string;
  CLIENTE_EMAIL: string;
  CLIENTE_TELEFONO: string;
  TOTAL: string;
  ITEMS: string;
  METODO_ENTREGA: string;
  DIRECCION_ENTREGA: string;
  TIENDA_NOMBRE: string;
}

/** Sustituye {{VARIABLE}} en subject/body con los valores reales del pedido. */
function render(template: string, vars: OrderNotificationVars): string {
  return template.replace(/\{\{(\w+)\}\}/g, (_, key) => (vars as any)[key] ?? '');
}

function buildItemsTableHtml(v: OrderNotificationVars, accentColor: string, totalColor: string): string {
  return (
    `<div style='margin-bottom:22px'>` +
    `<p style='margin:0 0 10px;font-size:11px;font-weight:800;color:#9ca3af;text-transform:uppercase;letter-spacing:0.08em'>📦 Detalle del pedido</p>` +
    `<table width='100%' cellpadding='0' cellspacing='0' style='border:1px solid #e5e7eb;border-radius:10px;overflow:hidden'>` +
    `<tr style='background:#f9fafb'>` +
    `<td style='padding:9px 6px 9px 14px;width:44px;border-bottom:1px solid #e5e7eb'></td>` +
    `<td style='padding:9px 8px;font-size:11px;font-weight:700;color:#6b7280;border-bottom:1px solid #e5e7eb'>PRODUCTO</td>` +
    `<td style='padding:9px 8px;font-size:11px;font-weight:700;color:#6b7280;border-bottom:1px solid #e5e7eb;text-align:center;white-space:nowrap'>CANT.</td>` +
    `<td style='padding:9px 8px;font-size:11px;font-weight:700;color:#6b7280;border-bottom:1px solid #e5e7eb;text-align:right;white-space:nowrap'>P. UNIT.</td>` +
    `<td style='padding:9px 14px 9px 8px;font-size:11px;font-weight:700;color:#6b7280;border-bottom:1px solid #e5e7eb;text-align:right;white-space:nowrap'>SUBTOTAL</td>` +
    `</tr>${v.ITEMS}` +
    `<tr style='background:${accentColor}'>` +
    `<td colspan='4' style='padding:14px 8px 14px 14px;font-size:14px;font-weight:700;color:#374151;border-top:2px solid #d1fae5'>Total abonado</td>` +
    `<td style='padding:14px 14px 14px 8px;font-size:20px;font-weight:900;color:${totalColor};border-top:2px solid #d1fae5;text-align:right;white-space:nowrap'>${v.TOTAL}</td>` +
    `</tr></table></div>`
  );
}

const EMAIL_STRUCTURE_BUILDERS: Record<string, (v: OrderNotificationVars) => string> = {
  orderConfirmed: (v) =>
    `<p style='margin:0 0 20px;font-size:16px;font-weight:700;color:#111'>Hola, ${v.CLIENTE_NOMBRE} 👋</p>` +
    `<div style='margin-bottom:22px'><table width='100%' cellpadding='0' cellspacing='0' style='background:linear-gradient(135deg,#f0fdf4,#dcfce7);border:1.5px solid #86efac;border-radius:12px'><tr><td style='padding:18px 22px'><span style='display:inline-block;background:#16a34a;color:#fff;font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:0.1em;padding:3px 10px;border-radius:999px;margin-bottom:10px'>✅ Pedido confirmado</span><p style='margin:0;font-size:28px;font-weight:900;color:#14532d;letter-spacing:-0.5px'>${v.NRO_PEDIDO}</p></td></tr></table></div>` +
    buildItemsTableHtml(v, '#f0fdf4', '#16a34a') +
    `<div style='margin-bottom:22px'><table width='100%' cellpadding='0' cellspacing='0' style='background:#eff6ff;border:1.5px solid #bfdbfe;border-radius:12px'><tr><td style='padding:14px 20px'><span style='font-size:11px;font-weight:800;color:#3b82f6;text-transform:uppercase;letter-spacing:0.08em'>🚚 Método de entrega</span><p style='margin:5px 0 0;font-size:15px;font-weight:700;color:#1e3a8a'>${v.METODO_ENTREGA}</p></td></tr></table></div>` +
    `<hr style='border:none;border-top:1px solid #f3f4f6;margin:4px 0 20px'/>`,

  orderInvoiced: (v) =>
    `<p style='margin:0 0 20px;font-size:16px;font-weight:700;color:#111'>Hola, ${v.CLIENTE_NOMBRE} 👋</p>` +
    `<div style='margin-bottom:22px'><table width='100%' cellpadding='0' cellspacing='0' style='background:linear-gradient(135deg,#eff6ff,#dbeafe);border:1.5px solid #93c5fd;border-radius:12px'><tr><td style='padding:18px 22px'><span style='display:inline-block;background:#2563eb;color:#fff;font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:0.1em;padding:3px 10px;border-radius:999px;margin-bottom:10px'>📄 Factura emitida</span><p style='margin:0;font-size:28px;font-weight:900;color:#1e3a8a;letter-spacing:-0.5px'>${v.NRO_PEDIDO}</p></td><td style='padding:18px 22px;text-align:right;font-size:44px;line-height:1;vertical-align:middle'>📄</td></tr></table></div>` +
    `<div style='margin-bottom:22px'><table width='100%' cellpadding='0' cellspacing='0' style='background:#f9fafb;border:1px solid #e5e7eb;border-radius:10px'><tr><td style='padding:16px 20px'><span style='font-size:11px;font-weight:700;color:#9ca3af;text-transform:uppercase;letter-spacing:0.06em'>Total facturado</span><p style='margin:6px 0 0;font-size:30px;font-weight:900;color:#111;letter-spacing:-0.5px'>${v.TOTAL}</p></td><td style='padding:16px 20px;text-align:right;vertical-align:middle'><span style='display:inline-block;background:#dcfce7;color:#16a34a;font-size:12px;font-weight:800;padding:6px 14px;border-radius:999px'>✅ Pagado</span></td></tr></table></div>` +
    `<div style='margin-bottom:22px'><table width='100%' cellpadding='0' cellspacing='0' style='background:#fefce8;border:1.5px solid #fde68a;border-radius:12px'><tr><td style='padding:14px 20px'><span style='font-size:11px;font-weight:800;color:#b45309;text-transform:uppercase;letter-spacing:0.06em'>📎 Archivo adjunto</span><p style='margin:5px 0 0;font-size:13px;color:#78350f;line-height:1.65'>Tu factura en formato PDF está adjunta a este correo. Guardala o imprimila cuando quieras.</p></td></tr></table></div>` +
    `<hr style='border:none;border-top:1px solid #f3f4f6;margin:4px 0 20px'/>`,

  orderShipped: (v) =>
    `<p style='margin:0 0 20px;font-size:16px;font-weight:700;color:#111'>¡Tu pedido está en camino, ${v.CLIENTE_NOMBRE}! 🎉</p>` +
    `<div style='margin-bottom:22px'><table width='100%' cellpadding='0' cellspacing='0' style='background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px'><tr><td style='padding:18px 16px'><table width='100%' cellpadding='0' cellspacing='0'><tr><td style='width:25%;text-align:center;padding:0 4px'><div style='width:34px;height:34px;background:#16a34a;border-radius:50%;line-height:34px;text-align:center;font-size:15px;margin:0 auto 8px'>✅</div><p style='margin:0;font-size:10px;font-weight:700;color:#16a34a'>Pedido</p></td><td style='width:25%;text-align:center;padding:0 4px'><div style='width:34px;height:34px;background:#16a34a;border-radius:50%;line-height:34px;text-align:center;font-size:15px;margin:0 auto 8px'>✅</div><p style='margin:0;font-size:10px;font-weight:700;color:#16a34a'>Confirmado</p></td><td style='width:25%;text-align:center;padding:0 4px'><div style='width:34px;height:34px;background:#f97316;border-radius:50%;line-height:34px;text-align:center;font-size:15px;margin:0 auto 8px'>🚚</div><p style='margin:0;font-size:10px;font-weight:700;color:#f97316'>En camino</p></td><td style='width:25%;text-align:center;padding:0 4px'><div style='width:34px;height:34px;background:#e5e7eb;border-radius:50%;line-height:34px;text-align:center;font-size:15px;margin:0 auto 8px'>🏠</div><p style='margin:0;font-size:10px;font-weight:700;color:#9ca3af'>Entregado</p></td></tr></table></td></tr></table></div>` +
    `<div style='margin-bottom:22px'><table width='100%' cellpadding='0' cellspacing='0' style='background:#fff7ed;border:1.5px solid #fed7aa;border-radius:12px'><tr><td style='padding:16px 20px'><span style='font-size:11px;font-weight:800;color:#ea580c;text-transform:uppercase;letter-spacing:0.08em'>📍 Dirección de entrega</span><p style='margin:6px 0 0;font-size:14px;font-weight:600;color:#1a1a1a;line-height:1.65'>${v.DIRECCION_ENTREGA}</p></td></tr></table></div>` +
    `<div style='margin-bottom:22px'><table width='100%' cellpadding='0' cellspacing='0' style='background:#eff6ff;border:1.5px solid #bfdbfe;border-radius:12px'><tr><td style='padding:14px 20px'><span style='font-size:11px;font-weight:800;color:#3b82f6;text-transform:uppercase;letter-spacing:0.08em'>🚚 Método</span><p style='margin:5px 0 0;font-size:15px;font-weight:700;color:#1e3a8a'>${v.METODO_ENTREGA}</p></td></tr></table></div>` +
    `<hr style='border:none;border-top:1px solid #f3f4f6;margin:4px 0 20px'/>`,

  orderCancelled: (v) =>
    `<p style='margin:0 0 20px;font-size:16px;font-weight:700;color:#111'>Hola, ${v.CLIENTE_NOMBRE}</p>` +
    `<div style='margin-bottom:22px'><table width='100%' cellpadding='0' cellspacing='0' style='background:#fef2f2;border:1.5px solid #fecaca;border-radius:12px'><tr><td style='padding:18px 22px'><span style='display:inline-block;background:#dc2626;color:#fff;font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:0.1em;padding:3px 10px;border-radius:999px;margin-bottom:10px'>❌ Pedido cancelado</span><p style='margin:0;font-size:28px;font-weight:900;color:#7f1d1d;letter-spacing:-0.5px'>${v.NRO_PEDIDO}</p></td></tr></table></div>` +
    `<div style='margin-bottom:22px'><table width='100%' cellpadding='0' cellspacing='0' style='border:1px solid #e5e7eb;border-radius:10px;overflow:hidden'><tr style='background:#f9fafb'><td style='padding:10px 16px;font-size:11px;font-weight:700;color:#6b7280;border-bottom:1px solid #e5e7eb'>¿QUÉ SIGUE?</td></tr><tr><td style='padding:16px;font-size:13px;color:#374151;line-height:1.9'><p style='margin:0 0 10px'>🔄 <strong style='color:#111'>Reintegro:</strong> Si realizaste algún pago, será procesado en los próximos días hábiles.</p><p style='margin:0 0 10px'>🛒 <strong style='color:#111'>Nuevo pedido:</strong> Podés volver a la tienda y realizar tu compra cuando quieras.</p><p style='margin:0'>💬 <strong style='color:#111'>¿Necesitás ayuda?</strong> Respondé este correo y te asistimos de inmediato.</p></td></tr></table></div>` +
    `<div style='margin-bottom:22px'><table width='100%' cellpadding='0' cellspacing='0' style='background:#f1f5f9;border:1.5px solid #cbd5e1;border-radius:12px'><tr><td style='padding:14px 20px'><span style='font-size:11px;font-weight:800;color:#475569;text-transform:uppercase;letter-spacing:0.08em'>📞 ¿Hablamos?</span><p style='margin:5px 0 0;font-size:13px;color:#334155;line-height:1.65'>Respondé este correo o contactanos directamente. Estamos para ayudarte.</p></td></tr></table></div>` +
    `<hr style='border:none;border-top:1px solid #f3f4f6;margin:4px 0 20px'/>`,

  newOrderAdmin: (v) =>
    `<div style='margin-bottom:20px'><table width='100%' cellpadding='0' cellspacing='0' style='background:linear-gradient(135deg,#fff7ed,#ffedd5);border:1.5px solid #fed7aa;border-radius:12px'><tr><td style='padding:18px 22px'><span style='display:inline-block;background:#ea580c;color:#fff;font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:0.1em;padding:3px 10px;border-radius:999px;margin-bottom:10px'>🔔 Nuevo pedido recibido</span><p style='margin:0;font-size:28px;font-weight:900;color:#7c2d12;letter-spacing:-0.5px'>${v.NRO_PEDIDO}</p></td><td style='padding:18px 22px;text-align:right;font-size:44px;line-height:1;vertical-align:middle'>🛍️</td></tr></table></div>` +
    `<div style='margin-bottom:20px'><p style='margin:0 0 10px;font-size:11px;font-weight:800;color:#9ca3af;text-transform:uppercase;letter-spacing:0.08em'>👤 Datos del cliente</p><table width='100%' cellpadding='0' cellspacing='0' style='border:1px solid #e5e7eb;border-radius:10px;overflow:hidden'><tr style='background:#f9fafb'><td style='width:35%;padding:9px 14px;font-size:11px;font-weight:700;color:#6b7280;border-bottom:1px solid #e5e7eb'>CAMPO</td><td style='padding:9px 14px;font-size:11px;font-weight:700;color:#6b7280;border-bottom:1px solid #e5e7eb'>VALOR</td></tr><tr><td style='padding:10px 14px;font-size:12px;color:#6b7280;border-bottom:1px solid #f3f4f6'>Nombre</td><td style='padding:10px 14px;font-size:13px;font-weight:600;color:#111;border-bottom:1px solid #f3f4f6'>${v.CLIENTE_NOMBRE}</td></tr><tr><td style='padding:10px 14px;font-size:12px;color:#6b7280;border-bottom:1px solid #f3f4f6'>Email</td><td style='padding:10px 14px;font-size:13px;font-weight:600;color:#111;border-bottom:1px solid #f3f4f6'>${v.CLIENTE_EMAIL}</td></tr><tr><td style='padding:10px 14px;font-size:12px;color:#6b7280'>Teléfono</td><td style='padding:10px 14px;font-size:13px;font-weight:600;color:#111'>${v.CLIENTE_TELEFONO}</td></tr></table></div>` +
    `<div style='margin-bottom:20px'><p style='margin:0 0 10px;font-size:11px;font-weight:800;color:#9ca3af;text-transform:uppercase;letter-spacing:0.08em'>📦 Productos</p><table width='100%' cellpadding='0' cellspacing='0' style='border:1px solid #e5e7eb;border-radius:10px;overflow:hidden'><tr style='background:#f9fafb'><td style='padding:9px 6px 9px 14px;width:44px;border-bottom:1px solid #e5e7eb'></td><td style='padding:9px 8px;font-size:11px;font-weight:700;color:#6b7280;border-bottom:1px solid #e5e7eb'>PRODUCTO</td><td style='padding:9px 8px;font-size:11px;font-weight:700;color:#6b7280;border-bottom:1px solid #e5e7eb;text-align:center;white-space:nowrap'>CANT.</td><td style='padding:9px 8px;font-size:11px;font-weight:700;color:#6b7280;border-bottom:1px solid #e5e7eb;text-align:right;white-space:nowrap'>P. UNIT.</td><td style='padding:9px 14px 9px 8px;font-size:11px;font-weight:700;color:#6b7280;border-bottom:1px solid #e5e7eb;text-align:right;white-space:nowrap'>SUBTOTAL</td></tr>${v.ITEMS}<tr style='background:#fff7ed'><td colspan='4' style='padding:14px 8px 14px 14px;font-size:14px;font-weight:700;color:#374151;border-top:2px solid #fed7aa'>Total del pedido</td><td style='padding:14px 14px 14px 8px;font-size:20px;font-weight:900;color:#ea580c;border-top:2px solid #fed7aa;text-align:right;white-space:nowrap'>${v.TOTAL}</td></tr></table></div>` +
    `<div style='margin-bottom:20px'><table width='100%' cellpadding='0' cellspacing='0' style='background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px'><tr><td style='padding:14px 18px'><p style='margin:0 0 4px;font-size:12px;font-weight:700;color:#475569'>🚚 ${v.METODO_ENTREGA}</p><p style='margin:0;font-size:13px;color:#334155'>📍 ${v.DIRECCION_ENTREGA}</p></td></tr></table></div>` +
    `<hr style='border:none;border-top:1px solid #f3f4f6;margin:4px 0 20px'/>`,
};

function formatItems(items: any[]): string {
  const gs = (n: number) => `Gs. ${n.toLocaleString('es-PY')}`;
  return items
    .map((i) => {
      const name = i.name ?? i.productName ?? 'Producto';
      const qty = Number(i.quantity ?? 1);
      const unitPrice = Number(i.unitPrice ?? i.price ?? 0);
      const subtotal = Number(i.lineTotal ?? unitPrice * qty);
      const imgUrl: string = i.imageUrl ?? '';
      const imgCell = imgUrl
        ? `<td style='padding:10px 6px 10px 14px;vertical-align:middle;border-bottom:1px solid #f3f4f6'><img src='${imgUrl}' width='36' height='36' alt='' style='border-radius:6px;display:block;object-fit:cover'/></td>`
        : `<td style='padding:10px 6px 10px 14px;vertical-align:middle;border-bottom:1px solid #f3f4f6'><div style='width:36px;height:36px;background:#f3f4f6;border-radius:6px;text-align:center;line-height:36px;font-size:18px'>📦</div></td>`;
      return (
        `<tr>${imgCell}` +
        `<td style='padding:10px 8px;font-size:13px;font-weight:600;color:#111;vertical-align:middle;border-bottom:1px solid #f3f4f6'>${name}</td>` +
        `<td style='padding:10px 8px;font-size:13px;color:#6b7280;text-align:center;vertical-align:middle;border-bottom:1px solid #f3f4f6;white-space:nowrap'>× ${qty}</td>` +
        `<td style='padding:10px 8px;font-size:13px;color:#374151;text-align:right;vertical-align:middle;border-bottom:1px solid #f3f4f6;white-space:nowrap'>${gs(unitPrice)}</td>` +
        `<td style='padding:10px 14px 10px 8px;font-size:13px;font-weight:700;color:#111;text-align:right;vertical-align:middle;border-bottom:1px solid #f3f4f6;white-space:nowrap'>${gs(subtotal)}</td></tr>`
      );
    })
    .join('');
}

function formatTotal(totals: any): string {
  const total = Number(totals?.total ?? totals?.subtotal ?? 0);
  return `Gs. ${total.toLocaleString('es-PY')}`;
}

@Injectable()
export class EcommerceNotificationsService {
  private readonly logger = new Logger(EcommerceNotificationsService.name);

  constructor(
    private readonly prisma: PrismaService,
    private readonly mail: MailService,
  ) {}

  /**
   * Carga la config de notificaciones. Los pedidos reales usan la versión PUBLICADA;
   * el mail de prueba usa el borrador (`borrador: true`) para poder ver una plantilla
   * antes de publicarla.
   */
  private async loadNotificationsConfig(empresaId: string, opts: { borrador?: boolean } = {}): Promise<any> {
    const row: { notifications_config?: unknown; nombre_comercial?: string | null } | null = opts.borrador
      ? await this.prisma.ecommerce_config.findUnique({
          where: { empresa_id: empresaId },
          select: { notifications_config: true, nombre_comercial: true },
        })
      : await leerConfigPublicada(this.prisma, empresaId, ['notifications_config', 'nombre_comercial'] as const);
    const def = (DEFAULT_STORE_CONFIG as any).notifications;
    const cfg = (row?.notifications_config as any) ?? {};
    return {
      tiendaNombre: row?.nombre_comercial ?? 'La tienda',
      adminEmail: cfg.adminEmail ?? def.adminEmail ?? '',
      orderConfirmed: { ...def.orderConfirmed, ...(cfg.orderConfirmed ?? {}) },
      orderInvoiced: { ...def.orderInvoiced, ...(cfg.orderInvoiced ?? {}) },
      orderShipped: { ...def.orderShipped, ...(cfg.orderShipped ?? {}) },
      orderCancelled: { ...def.orderCancelled, ...(cfg.orderCancelled ?? {}) },
      newOrderAdmin: { ...def.newOrderAdmin, ...(cfg.newOrderAdmin ?? {}) },
    };
  }

  private buildVars(session: any, tiendaNombre: string): OrderNotificationVars {
    const customer = (session.customer_snapshot as any) ?? {};
    const delivery = (session.delivery_snapshot as any) ?? {};
    const items = (session.items_snapshot as any[]) ?? [];
    const totals = (session.totals_snapshot as any) ?? {};

    const direccion = [delivery.address, delivery.city, delivery.district, delivery.department]
      .filter(Boolean)
      .join(', ');
    const metodo = delivery.methodName ?? (delivery.type === 'pickup' ? 'Retiro en tienda' : 'Delivery');

    return {
      NRO_PEDIDO: session.codigo ?? '',
      CLIENTE_NOMBRE: customer.name ?? 'Cliente',
      CLIENTE_EMAIL: customer.email ?? '',
      CLIENTE_TELEFONO: customer.phone ?? '',
      TOTAL: formatTotal(totals),
      ITEMS: formatItems(items),
      METODO_ENTREGA: metodo,
      DIRECCION_ENTREGA: direccion || 'No especificada',
      TIENDA_NOMBRE: tiendaNombre,
    };
  }

  private async sendIfEnabled(
    tpl: { enabled: boolean; subject: string; body: string },
    to: string,
    vars: OrderNotificationVars,
    tplKey: string,
    pdfAttachment?: { filename: string; content: Buffer },
  ): Promise<void> {
    // Cada envío deja rastro en el log: antes un mail de pedido real no se registraba
    // ni al salir ni al fallar, y no había forma de saber si el comprador lo recibió.
    if (!tpl.enabled) {
      this.logger.log(`Email ${tplKey} del pedido ${vars.NRO_PEDIDO} omitido: la plantilla está desactivada.`);
      return;
    }
    if (!to) {
      this.logger.warn(`Email ${tplKey} del pedido ${vars.NRO_PEDIDO} omitido: no hay destinatario.`);
      return;
    }
    const subject = render(tpl.subject, vars);
    const structureHtml = EMAIL_STRUCTURE_BUILDERS[tplKey]?.(vars) ?? '';
    const bodyHtml = render(tpl.body, vars);
    const html = structureHtml + (bodyHtml ? `<div style="margin-top:4px">${bodyHtml}</div>` : '');
    try {
      await this.mail.sendStoreEmail({ to, subject, html, pdfAttachment });
    } catch (err) {
      this.logger.error(`Email ${tplKey} del pedido ${vars.NRO_PEDIDO} a ${to} falló: ${(err as Error).message}`);
      throw err;
    }
    this.logger.log(`Email ${tplKey} del pedido ${vars.NRO_PEDIDO} enviado a ${to}.`);
  }

  /**
   * Envía un email de PRUEBA de una plantilla con datos de ejemplo, para que el
   * comercio vea cómo llega antes de que haya pedidos reales. Va al email indicado
   * o, si no, al del administrador configurado.
   */
  async sendTestEmail(empresaId: string, tplKey: string, toEmail?: string): Promise<{ to: string }> {
    const cfg = await this.loadNotificationsConfig(empresaId, { borrador: true });
    const plantillas: Record<string, { enabled: boolean; subject: string; body: string }> = {
      orderConfirmed: cfg.orderConfirmed,
      orderInvoiced: cfg.orderInvoiced,
      orderShipped: cfg.orderShipped,
      orderCancelled: cfg.orderCancelled,
      newOrderAdmin: cfg.newOrderAdmin,
    };
    const tpl = plantillas[tplKey];
    if (!tpl) throw new BadRequestException('Plantilla de notificación desconocida.');

    const to = (toEmail?.trim() || cfg.adminEmail || '').trim();
    if (!to) {
      throw new BadRequestException(
        'Indicá un email de destino o configurá el email del administrador para enviar la prueba.',
      );
    }

    const vars: OrderNotificationVars = {
      NRO_PEDIDO: 'ECOM-2026-0001',
      CLIENTE_NOMBRE: 'Cliente de Prueba',
      CLIENTE_EMAIL: to,
      CLIENTE_TELEFONO: '0981 000 000',
      TOTAL: 'Gs. 250.000',
      ITEMS: '2 × Producto de ejemplo',
      METODO_ENTREGA: 'Delivery programado',
      DIRECCION_ENTREGA: 'Asunción, Paraguay',
      TIENDA_NOMBRE: cfg.tiendaNombre,
    };
    const subject = `[PRUEBA] ${render(tpl.subject, vars)}`;
    const structureHtml = EMAIL_STRUCTURE_BUILDERS[tplKey]?.(vars) ?? '';
    const bodyHtml = render(tpl.body, vars);
    const html = structureHtml + (bodyHtml ? `<div style="margin-top:4px">${bodyHtml}</div>` : '');
    await this.mail.sendStoreEmail({ to, subject, html });
    this.logger.log(`Email de prueba (${tplKey}) enviado a ${to} para empresa ${empresaId}`);
    return { to };
  }

  /** Pedido confirmado por el cliente (checkout creado). */
  async onOrderCreated(empresaId: string, sessionId: string): Promise<void> {
    try {
      const [session, cfg] = await Promise.all([
        this.prisma.ecommerce_checkout_session.findUnique({ where: { id: sessionId } }),
        this.loadNotificationsConfig(empresaId),
      ]);
      if (!session) return;

      const vars = this.buildVars(session, cfg.tiendaNombre);
      const customerEmail = (session.customer_snapshot as any)?.email ?? '';

      await Promise.allSettled([
        this.sendIfEnabled(cfg.orderConfirmed, customerEmail, vars, 'orderConfirmed'),
        this.sendIfEnabled(cfg.newOrderAdmin, cfg.adminEmail, vars, 'newOrderAdmin'),
      ]);
    } catch (err) {
      this.logger.warn(`onOrderCreated failed for session ${sessionId}: ${(err as Error).message}`);
    }
  }

  /** Pedido listo/despachado (estado → listo). */
  async onOrderShipped(empresaId: string, sessionId: string): Promise<void> {
    try {
      const [session, cfg] = await Promise.all([
        this.prisma.ecommerce_checkout_session.findUnique({ where: { id: sessionId } }),
        this.loadNotificationsConfig(empresaId),
      ]);
      if (!session) return;

      const vars = this.buildVars(session, cfg.tiendaNombre);
      const customerEmail = (session.customer_snapshot as any)?.email ?? '';
      await this.sendIfEnabled(cfg.orderShipped, customerEmail, vars, 'orderShipped');
    } catch (err) {
      this.logger.warn(`onOrderShipped failed for session ${sessionId}: ${(err as Error).message}`);
    }
  }

  /** Pedido cancelado. */
  async onOrderCancelled(empresaId: string, sessionId: string): Promise<void> {
    try {
      const [session, cfg] = await Promise.all([
        this.prisma.ecommerce_checkout_session.findUnique({ where: { id: sessionId } }),
        this.loadNotificationsConfig(empresaId),
      ]);
      if (!session) return;

      const vars = this.buildVars(session, cfg.tiendaNombre);
      const customerEmail = (session.customer_snapshot as any)?.email ?? '';
      await this.sendIfEnabled(cfg.orderCancelled, customerEmail, vars, 'orderCancelled');
    } catch (err) {
      this.logger.warn(`onOrderCancelled failed for session ${sessionId}: ${(err as Error).message}`);
    }
  }

  /**
   * Pedido facturado — llamado desde facturas.service al crear factura
   * vinculada a un pedido ERP que proviene de ecommerce.
   */
  async onOrderInvoiced(
    empresaId: string,
    pedidoId: string,
    pdfAttachment?: { filename: string; content: Buffer },
  ): Promise<void> {
    try {
      const session = await this.prisma.ecommerce_checkout_session.findFirst({
        where: { empresa_id: empresaId, pedido_id: pedidoId },
      });
      if (!session) return; // pedido no proviene de ecommerce

      const cfg = await this.loadNotificationsConfig(empresaId);
      const vars = this.buildVars(session, cfg.tiendaNombre);
      const customerEmail = (session.customer_snapshot as any)?.email ?? '';
      await this.sendIfEnabled(cfg.orderInvoiced, customerEmail, vars, 'orderInvoiced', pdfAttachment);
    } catch (err) {
      this.logger.warn(`onOrderInvoiced failed for pedido ${pedidoId}: ${(err as Error).message}`);
    }
  }
}
