// lib/dns-verify.ts
import dns from "dns";
import { promisify } from "util";

const resolveMx = promisify(dns.resolveMx);
const resolveTxt = promisify(dns.resolveTxt);

// The MX target your inbound mail routing provider requires customers to point to.
// Configure via env so it can be swapped for Mailgun / Postmark / etc without a code change.
const REQUIRED_MX_HOST = process.env.INBOUND_MX_HOST || "mxa.mailgun.org";
const REQUIRED_MX_HOST_FALLBACK = process.env.INBOUND_MX_HOST_FALLBACK || "mxb.mailgun.org";
const TXT_PREFIX = "tempmail-verify=";

export interface DnsVerificationResult {
  mxValid: boolean;
  txtValid: boolean;
  isFullyVerified: boolean;
  mxRecordsFound: string[];
  txtRecordsFound: string[];
  errors: string[];
}

/**
 * Checks live MX and TXT records for a domain to confirm the admin has
 * correctly pointed DNS at our inbound mail infrastructure, and owns the
 * domain (via a unique TXT verification token).
 */
export async function verifyDomainDns(
  domainName: string,
  expectedVerificationToken: string
): Promise<DnsVerificationResult> {
  const result: DnsVerificationResult = {
    mxValid: false,
    txtValid: false,
    isFullyVerified: false,
    mxRecordsFound: [],
    txtRecordsFound: [],
    errors: [],
  };

  // --- MX record check -----------------------------------------------------
  try {
    const mxRecords = await resolveMx(domainName);
    result.mxRecordsFound = mxRecords.map((r) => r.exchange.toLowerCase());
    result.mxValid = result.mxRecordsFound.some(
      (host) =>
        host === REQUIRED_MX_HOST.toLowerCase() ||
        host === REQUIRED_MX_HOST_FALLBACK.toLowerCase()
    );
  } catch (err) {
    const message = err instanceof Error ? err.message : "Unknown MX lookup error";
    result.errors.push(`MX lookup failed: ${message}`);
  }

  // --- TXT record check (domain ownership proof) ---------------------------
  try {
    const txtRecordsRaw = await resolveTxt(domainName);
    // dns.resolveTxt returns string[][] (chunked TXT records) — flatten them
    const flattened = txtRecordsRaw.map((chunks) => chunks.join(""));
    result.txtRecordsFound = flattened;

    const expectedRecord = `${TXT_PREFIX}${expectedVerificationToken}`;
    result.txtValid = flattened.some((record) => record.trim() === expectedRecord);
  } catch (err) {
    const message = err instanceof Error ? err.message : "Unknown TXT lookup error";
    result.errors.push(`TXT lookup failed: ${message}`);
  }

  result.isFullyVerified = result.mxValid && result.txtValid;
  return result;
}

/**
 * Builds the exact DNS records an admin needs to add at their registrar,
 * for display in the "DNS Settings" modal.
 */
export function buildRequiredDnsRecords(verificationToken: string) {
  return {
    mxRecords: [
      { type: "MX", host: "@", value: REQUIRED_MX_HOST, priority: 10 },
      { type: "MX", host: "@", value: REQUIRED_MX_HOST_FALLBACK, priority: 20 },
    ],
    txtRecord: {
      type: "TXT",
      host: "@",
      value: `${TXT_PREFIX}${verificationToken}`,
    },
  };
}
