import { ImapFlow } from 'imapflow';
import nodemailer from 'nodemailer';
import dns from 'node:dns/promises';
import net from 'node:net';

// Резолвим имя резолвером ОС (getaddrinfo), а не c-ares.
// nodemailer по умолчанию использует c-ares (dns.resolve), который в некоторых
// окружениях настроен на нерабочий DNS-сервер и даёт queryA ETIMEOUT.
// Подключаемся по IP, но TLS-сертификат проверяем по исходному имени (servername).
async function resolveHost(host) {
  if (!host || net.isIP(host)) return host;
  try {
    const { address } = await dns.lookup(host);
    return address;
  } catch {
    return host; // не вышло — пусть библиотека сама пробует
  }
}

// Проверка IMAP: подключаемся, авторизуемся, читаем число писем в INBOX и выходим.
// Бросает понятную ошибку, если что-то не так.
export async function testImap({ host, port, secure, user, pass }) {
  if (!host || !user) throw new Error('Укажите IMAP хост и логин');
  const client = new ImapFlow({
    host,
    port: Number(port) || 993,
    secure: secure !== false && secure !== 0,
    auth: { user, pass },
    logger: false,
    // Не зависаем надолго при недоступном сервере.
    socketTimeout: 15000,
  });
  try {
    await client.connect();
    const mailbox = await client.mailboxOpen('INBOX');
    const total = mailbox.exists;
    await client.logout();
    return { ok: true, total };
  } catch (err) {
    try { await client.logout(); } catch { /* уже закрыто */ }
    throw new Error(`IMAP: ${err.message}`);
  }
}

// Отправка письма через SMTP. Использует resolveHost (обход c-ares).
export async function sendMail({ host, port, secure, user, pass }, { from, to, subject, text }) {
  if (!to) throw new Error('Не указан получатель');
  const ip = await resolveHost(host);
  const transporter = nodemailer.createTransport({
    host: ip,
    port: Number(port) || 465,
    secure: secure !== false && secure !== 0,
    auth: { user, pass },
    connectionTimeout: 15000,
    greetingTimeout: 15000,
    tls: { servername: host },
  });
  const info = await transporter.sendMail({ from, to, subject, text });
  return { ok: true, messageId: info.messageId };
}

// Проверка SMTP: создаём транспорт и вызываем verify() — он логинится на сервере.
export async function testSmtp({ host, port, secure, user, pass }) {
  if (!host || !user) throw new Error('Укажите SMTP хост и логин');
  const ip = await resolveHost(host);
  const transporter = nodemailer.createTransport({
    host: ip,
    port: Number(port) || 465,
    secure: secure !== false && secure !== 0,
    auth: { user, pass },
    connectionTimeout: 15000,
    greetingTimeout: 15000,
    // Проверяем сертификат по реальному имени, хотя подключаемся по IP.
    tls: { servername: host },
  });
  try {
    await transporter.verify();
    return { ok: true };
  } catch (err) {
    throw new Error(`SMTP: ${err.message}`);
  }
}
