import { beforeEach, describe, expect, it, vi } from 'vitest';
import {
  buildWelcomeEmail,
  SettingsWelcomeMailer,
} from '../infrastructure/settings-welcome-mailer.js';

const SMTP_ROWS = [
  { key: 'smtp_host', value: 'smtp.test' },
  { key: 'smtp_port', value: '587' },
  { key: 'smtp_secure', value: 'false' },
  { key: 'smtp_user', value: 'user@test' },
  { key: 'smtp_pass', value: 'pass' },
  { key: 'smtp_from', value: 'no-reply@test' },
];

const sentMails: Record<string, unknown>[] = [];
vi.mock('nodemailer', () => ({
  default: {
    createTransport: () => ({
      sendMail: (mail: Record<string, unknown>) => {
        sentMails.push(mail);
        return Promise.resolve({});
      },
    }),
  },
}));

function pool(rows: typeof SMTP_ROWS | [] = SMTP_ROWS) {
  return { query: vi.fn().mockResolvedValue({ rows }) };
}

describe('buildWelcomeEmail', () => {
  it('greets by name and links to mercadodevida', () => {
    const email = buildWelcomeEmail({ email: 'a@b.c', name: 'Ada' });
    expect(email.subject).toBe('¡Bienvenido a Mercado de Vida!');
    expect(email.text).toContain('Hola Ada');
    expect(email.html).toContain('<p>Hola Ada,</p>');
    expect(email.html).toContain('mercadodevida');
  });

  it('falls back to a generic greeting when name is missing', () => {
    const email = buildWelcomeEmail({ email: 'a@b.c' });
    expect(email.text).toContain('Hola,');
    expect(email.html).toContain('<p>Hola,</p>');
  });

  it('escapes HTML in the name for the HTML body (XSS)', () => {
    const email = buildWelcomeEmail({ email: 'a@b.c', name: '<b>Ada</b>' });
    expect(email.html).not.toContain('<b>Ada</b>');
    expect(email.html).toContain('&lt;b&gt;Ada&lt;/b&gt;');
  });
});

describe('SettingsWelcomeMailer', () => {
  beforeEach(() => {
    sentMails.length = 0;
  });

  it('reads SMTP config from store_settings and sends the welcome email', async () => {
    const pgPool = pool();
    const mailer = new SettingsWelcomeMailer(pgPool as unknown as import('pg').Pool);
    await mailer.sendWelcome({ email: 'ada@example.com', name: 'Ada' });
    expect(pgPool.query).toHaveBeenCalled();
    expect(sentMails).toHaveLength(1);
    const mail = sentMails[0]!;
    expect(mail.to).toBe('ada@example.com');
    expect(mail.from).toBe('no-reply@test');
    expect(mail.subject).toBe('¡Bienvenido a Mercado de Vida!');
  });

  it('throws when SMTP is not configured', async () => {
    const pgPool = pool([]);
    const mailer = new SettingsWelcomeMailer(pgPool as unknown as import('pg').Pool);
    await expect(mailer.sendWelcome({ email: 'ada@example.com' })).rejects.toThrow(
      'SMTP is not configured',
    );
    expect(sentMails).toHaveLength(0);
  });
});
