import nodemailer from 'nodemailer';
import type pg from 'pg';
import type { EmailMessage } from '../domain/notification.js';
import type { EmailProvider } from '../domain/ports.js';

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

export interface TransactionalEmail {
  to: string;
  subject: string;
  text: string;
  html?: string;
}

export async function sendTransactionalEmail(pool: pg.Pool, message: TransactionalEmail): Promise<void> {
  const result = await 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() || process.env.SMTP_HOST?.trim();
  const user = settings.smtp_user?.trim() || process.env.SMTP_USER?.trim();
  const password = settings.smtp_pass || process.env.SMTP_PASS;
  const from = settings.smtp_from?.trim() || process.env.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 || process.env.SMTP_PORT || '465');
  if (!Number.isInteger(port) || port < 1 || port > 65535) {
    throw new Error('SMTP port is invalid in Ajustes → SMTP / Email');
  }
  const transporter = nodemailer.createTransport({
    host,
    port,
    secure: (settings.smtp_secure ?? process.env.SMTP_SECURE) !== 'false' || port === 465,
    auth: { user, pass: password },
  });
  await transporter.sendMail({ from, ...message });
}

export class SettingsEmailProvider implements EmailProvider {
  constructor(private readonly pool: pg.Pool) {}

  async send(message: EmailMessage): Promise<void> {
    await sendTransactionalEmail(this.pool, {
      to: message.recipient,
      subject: message.subject,
      text: message.body,
      html: `<p>${escapeHtml(message.body).replace(/\n/g, '<br>')}</p>`,
    });
  }
}

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