"use server";

import { callbackSchema, leadSchema } from "@/lib/lead-schema";
import {
  sendCallbackAlert,
  sendLeadAlert,
  sendNewsletterNotify,
  sendProspectAck,
} from "@/lib/email";
import { appendFile, mkdir } from "node:fs/promises";
import path from "node:path";

export type LeadState = {
  ok: boolean;
  message: string;
  errors?: Record<string, string>;
};

// Simple in-memory rate limit (per server instance — replace with Redis later)
const hits = new Map<string, { count: number; ts: number }>();

/* Lead-store mode + Postgres migration contract (reliability docs, no behavior change).
 *
 * TODAY (file mode): leads append to data/*.jsonl (git-ignored, local disk).
 * Every lead is ALSO emailed to sales in real time — the inbox is an
 * independent second copy. Hourly off-machine backup of data/ is required;
 * /api/health "leads" check verifies writability.
 *
 * MIGRATION (when volume > ~50/day, serverless hosting, or CRM sync needed):
 *   env:      DATABASE_URL (Postgres; Neon/Supabase free tier suffices to start)
 *   table:    leads(id uuid pk, created_at timestamptz, source text,
 *             name text, company text, email citext, phone text,
 *             phone_country text, industry text, company_size text,
 *             interests text[], notes text, slot text, consent_at timestamptz)
 *   rule:     write DB first, keep JSONL append as fallback until the DB path
 *             is proven in production; never remove the real-time sales email.
 */
const LEAD_STORE_MODE = "file:data/*.jsonl";
if (typeof process !== "undefined" && process.env.NEXT_RUNTIME !== "edge") {
  console.log(`[leads] store mode: ${LEAD_STORE_MODE}`);
}

export async function submitLead(
  _prev: LeadState,
  formData: FormData
): Promise<LeadState> {
  const raw = {
    name: String(formData.get("name") ?? ""),
    company: String(formData.get("company") ?? ""),
    email: String(formData.get("email") ?? ""),
    phone: String(formData.get("phone") ?? ""),
    industry: String(formData.get("industry") ?? ""),
    phoneCountry: String(formData.get("phoneCountry") ?? ""),
    companySize: String(formData.get("companySize") ?? "").trim(),
    interests: formData
      .getAll("interests")
      .map((v) => String(v).trim())
      .filter(Boolean),
    notes: String(formData.get("notes") ?? "").trim(),
    consent: formData.get("consent") === "on" ? true : undefined,
    website: String(formData.get("website") ?? ""),
  };

  // Honeypot
  if (raw.website) {
    return { ok: true, message: "Thanks! We will be in touch shortly." };
  }

  const parsed = leadSchema.safeParse(raw);
  if (!parsed.success) {
    const errors: Record<string, string> = {};
    for (const issue of parsed.error.issues) {
      const key = String(issue.path[0] ?? "form");
      if (!errors[key]) errors[key] = issue.message;
    }
    return { ok: false, message: "Please fix the highlighted fields.", errors };
  }

  const ip = "local";
  const now = Date.now();
  const entry = hits.get(ip);
  if (entry && now - entry.ts < 60_000 && entry.count >= 5) {
    return { ok: false, message: "Too many requests. Please try again in a minute." };
  }
  hits.set(ip, { count: (entry?.count ?? 0) + 1, ts: entry ? entry.ts : now });

  // v1 local persistence — replace with Postgres + SES + CRM later (no deploy for now)
  try {
    const dir = path.join(process.cwd(), "data");
    await mkdir(dir, { recursive: true });
    const row = JSON.stringify({
      ...parsed.data,
      page: "/",
      ts: new Date().toISOString(),
    });
    await appendFile(path.join(dir, "leads.jsonl"), row + "\n", "utf8");
  } catch {
    // Do not fail the UX on local persistence errors
  }

  // Notify sales + acknowledge prospect — fire and forget, never fail UX
  const lead = parsed.data;
  void Promise.allSettled([
    sendLeadAlert({
      name: lead.name,
      company: lead.company,
      email: lead.email,
      phone: lead.phone || undefined,
      phoneCountry: lead.phoneCountry || undefined,
      industry: lead.industry,
      companySize: lead.companySize,
      interests: lead.interests ?? [],
      notes: lead.notes,
      page: "/",
    }),
    sendProspectAck(lead.email, lead.name, lead.interests ?? []),
  ]);

  return { ok: true, message: "Thanks! A product specialist will contact you shortly." };
}

export async function subscribeNewsletter(
  _prev: LeadState,
  formData: FormData
): Promise<LeadState> {
  const email = String(formData.get("email") ?? "").trim().toLowerCase();
  if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
    return { ok: false, message: "Please enter a valid email address." };
  }
  try {
    const dir = path.join(process.cwd(), "data");
    await mkdir(dir, { recursive: true });
    await appendFile(
      path.join(dir, "newsletter.jsonl"),
      JSON.stringify({ email, ts: new Date().toISOString() }) + "\n",
      "utf8"
    );
  } catch {
    /* ignore local persistence errors */
  }
  void sendNewsletterNotify(email);
  return { ok: true, message: "Subscribed! One email a month, no spam." };
}

export async function requestCallback(
  _prev: LeadState,
  formData: FormData
): Promise<LeadState> {
  const raw = {
    name: String(formData.get("name") ?? ""),
    phone: String(formData.get("phone") ?? ""),
    phoneCountry: String(formData.get("phoneCountry") ?? ""),
    email: String(formData.get("email") ?? "").trim(),
    industry: String(formData.get("industry") ?? ""),
    slot: String(formData.get("slot") ?? ""),
    consent: formData.get("consent") === "on" ? true : undefined,
    website: String(formData.get("website") ?? ""),
  };

  // Honeypot
  if (raw.website) {
    return { ok: true, message: "Thanks! We will call you back shortly." };
  }

  const parsed = callbackSchema.safeParse(raw);
  if (!parsed.success) {
    const errors: Record<string, string> = {};
    for (const issue of parsed.error.issues) {
      const key = String(issue.path[0] ?? "form");
      if (!errors[key]) errors[key] = issue.message;
    }
    return { ok: false, message: "Please fix the highlighted fields.", errors };
  }

  const ip = "local";
  const now = Date.now();
  const entry = hits.get(ip);
  if (entry && now - entry.ts < 60_000 && entry.count >= 5) {
    return { ok: false, message: "Too many requests. Please try again in a minute." };
  }
  hits.set(ip, { count: (entry?.count ?? 0) + 1, ts: entry ? entry.ts : now });

  try {
    const dir = path.join(process.cwd(), "data");
    await mkdir(dir, { recursive: true });
    await appendFile(
      path.join(dir, "callbacks.jsonl"),
      JSON.stringify({ ...parsed.data, ts: new Date().toISOString() }) + "\n",
      "utf8"
    );
  } catch {
    /* ignore local persistence errors */
  }

  const cb = parsed.data;
  void sendCallbackAlert({
    name: cb.name,
    phone: cb.phone,
    phoneCountry: cb.phoneCountry || undefined,
    email: cb.email || undefined,
    industry: cb.industry,
    slot: cb.slot,
  });

  return { ok: true, message: `Thanks ${cb.name.trim().split(/\s+/)[0]}! We will call you ${cb.slot === "As soon as possible" ? "back shortly" : `in the ${cb.slot.split(" ")[0].toLowerCase()}`}.` };
}
