import type { AdminState, EmailNurtureKind, EmailNurtureStepKey, LeadEvent } from "./mpc-types";
import { getAdminState, saveAdminState, updateLeadEvent } from "./admin-store";
import { sendSmtpMail, type SmtpSendResult } from "./email";

const defaultReplyTo = "contact@marlothparkcentral.com";
const backfillMaxDays = Number(process.env.MPC_NURTURE_BACKFILL_MAX_DAYS || 14);
const nurtureDisabled = String(process.env.MPC_NURTURE_EMAILS_ENABLED || "true").toLowerCase() === "false";

const stepOffsets: Record<EmailNurtureStepKey, number> = { day1: 1, day3: 3, day7: 7 };

function siteUrl(state: AdminState) {
  return (state.siteSettings.siteUrl || process.env.NEXT_PUBLIC_SITE_URL || "https://marlothparkcentral.com").replace(/\/$/, "");
}

function primaryEmail(state: AdminState) {
  return state.integrations.guideDeliveryReplyToEmail || state.integrations.notificationEmail || state.siteSettings.partnerEmail || defaultReplyTo;
}

function addDays(iso: string, days: number) {
  const date = new Date(iso || Date.now());
  if (Number.isNaN(date.getTime())) return new Date(Date.now() + days * 86400000).toISOString();
  date.setUTCDate(date.getUTCDate() + days);
  return date.toISOString();
}

function cleanName(lead: LeadEvent) {
  return (lead.contactName || "there").trim().split(/\s+/).slice(0, 2).join(" ") || "there";
}

export function classifyNurtureKind(lead: LeadEvent): EmailNurtureKind | null {
  const text = `${lead.buttonType || ""} ${lead.source || ""} ${lead.category || ""} ${lead.page || ""}`.toLowerCase();
  if (lead.guideSlug || lead.guideTitle || text.includes("free-guide") || text.includes("guide-delivery")) return "free-guide";
  if (lead.routePackId || lead.routePackTitle || text.includes("route") || text.includes("manual-order")) return "route-pack";
  if (lead.accommodationName || lead.accommodationId || text.includes("accommodation-enquiry")) return "accommodation-help";
  if (text.includes("stay")) return "stay";
  if (text.includes("contact-property") || text.includes("property-application") || text.includes("listing-onboarding")) return "listing-onboarding";
  if (text.includes("business") || text.includes("supplier") || text.includes("biz")) return "business-onboarding";
  if (text.includes("contact") || text.includes("email-message")) return "accommodation-help";
  return null;
}

export function buildNurtureState(lead: LeadEvent, kind = classifyNurtureKind(lead)) {
  if (!kind || !lead.contactValue) return undefined;
  const createdAt = lead.receivedAt || new Date().toISOString();
  return {
    kind,
    enabled: true,
    createdAt,
    updatedAt: new Date().toISOString(),
    steps: {
      day1: { key: "day1" as const, scheduledFor: addDays(createdAt, stepOffsets.day1) },
      day3: { key: "day3" as const, scheduledFor: addDays(createdAt, stepOffsets.day3) },
      day7: { key: "day7" as const, scheduledFor: addDays(createdAt, stepOffsets.day7) },
    },
  };
}

export async function queueNurtureForLead(lead: LeadEvent, kind?: EmailNurtureKind) {
  const existing = lead.nurture;
  if (existing?.enabled && existing.steps?.day1?.scheduledFor) return lead;
  const nurture = buildNurtureState(lead, kind || classifyNurtureKind(lead));
  if (!nurture) return lead;
  return updateLeadEvent(lead.id, { nurture, nurtureStatus: `Nurture queued at ${new Date().toISOString()}` } as Partial<LeadEvent>);
}

function stopStatus(lead: LeadEvent) {
  return ["closed", "booked", "not-available"].includes(String(lead.status || "").toLowerCase());
}

function shouldBackfill(lead: LeadEvent) {
  const received = new Date(lead.receivedAt || "").getTime();
  if (!received) return false;
  return (Date.now() - received) / 86400000 <= backfillMaxDays;
}

function subjectFor(kind: EmailNurtureKind, step: EmailNurtureStepKey, lead: LeadEvent) {
  const ref = lead.leadCode ? ` (${lead.leadCode})` : "";
  if (step === "day1") {
    if (kind === "free-guide") return `Your Marloth/Kruger planning next step${ref}`;
    if (kind === "stay") return `Your stay enquiry: what to confirm next${ref}`;
    if (kind === "route-pack") return `Your route planning request: next step${ref}`;
    if (kind === "accommodation-help") return `Accommodation help: what to check next${ref}`;
    if (kind === "business-onboarding") return `Your MPC business listing request: next step${ref}`;
    return `Your MPC property listing request: next step${ref}`;
  }
  if (step === "day3") {
    if (kind === "free-guide") return "Need help choosing your Kruger route?";
    if (kind === "stay" || kind === "accommodation-help") return "Still looking for the right Marloth stay?";
    if (kind === "business-onboarding") return "MPC business listing: strengthen your profile";
    if (kind === "listing-onboarding") return "MPC property listing: photos and enquiry setup";
    return "Need help choosing your route plan?";
  }
  if (kind === "business-onboarding") return "MPC business listing: ready for visitor leads?";
  if (kind === "listing-onboarding") return "MPC property listing: ready to go live?";
  if (kind === "stay" || kind === "accommodation-help") return "Still looking for accommodation in Marloth Park?";
  if (kind === "free-guide") return "Still planning your Marloth and Kruger trip?";
  return "Still planning your Marloth/Kruger route?";
}

export function bodyFor(state: AdminState, kind: EmailNurtureKind, step: EmailNurtureStepKey, lead: LeadEvent) {
  const url = siteUrl(state);
  const name = cleanName(lead);
  const ref = lead.leadCode ? `\nReference: ${lead.leadCode}` : "";
  const routeTitle = lead.routePackTitle || lead.guideTitle || "your MPC request";
  const accommodation = lead.accommodationName || lead.stayingAt || "your Marloth stay";
  const commonFooter = [
    "",
    "Helpful MPC links:",
    `${url}/free-guides`,
    `${url}/route-packs`,
    `${url}/accommodation`,
    "",
    "Marloth Park Central",
  ].join("\n");

  if (step === "day1") {
    if (kind === "free-guide") return [`Hi ${name},`, "", "Here is the best next step after requesting your MPC Visitor Guide Set:", "", "1. Confirm your arrival day and Crocodile Bridge timing.", "2. Decide whether you need a simple first-day Kruger route or a broader planning pack.", "3. Keep emergency, gate and local-supply information easy to find before you travel.", ref, commonFooter].join("\n");
    if (kind === "stay") return [`Hi ${name},`, "", `MPC has your stay enquiry for ${accommodation}.`, "", "Before you decide, confirm dates, visitor group size, arrival time, payment terms, cancellation terms and whether linen, stay care, braai facilities and backup power fit your trip.", ref, commonFooter].join("\n");
    if (kind === "route-pack") return [`Hi ${name},`, "", `MPC has your route-planning interest for ${routeTitle}.`, "", "Next practical step: confirm which gate you will use, where you sleep the night before, how early you can leave, and whether you prefer a relaxed or higher-activity route.", ref, commonFooter].join("\n");
    if (kind === "business-onboarding") return [`Hi ${name},`, "", "MPC received your local business listing request.", "", "Next practical step: prepare your best public contact details, service area, opening/delivery notes, payment options, and one strong landscape WebP image for the listing.", ref, `${url}/advertise-local-business`, "", "Marloth Park Central"].join("\n");
    if (kind === "listing-onboarding") return [`Hi ${name},`, "", "MPC received your property listing request.", "", "Next practical step: prepare 8–12 clear WebP property photos, visitor capacity, bedroom/bathroom counts, booking rules, rates guidance, and the best enquiry routing email/WhatsApp.", ref, `${url}/list-your-marloth-property`, "", "Marloth Park Central"].join("\n");
    return [`Hi ${name},`, "", "MPC received your accommodation help request.", "", "Next practical step: confirm travel dates, visitor group size, budget range, access needs, pet/child requirements and whether you want direct-contact or MPC-assisted enquiry support.", ref, commonFooter].join("\n");
  }

  if (step === "day3") {
    if (kind === "business-onboarding") return [`Hi ${name},`, "", "A stronger MPC business listing normally includes clear services, featured contact details, service area, delivery/collection notes, payment options and an image that helps visitors trust the business quickly.", "", "Reply with missing details when ready.", ref, "", "Marloth Park Central"].join("\n");
    if (kind === "listing-onboarding") return [`Hi ${name},`, "", "For accommodation listings, photos and enquiry routing are the two biggest setup items. Clear images and the correct recipient reduce back-and-forth and help MPC send better visitor enquiries.", "", "Reply with missing details when ready.", ref, "", "Marloth Park Central"].join("\n");
    return [`Hi ${name},`, "", "Need help choosing your Kruger route or Marloth planning option?", "", "A simple way to decide is to start with your gate, travel month, available time, confidence level and whether this is your first Kruger day or a repeat visit.", ref, commonFooter].join("\n");
  }

  if (kind === "business-onboarding") return [`Hi ${name},`, "", "Final follow-up from MPC on your business listing request.", "", "Once your details are complete, MPC can review the listing and prepare it for the most suitable category or clear visibility option.", ref, "", "Marloth Park Central"].join("\n");
  if (kind === "listing-onboarding") return [`Hi ${name},`, "", "Final follow-up from MPC on your property listing request.", "", "Once your photos, details, package choice and enquiry routing are confirmed, MPC can prepare the listing for approval and publishing.", ref, "", "Marloth Park Central"].join("\n");
  return [`Hi ${name},`, "", "Still planning your Marloth Park or Kruger trip?", "", "MPC can still help with route choice, accommodation direction, local supplies and visitor planning. Use the MPC links below or reply with what you still need to solve.", ref, commonFooter].join("\n");
}

async function sendNurtureEmail(state: AdminState, lead: LeadEvent, kind: EmailNurtureKind, step: EmailNurtureStepKey): Promise<SmtpSendResult> {
  return sendSmtpMail({
    to: lead.contactValue || "",
    subject: subjectFor(kind, step, lead),
    text: bodyFor(state, kind, step, lead),
    replyTo: primaryEmail(state),
  }, { profile: kind === "free-guide" ? "guides" : "enquiries" });
}

export async function runDueNurtureEmails(options: { dryRun?: boolean; limit?: number; now?: Date } = {}) {
  const now = options.now || new Date();
  const limit = Math.max(1, Math.min(Number(options.limit || process.env.MPC_NURTURE_SEND_LIMIT || 25), 100));
  const state = await getAdminState();
  const processed: Array<{ leadId: string; leadCode?: string; step: string; status: string; sent: boolean; skipped?: boolean }> = [];
  let sentCount = 0;
  let changed = false;
  const leads = [...(state.leadEvents || [])];

  for (const lead of leads) {
    if (sentCount >= limit) break;
    if (!lead.contactValue || stopStatus(lead)) continue;
    let nurture = lead.nurture;
    if (!nurture?.kind || !nurture.steps) {
      if (!shouldBackfill(lead)) continue;
      nurture = buildNurtureState(lead);
      if (!nurture) continue;
      lead.nurture = nurture;
      changed = true;
    }
    if (nurtureDisabled || nurture.enabled === false) continue;
    const kind = nurture.kind;
    for (const step of ["day1", "day3", "day7"] as EmailNurtureStepKey[]) {
      if (sentCount >= limit) break;
      const existingStep = nurture.steps[step];
      if (!existingStep?.scheduledFor || existingStep.sentAt) continue;
      if (new Date(existingStep.scheduledFor).getTime() > now.getTime()) continue;
      if (options.dryRun) {
        processed.push({ leadId: lead.id, leadCode: lead.leadCode, step, status: "due", sent: false });
        continue;
      }
      const result = await sendNurtureEmail(state, lead, kind, step);
      nurture.steps[step] = { ...existingStep, attempts: (existingStep.attempts || 0) + 1, lastStatus: result.status };
      lead.nurtureStatus = result.status;
      lead.lastNurtureStatus = result.status;
      lead.updatedAt = new Date().toISOString();
      if (result.ok) {
        nurture.steps[step].sentAt = new Date().toISOString();
        sentCount += 1;
      }
      processed.push({ leadId: lead.id, leadCode: lead.leadCode, step, status: result.status, sent: result.ok, skipped: result.skipped });
      changed = true;
    }
    if (nurture) nurture.updatedAt = new Date().toISOString();
  }

  if (changed && !options.dryRun) {
    state.leadEvents = leads;
    state.integrations.lastEmailStatus = `Nurture runner processed ${processed.length} item(s), sent ${sentCount} at ${new Date().toISOString()}`;
    await saveAdminState(state);
  }

  return { ok: true, dryRun: Boolean(options.dryRun), processed, sentCount, limit, checkedLeadCount: leads.length };
}
