import nodemailer from 'nodemailer';
import type pg from 'pg';
import type { WelcomeMailer } from '../domain/ports.js';

const SMTP_KEYS = [
  'smtp_host',
  'smtp_port',
  'smtp_secure',
  'smtp_user',
  'smtp_pass',
  'smtp_from',
] as const;

interface SmtpOptions {
  host: string;
  port: number;
  secure: boolean;
  user: string;
  password: string;
  from: string;
}

function escapeHtml(value: string): string {
  return value.replace(
    /[&<>"']/g,
    (character) =>
      ({
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#39;',
      })[character] ?? character,
  );
}

/**
 * Builds the welcome email body. Pure function: no SMTP, easily unit-testable.
 */
export function buildWelcomeEmail(input: { email: string; name?: string }): {
  subject: string;
  text: string;
  html: string;
} {
  const greetingName = input.name?.trim() ? ` ${escapeHtml(input.name.trim())}` : '';
  return {
    subject: '¡Bienvenido a Mercado de Vida!',
    text: [
      `Hola${input.name?.trim() ? ` ${input.name.trim()}` : ''},`,
      '',
      'Tu cuenta en Mercado de Vida se ha creado correctamente.',
      '',
      'Ya puedes iniciar sesión en mercadodevida y empezar a comprar nuestros productos ecológicos y de proximidad.',
      '',
      'Gracias por unirte.',
    ].join('\n'),
    html: [
      `<p>Hola${greetingName},</p>`,
      '<p>Tu cuenta en <strong>Mercado de Vida</strong> se ha creado correctamente.</p>',
      '<p>Ya puedes <a href="https://mercadodevida">iniciar sesión</a> y empezar a comprar nuestros productos ecológicos y de proximidad.</p>',
      '<p>Gracias por unirte.</p>',
    ].join(''),
  };
}

/**
 * Sends welcome emails through the SMTP configuration stored in store_settings
 * (Ajustes → SMTP / Email), with env-free config so admins can change it
 * without a deploy. Modeled on SettingsPasswordResetMailer. Best-effort: a
 * failure throws so the caller (identity routes) can log and continue.
 */
export class SettingsWelcomeMailer implements WelcomeMailer {
  constructor(private readonly pool: pg.Pool) {}

  async sendWelcome(input: { email: string; name?: string }): Promise<void> {
    const options = await this.readSmtpOptions();
    const transporter = nodemailer.createTransport({
      host: options.host,
      port: options.port,
      secure: options.secure,
      auth: { user: options.user, pass: options.password },
    });
    const body = buildWelcomeEmail(input);
    await transporter.sendMail({
      from: options.from,
      to: input.email,
      subject: body.subject,
      text: body.text,
      html: body.html,
    });
  }

  private async readSmtpOptions(): Promise<SmtpOptions> {
    const result = await this.pool.query<{ key: string; value: string }>(
      `SELECT key, value FROM store_settings WHERE key = ANY($1::text[])`,
      [SMTP_KEYS],
    );
    const settings = Object.fromEntries(result.rows.map((row) => [row.key, row.value]));
    const host = settings.smtp_host?.trim();
    const user = settings.smtp_user?.trim();
    const password = settings.smtp_pass;
    const from = settings.smtp_from?.trim() || user;
    if (!host || !user || !password || !from) {
      throw new Error('SMTP is not configured in Ajustes → SMTP / Email');
    }
    const port = Number(settings.smtp_port || '465');
    if (!Number.isInteger(port) || port < 1 || port > 65535) {
      throw new Error('SMTP port is invalid in Ajustes → SMTP / Email');
    }
    return {
      host,
      port,
      secure: settings.smtp_secure !== 'false' || port === 465,
      user,
      password,
      from,
    };
  }
}
