import nodemailer, { type Transporter } from "nodemailer";
import { appendFile, mkdir } from "node:fs/promises";
import path from "node:path";

/* Central mail module — SMTP via env, never throws to callers. */

let transporter: Transporter | null = null;

/* Idempotency guard: repeated submissions of the same payload within a
   short window (double-clicks, retries, StrictMode re-invocation) must
   not produce repeated mails. Keyed per mail type + lead identity. */
const sentRecently = new Map<string, number>();
const DEDUPE_WINDOW_MS = 120_000;

function isDuplicate(key: string): boolean {
  const now = Date.now();
  for (const [k, ts] of sentRecently) {
    if (now - ts > DEDUPE_WINDOW_MS) sentRecently.delete(k);
  }
  if (sentRecently.has(key)) return true;
  sentRecently.set(key, now);
  return false;
}

/** Failure ledger: which mails died, when, why. Powers the health
    endpoint's 24h count. Never throws, contains no message bodies. */
async function logMailFailure(
  type: "lead" | "ack" | "newsletter" | "callback" | "verify",
  detail: string
): Promise<void> {
  try {
    const dir = path.join(process.cwd(), "data");
    await mkdir(dir, { recursive: true });
    await appendFile(
      path.join(dir, "mail-failures.jsonl"),
      JSON.stringify({
        ts: new Date().toISOString(),
        type,
        detail: String(detail).slice(0, 200),
      }) + "\n",
      "utf8"
    );
  } catch {
    /* ledger itself must never break sending */
  }
}

/** Count failures in the trailing 24h (for /api/health). Never throws. */
export async function countRecentMailFailures(): Promise<number> {
  try {
    const { readFile } = await import("node:fs/promises");
    const raw = await readFile(
      path.join(process.cwd(), "data", "mail-failures.jsonl"),
      "utf8"
    );
    const cutoff = Date.now() - 24 * 60 * 60 * 1000;
    let n = 0;
    for (const line of raw.split("\n")) {
      if (!line.trim()) continue;
      try {
        const ts = Date.parse(JSON.parse(line).ts);
        if (!Number.isNaN(ts) && ts >= cutoff) n++;
      } catch {
        /* skip malformed lines */
      }
    }
    return n;
  } catch {
    return 0; // no ledger yet = no failures recorded
  }
}

function getTransporter(): Transporter | null {
  const host = process.env.SMTP_HOST;
  const user = process.env.SMTP_USER;
  const pass = process.env.SMTP_PASS;
  if (!host || !user || !pass) return null;
  if (!transporter) {
    transporter = nodemailer.createTransport({
      host,
      port: Number(process.env.SMTP_PORT ?? 465),
      secure: process.env.SMTP_SECURE !== "false",
      auth: { user, pass },
      pool: true,
      maxConnections: 3,
      connectionTimeout: 10_000,
      greetingTimeout: 10_000,
      socketTimeout: 15_000,
    });
  }
  return transporter;
}

export function getReceivers(): string[] {
  return (process.env.CONTACT_RECEIVER ?? "")
    .split(",")
    .map((s) => s.trim())
    .filter(Boolean);
}

/* Cheap SMTP handshake for the health endpoint. Cached + time-bounded.
   Returns "ok" | "skipped" (no env configured) | "fail". Never throws. */
let smtpCache: { at: number; result: "ok" | "fail" } | null = null;
const SMTP_CACHE_MS = 60_000;

export async function checkSmtp(): Promise<"ok" | "skipped" | "fail"> {
  const t = getTransporter();
  if (!t) return "skipped";
  const now = Date.now();
  if (smtpCache && now - smtpCache.at < SMTP_CACHE_MS) {
    return smtpCache.result;
  }
  try {
    const result = await Promise.race([
      t.verify(),
      new Promise<never>((_, reject) =>
        setTimeout(() => reject(new Error("smtp-verify-timeout")), 5_000)
      ),
    ]);
    void result;
    smtpCache = { at: now, result: "ok" };
    return "ok";
  } catch (e) {
    console.error("[mail] smtp verify failed:", e);
    void logMailFailure("verify", e instanceof Error ? e.message : String(e));
    smtpCache = { at: now, result: "fail" };
    return "fail";
  }
}

const FROM_SMTP = process.env.SMTP_USER ?? "vivekthakur@acgil.com";
const FROM_SALES = `MxERP Sales <${FROM_SMTP}>`;
const FROM_SITE = `MxERP Website <${FROM_SMTP}>`;

export type LeadMailData = {
  name: string;
  company: string;
  email: string;
  phone?: string;
  phoneCountry?: string;
  industry: string;
  companySize?: string;
  interests: string[];
  notes?: string;
  page: string;
};

const esc = (s: string) =>
  s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");

function leadAlertHtml(d: LeadMailData, when: string): string {
  const interests =
    d.interests.length > 0
      ? d.interests
          .map(
            (i) =>
              `<span style="display:inline-block;background:#eff6ff;color:#1d4ed8;font-size:12px;font-weight:600;padding:4px 10px;border-radius:999px;margin:0 6px 6px 0;">${esc(i)}</span>`
          )
          .join("")
      : '<span style="color:#64748b;font-size:13px;">Not specified</span>';
  return `
<table width="100%" cellpadding="0" cellspacing="0" style="font-family:Arial,Helvetica,sans-serif;background:#f1f5f9;padding:24px 0;">
  <tr><td align="center">
    <table width="600" cellpadding="0" cellspacing="0" style="background:#ffffff;border-radius:12px;overflow:hidden;max-width:600px;width:100%;">
      <tr><td style="background:#0b1b33;padding:20px 28px;">
        <div style="color:#7db4ff;font-size:11px;letter-spacing:2px;font-weight:bold;">MXERP · NEW LEAD</div>
        <div style="color:#ffffff;font-size:20px;font-weight:bold;margin-top:6px;">New demo request — ${esc(d.company)}</div>
      </td></tr>
      <tr><td style="padding:24px 28px;">
        <div style="font-size:12px;letter-spacing:1.5px;color:#64748b;font-weight:bold;margin-bottom:10px;">CONTACT</div>
        <table width="100%" cellpadding="0" cellspacing="0" style="font-size:14px;color:#0f172a;">
          <tr><td style="padding:4px 0;color:#64748b;width:110px;">Name</td><td style="padding:4px 0;font-weight:bold;">${esc(d.name)}</td></tr>
          <tr><td style="padding:4px 0;color:#64748b;">Company</td><td style="padding:4px 0;font-weight:bold;">${esc(d.company)}</td></tr>
          <tr><td style="padding:4px 0;color:#64748b;">Email</td><td style="padding:4px 0;"><a href="mailto:${esc(d.email)}" style="color:#1d4ed8;">${esc(d.email)}</a></td></tr>
          ${d.phone ? `<tr><td style="padding:4px 0;color:#64748b;">Phone</td><td style="padding:4px 0;">${esc(d.phone)}${d.phoneCountry ? ` <span style="color:#64748b;">(${esc(d.phoneCountry)})</span>` : ""}</td></tr>` : ""}
        </table>
        <div style="font-size:12px;letter-spacing:1.5px;color:#64748b;font-weight:bold;margin:20px 0 10px;">REQUIREMENT</div>
        <table width="100%" cellpadding="0" cellspacing="0" style="font-size:14px;color:#0f172a;">
          <tr><td style="padding:4px 0;color:#64748b;width:110px;">Industry</td><td style="padding:4px 0;font-weight:bold;">${esc(d.industry)}</td></tr>
          ${d.companySize ? `<tr><td style="padding:4px 0;color:#64748b;">Size</td><td style="padding:4px 0;">${esc(d.companySize)}</td></tr>` : ""}
        </table>
        <div style="margin-top:8px;">${interests}</div>
        ${d.notes ? `<div style="margin-top:12px;background:#f8fafc;border-left:3px solid #f59e13;padding:12px 14px;font-size:13px;color:#334155;font-style:italic;">&ldquo;${esc(d.notes)}&rdquo;</div>` : ""}
        <div style="margin-top:20px;font-size:12px;color:#94a3b8;">Page: ${esc(d.page)} · ${esc(when)}</div>
        <div style="margin-top:16px;">
          <a href="mailto:${esc(d.email)}?subject=Re%3A%20Your%20MxERP%20demo%20request" style="display:inline-block;background:#1d4ed8;color:#ffffff;font-size:14px;font-weight:bold;text-decoration:none;padding:12px 24px;border-radius:8px;">Reply to ${esc(d.name)}</a>
        </div>
      </td></tr>
    </table>
  </td></tr>
</table>`;
}

function leadAlertText(d: LeadMailData, when: string): string {
  return [
    `New demo request — ${d.company} (${d.industry})`,
    ``,
    `CONTACT`,
    `Name: ${d.name}`,
    `Company: ${d.company}`,
    `Email: ${d.email}`,
    d.phone ? `Phone: ${d.phone}${d.phoneCountry ? ` (${d.phoneCountry})` : ""}` : null,
    ``,
    `REQUIREMENT`,
    `Industry: ${d.industry}`,
    d.companySize ? `Size: ${d.companySize}` : null,
    `Interests: ${d.interests.length > 0 ? d.interests.join(", ") : "Not specified"}`,
    d.notes ? `Notes: "${d.notes}"` : null,
    ``,
    `Page: ${d.page} · ${when}`,
  ]
    .filter((l) => l !== null)
    .join("\n");
}

function prospectAckHtml(name: string, interests: string[]): string {
  const recap =
    interests.length > 0
      ? `<p style="margin:0 0 6px;font-size:14px;color:#334155;">You asked about: <strong>${esc(interests.join(", "))}</strong>.</p>`
      : "";
  return `
<table width="100%" cellpadding="0" cellspacing="0" style="font-family:Arial,Helvetica,sans-serif;background:#f1f5f9;padding:24px 0;">
  <tr><td align="center">
    <table width="600" cellpadding="0" cellspacing="0" style="background:#ffffff;border-radius:12px;overflow:hidden;max-width:600px;width:100%;">
      <tr><td style="background:#0b1b33;padding:20px 28px;">
        <div style="color:#7db4ff;font-size:11px;letter-spacing:2px;font-weight:bold;">MXERP</div>
        <div style="color:#ffffff;font-size:20px;font-weight:bold;margin-top:6px;">Thanks ${esc(name)} — request received</div>
      </td></tr>
      <tr><td style="padding:24px 28px;font-size:14px;color:#334155;line-height:1.6;">
        <p style="margin:0 0 12px;">Thank you for your interest in MxERP. A product specialist will contact you shortly to schedule a walkthrough of the modules that matter to you.</p>
        ${recap}
        <p style="margin:12px 0 0;">In the meantime, reach us any time:</p>
        <p style="margin:8px 0 0;">Phone: <a href="tel:+919818993537" style="color:#1d4ed8;">+91-9818993537</a><br/>
        Email: <a href="mailto:akg@acgil.net" style="color:#1d4ed8;">akg@acgil.net</a><br/>
        Office: H-107, Sector-63, Noida – 201301, UP, India</p>
        <p style="margin:16px 0 0;font-size:12px;color:#94a3b8;">— Team MxERP</p>
      </td></tr>
    </table>
  </td></tr>
</table>`;
}

/** Internal alert to sales. Never throws. */
export async function sendLeadAlert(d: LeadMailData): Promise<void> {
  try {
    if (isDuplicate(`lead:${d.email.toLowerCase()}:${d.company.toLowerCase()}`)) {
      return;
    }
    const t = getTransporter();
    const to = getReceivers();
    if (!t || to.length === 0) return;
    const when = new Date().toISOString();
    await t.sendMail({
      from: FROM_SITE,
      to: to.join(", "),
      replyTo: d.email,
      subject: `New demo request — ${d.company} (${d.industry})`,
      text: leadAlertText(d, when),
      html: leadAlertHtml(d, when),
    });
  } catch (e) {
    console.error("[mail] lead alert failed:", e);
    void logMailFailure("lead", e instanceof Error ? e.message : String(e));
  }
}

/** Auto-acknowledgement to the prospect. Never throws. */
export async function sendProspectAck(
  to: string,
  name: string,
  interests: string[]
): Promise<void> {
  try {
    if (isDuplicate(`ack:${to.toLowerCase()}`)) return;
    const t = getTransporter();
    if (!t || !to) return;
    const first = name.trim().split(/\s+/)[0] || name;
    await t.sendMail({
      from: FROM_SALES,
      to,
      subject: `Thanks ${first} — we've received your demo request`,
      text: `Hi ${first},\n\nThank you for your interest in MxERP. A product specialist will contact you shortly.\n\nPhone: +91-9818993537\nEmail: akg@acgil.net\nOffice: H-107, Sector-63, Noida - 201301, UP, India\n\n— Team MxERP`,
      html: prospectAckHtml(first, interests),
    });
  } catch (e) {
    console.error("[mail] prospect ack failed:", e);
    void logMailFailure("ack", e instanceof Error ? e.message : String(e));
  }
}

export type CallbackMailData = {
  name: string;
  phone: string;
  phoneCountry?: string;
  email?: string;
  industry?: string;
  slot: string;
};

/** Internal alert for callback requests. Never throws. */
export async function sendCallbackAlert(d: CallbackMailData): Promise<void> {
  try {
    if (isDuplicate(`cb:${d.phone.replace(/[\s-]/g, "")}`)) return;
    const t = getTransporter();
    const to = getReceivers();
    if (!t || to.length === 0) return;
    const when = new Date().toISOString();
    const telHref = `tel:+${d.phone.replace(/\D/g, "")}`;
    await t.sendMail({
      from: FROM_SITE,
      to: to.join(", "),
      subject: `New callback request — ${d.name} (${d.slot})`,
      text: `New callback request\n\nName: ${d.name}\nPhone: ${d.phone}${d.phoneCountry ? ` (${d.phoneCountry})` : ""}\n${d.email ? `Email: ${d.email}\n` : ""}${d.industry ? `Industry: ${d.industry}\n` : ""}Preferred time: ${d.slot}\nTime: ${when}\n\nCall now: ${telHref}`,
      html: `
<table width="100%" cellpadding="0" cellspacing="0" style="font-family:Arial,Helvetica,sans-serif;background:#f1f5f9;padding:24px 0;">
  <tr><td align="center">
    <table width="600" cellpadding="0" cellspacing="0" style="background:#ffffff;border-radius:12px;overflow:hidden;max-width:600px;width:100%;">
      <tr><td style="background:#0b1b33;padding:20px 28px;">
        <div style="color:#7db4ff;font-size:11px;letter-spacing:2px;font-weight:bold;">MXERP · CALLBACK</div>
        <div style="color:#ffffff;font-size:20px;font-weight:bold;margin-top:6px;">${esc(d.name)} asked for a call</div>
      </td></tr>
      <tr><td style="padding:24px 28px;font-size:14px;color:#0f172a;">
        <table width="100%" cellpadding="0" cellspacing="0">
          <tr><td style="padding:4px 0;color:#64748b;width:130px;">Phone</td><td style="padding:4px 0;font-weight:bold;"><a href="${esc(telHref)}" style="color:#1d4ed8;">${esc(d.phone)}</a>${d.phoneCountry ? ` <span style="color:#64748b;font-weight:normal;">(${esc(d.phoneCountry)})</span>` : ""}</td></tr>
          ${d.email ? `<tr><td style="padding:4px 0;color:#64748b;">Email</td><td style="padding:4px 0;"><a href="mailto:${esc(d.email)}" style="color:#1d4ed8;">${esc(d.email)}</a></td></tr>` : ""}
          ${d.industry ? `<tr><td style="padding:4px 0;color:#64748b;">Industry</td><td style="padding:4px 0;font-weight:bold;">${esc(d.industry)}</td></tr>` : ""}
          <tr><td style="padding:4px 0;color:#64748b;">Preferred time</td><td style="padding:4px 0;font-weight:bold;">${esc(d.slot)}</td></tr>
        </table>
        <div style="margin-top:16px;">
          <a href="${esc(telHref)}" style="display:inline-block;background:#1d4ed8;color:#ffffff;font-size:14px;font-weight:bold;text-decoration:none;padding:12px 24px;border-radius:8px;">Call ${esc(d.name)} now</a>
        </div>
        <div style="margin-top:16px;font-size:12px;color:#94a3b8;">${esc(when)}</div>
      </td></tr>
    </table>
  </td></tr>
</table>`,
    });
  } catch (e) {
    console.error("[mail] callback alert failed:", e);
    void logMailFailure("callback", e instanceof Error ? e.message : String(e));
  }
}

/** Newsletter subscriber notify. Never throws. */
export async function sendNewsletterNotify(email: string): Promise<void> {
  try {
    if (isDuplicate(`nl:${email.toLowerCase()}`)) return;
    const t = getTransporter();
    const to = getReceivers();
    if (!t || to.length === 0) return;
    await t.sendMail({
      from: FROM_SITE,
      to: to.join(", "),
      subject: `New newsletter subscriber — ${email}`,
      text: `New newsletter subscriber: ${email}\nTime: ${new Date().toISOString()}`,
      html: `<p style="font-family:Arial,Helvetica,sans-serif;font-size:14px;color:#0f172a;">New newsletter subscriber: <strong>${esc(email)}</strong><br/><span style="color:#64748b;font-size:12px;">${esc(new Date().toISOString())}</span></p>`,
    });
  } catch (e) {
    console.error("[mail] newsletter notify failed:", e);
    void logMailFailure("newsletter", e instanceof Error ? e.message : String(e));
  }
}
