import { resolveMx } from "node:dns/promises";

import disposable from "disposable-email-domains";

/* Domains we treat as personal / free webmail — rejected for lead capture.
   Keep this list pragmatic: a small set covers ~95% of the noise. */
const CONSUMER_DOMAINS = new Set([
  // Google
  "gmail.com",
  "googlemail.com",
  // Yahoo
  "yahoo.com",
  "yahoo.fr",
  "yahoo.co.uk",
  "yahoo.es",
  "yahoo.it",
  "yahoo.de",
  "ymail.com",
  "rocketmail.com",
  // Microsoft
  "hotmail.com",
  "hotmail.fr",
  "hotmail.es",
  "hotmail.it",
  "hotmail.de",
  "hotmail.co.uk",
  "outlook.com",
  "outlook.fr",
  "outlook.es",
  "outlook.it",
  "outlook.de",
  "live.com",
  "live.fr",
  "msn.com",
  // Apple
  "icloud.com",
  "me.com",
  "mac.com",
  // Misc
  "aol.com",
  "protonmail.com",
  "proton.me",
  "pm.me",
  "mail.com",
  "gmx.com",
  "gmx.fr",
  "gmx.de",
  "yandex.com",
  "yandex.ru",
  "tutanota.com",
  "hey.com",
  "fastmail.com",
  "zoho.com",
  // French ISPs / FAI
  "orange.fr",
  "wanadoo.fr",
  "free.fr",
  "sfr.fr",
  "neuf.fr",
  "bbox.fr",
  "laposte.net",
  "club-internet.fr",
  "numericable.fr",
  "9online.fr",
  "voila.fr",
  "noos.fr",
  "alice.fr",
]);

/* Disposable / temp-mail providers from the community-maintained
   `disposable-email-domains` npm package (~5k domains).
   See https://github.com/ivolo/disposable-email-domains */
const DISPOSABLE_DOMAINS = new Set(disposable);

export type ProEmailRejectReason = "format" | "consumer" | "disposable" | "no-mx";

export type ProEmailValidation =
  | { valid: true; domain: string }
  | { valid: false; reason: ProEmailRejectReason };

export async function validateProEmail(email: string): Promise<ProEmailValidation> {
  const at = email.lastIndexOf("@");
  if (at === -1 || at === 0 || at === email.length - 1) {
    return { valid: false, reason: "format" };
  }
  const domain = email
    .slice(at + 1)
    .toLowerCase()
    .trim();
  if (!domain.includes(".")) return { valid: false, reason: "format" };

  if (CONSUMER_DOMAINS.has(domain)) return { valid: false, reason: "consumer" };
  if (DISPOSABLE_DOMAINS.has(domain)) return { valid: false, reason: "disposable" };

  try {
    const records = await resolveMx(domain);
    if (!records || records.length === 0) return { valid: false, reason: "no-mx" };
  } catch {
    return { valid: false, reason: "no-mx" };
  }

  return { valid: true, domain };
}

export function proEmailRejectMessage(reason: ProEmailRejectReason): string {
  switch (reason) {
    case "format":
      return "Adresse email invalide.";
    case "consumer":
      return "Merci d'utiliser votre email professionnel (Gmail, iCloud, Outlook, etc. ne sont pas acceptés).";
    case "disposable":
      return "Les emails jetables ne sont pas acceptés.";
    case "no-mx":
      return "Le domaine de cet email ne semble pas valide.";
  }
}
