"use client";

import React, { Suspense, useEffect, useMemo, useState } from "react";
import { useAuth } from "@/hooks/useAuth";
import { useRouter, useSearchParams } from "next/navigation";
import { apiFetch, fetchAllUsers } from "@/lib/api";
import { useDismissingState } from "@/hooks/useDismissingState";
import { Mail } from "lucide-react";

type Attendee = { id: string; name: string; email: string; pref: string };

export default function EmailAttendeesPage() {
  return (
    <Suspense fallback={<div className="p-6">Loading...</div>}>
      <EmailAttendeesPageInner />
    </Suspense>
  );
}

function AttendeesCheckboxDropdown({
  attendees,
  loading,
  selectedIds,
  onChange,
  channel = "email",
}: {
  attendees: { id: string; name: string; email?: string; pref: string }[];
  loading: boolean;
  selectedIds: string[];
  onChange: (ids: string[]) => void;
  channel?: "email" | "whatsapp";
}) {
  const [open, setOpen] = useState(false);

  const allIds = useMemo(() => attendees.map(a => a.id), [attendees]);
  const allSelected = selectedIds.length > 0 && selectedIds.length === allIds.length;
  const noneSelected = selectedIds.length === 0;

  const prefMatch = (pref: string) =>
    channel === "email" ? pref === "email" || pref === "both" : pref === "whatsapp" || pref === "both";

  const prefLabel = (pref: string) => {
    if (pref === "both") return "both";
    if (pref === "whatsapp") return "WA";
    if (pref === "email") return "email";
    return pref || "email";
  };

  const mismatched = selectedIds.filter(id => {
    const a = attendees.find(x => x.id === id);
    return a && !prefMatch(a.pref);
  });

  const toggleAll = (checked: boolean) => onChange(checked ? allIds : []);
  const toggleId = (id: string) => {
    if (selectedIds.includes(id)) onChange(selectedIds.filter(x => x !== id));
    else onChange([...selectedIds, id]);
  };

  const summary = loading
    ? "Loading attendees…"
    : attendees.length === 0
      ? "No attendees"
      : allSelected
        ? `All attendees (${attendees.length})`
        : noneSelected
          ? "None selected"
          : `${selectedIds.length} selected`;

  return (
    <div className="relative block w-full max-w-xs">
      <button type="button" className="w-full border rounded px-3 py-2 text-sm bg-white hover:bg-gray-50 text-left" onClick={() => setOpen(o => !o)}>
        {summary}
        {mismatched.length > 0 && (
          <span className="ml-2 text-xs text-amber-600">({mismatched.length} pref mismatch)</span>
        )}
      </button>
      {open && (
        <div className="absolute z-10 mt-1 left-0 right-0 max-h-72 overflow-auto bg-white border rounded shadow">
          <div className="px-3 py-2 border-b sticky top-0 bg-white space-y-1">
            <label className="text-sm flex items-center gap-2">
              <input type="checkbox" checked={allSelected} onChange={e => toggleAll(e.target.checked)} />
              <span className="font-medium">Select all</span>
            </label>
            <div className="flex gap-1 flex-wrap">
              <button
                type="button"
                className="text-xs px-2 py-0.5 rounded border border-brand-300 text-brand-700 hover:bg-brand-50"
                onClick={() => onChange(attendees.filter(a => prefMatch(a.pref)).map(a => a.id))}
              >
                Select {channel === "email" ? "Email/both" : "WhatsApp/both"}
              </button>
              <button
                type="button"
                className="text-xs px-2 py-0.5 rounded border border-gray-300 text-gray-600 hover:bg-gray-50"
                onClick={() => onChange([])}
              >
                Clear
              </button>
            </div>
          </div>
          {loading ? (
            <div className="px-3 py-2 text-sm text-gray-500">Loading…</div>
          ) : attendees.length === 0 ? (
            <div className="px-3 py-2 text-sm text-gray-500">No attendees found</div>
          ) : (
            <ul className="py-1">
              {attendees.map(a => {
                const checked = selectedIds.includes(a.id);
                const match = prefMatch(a.pref);
                return (
                  <li key={a.id} className={`px-3 py-1 hover:bg-gray-50 ${!match ? "opacity-75" : ""}`}>
                    <label className="flex items-center gap-2 text-sm min-w-0">
                      <input type="checkbox" checked={checked} onChange={() => toggleId(a.id)} />
                      <span className="truncate flex-1">
                        {a.name ? `${a.name} <${a.email}>` : a.email}
                      </span>
                      <span className={`text-[10px] px-1 rounded shrink-0 ${match ? "text-brand-700 bg-brand-50" : "text-amber-700 bg-amber-50"}`}>
                        {prefLabel(a.pref)}
                      </span>
                    </label>
                  </li>
                );
              })}
            </ul>
          )}
          <div className="px-3 py-2 border-t bg-gray-50 text-right">
            <button type="button" className="px-2 py-1 text-xs rounded border bg-white hover:bg-gray-100" onClick={() => setOpen(false)}>Done</button>
          </div>
        </div>
      )}
    </div>
  );
}

function PrefWarning({ attendees, selectedIds, channel }: { attendees: { id: string; pref: string }[]; selectedIds: string[]; channel: "email" | "whatsapp" }) {
  const prefMatch = (pref: string) =>
    channel === "email" ? pref === "email" || pref === "both" : pref === "whatsapp" || pref === "both";

  const mismatched = useMemo(
    () => selectedIds.filter(id => {
      const a = attendees.find(x => x.id === id);
      return a && !prefMatch(a.pref);
    }),
    [attendees, selectedIds, channel]
  );

  if (mismatched.length === 0) return null;
  return (
    <div className="p-3 border rounded bg-amber-50 text-amber-800 text-xs">
      <strong>{mismatched.length} selected attendee(s)</strong> have a notification preference that doesn&apos;t include{" "}
      {channel === "email" ? "email" : "WhatsApp"}. They will still receive the message, but it may not be their preferred channel.
      {" "}Use the dropdown to filter by preference.
    </div>
  );
}

function EmailAttendeesPageInner() {
  const { user, loading, token } = useAuth();
  const router = useRouter();
  const search = useSearchParams();
  const preselectEventId = search?.get("eventId") || "";

  const canView = useMemo(() => {
    const role = user?.role;
    return role === "admin" || role === "supervisor";
  }, [user]);

  useEffect(() => {
    if (loading) return;
    if (!user) router.replace("/login");
  }, [user, loading, router]);

  // Load events for selection
  const [loadingEvents, setLoadingEvents] = useState(false);
  const [error, setError] = useDismissingState<string | null>(null);
  const [info, setInfo] = useDismissingState<string | null>(null);

  // Tabs: attendees (current), automations (coming soon), broadcasts
  const [tab, setTab] = useState<'attendees'|'automations'|'broadcasts'|'scheduled'>('attendees');

  const isAdmin = user?.role === "admin";

  const [allEvents, setAllEvents] = useState<any[]>([]);
  const [evIncludePast, setEvIncludePast] = useState(false);

  const events = useMemo(() => {
    const now = Date.now();
    if (evIncludePast) return allEvents;
    return allEvents.filter(ev => {
      const t = new Date(ev.endDate).getTime();
      return !isNaN(t) && t > now;
    });
  }, [allEvents, evIncludePast]);

  const loadEvents = async () => {
    try {
      setLoadingEvents(true);
      const evs = await apiFetch<any[]>("/api/events/all?includePast=true", { authToken: token || undefined });
      const sorted = (evs || []).sort((a: any, b: any) => new Date(a.startDate).getTime() - new Date(b.startDate).getTime());
      setAllEvents(sorted);
    } catch (e: any) {
      setError(e?.message || "Failed to load events");
    } finally {
      setLoadingEvents(false);
    }
  };

  useEffect(() => { loadEvents(); }, [user, token]);

  // Load users for broadcasts
  useEffect(() => {
    const run = async () => {
      try {
        if (!token) return;
        setLoadingUsers(true);
        const allUsers = await fetchAllUsers(token);
        const mapped = allUsers
          .filter((u: any) => u.isActive !== false && !u.email?.endsWith('@guest.local'))
          .map((u: any) => ({ id: u.id, name: u.name || '', email: u.email || '', pref: u.notificationPreference || 'email' }))
          .sort((a: any, b: any) => (a.name || '').localeCompare(b.name || '', undefined, { sensitivity: 'base' }));
        setUsers(mapped);
      } catch (e) {
        // ignore for now
      } finally {
        setLoadingUsers(false);
      }
    };
    run();
  }, [token]);

  // Form state
  const [eventId, setEventId] = useState<string>(preselectEventId);
  useEffect(() => {
    if (preselectEventId) setEventId(preselectEventId);
  }, [preselectEventId]);

  const [templateKey, setTemplateKey] = useState<'custom'|'payment_reminder'|'event_reminder'|'tickets'>('custom');
  const [showInfo, setShowInfo] = useState(false);

  // Broadcasts state
  const [users, setUsers] = useState<{id:string;name:string;email:string;pref:string}[]>([]);
  const [loadingUsers, setLoadingUsers] = useState(false);
  const [selectedUserIds, setSelectedUserIds] = useState<string[]>([]);
  const [broadcastEventId, setBroadcastEventId] = useState<string>("");
  const [broadcastSubject, setBroadcastSubject] = useState("");
  const [broadcastBody, setBroadcastBody] = useState("");
  const [broadcastEmails, setBroadcastEmails] = useState("");
  const [broadcastPreviewCount, setBroadcastPreviewCount] = useState<number|null>(null);
  const [broadcastPreviewSample, setBroadcastPreviewSample] = useState<{email:string;name?:string}[]|null>(null);
  const [broadcastScheduledAtLocal, setBroadcastScheduledAtLocal] = useState<string>("");
  const resetBroadcastForm = () => {
    setSelectedUserIds([]);
    setBroadcastEventId("");
    setBroadcastSubject("");
    setBroadcastBody("");
    setBroadcastEmails("");
    setBroadcastPreviewCount(null);
    setBroadcastPreviewSample(null);
    setBroadcastScheduledAtLocal("");
  };

  // Scheduled jobs state
  type ScheduledJob = { id: string; kind: 'attendees'|'broadcast'|'unknown'; eventId?: string|null; broadcast?: boolean; scheduledAt: string; createdAt: string; status: 'queued'|'sending'|'sent'|'error'; attempts: number; sentAt?: string|null; lastError?: string|null; subject?: string; hasHtml?: boolean; hasText?: boolean };
  const [scheduled, setScheduled] = useState<ScheduledJob[]>([]);
  const [loadingScheduled, setLoadingScheduled] = useState(false);
  const [editing, setEditing] = useState<ScheduledJob | null>(null);
  const [editSubject, setEditSubject] = useState<string>('');
  const [editBody, setEditBody] = useState<string>('');
  const [editWhen, setEditWhen] = useState<string>('');
  const [savingEdit, setSavingEdit] = useState(false);

  const loadScheduled = async () => {
    try {
      if (!token) return;
      setLoadingScheduled(true);
      const res = await apiFetch<{jobs: ScheduledJob[]}>(`/api/scheduled-emails`, { authToken: token });
      setScheduled(Array.isArray(res?.jobs) ? res.jobs : []);
    } catch (e) {
      // ignore here; surfaces via UI when tab open
    } finally {
      setLoadingScheduled(false);
    }
  };

  useEffect(() => { if (tab === 'scheduled') loadScheduled(); }, [tab, token]);

  const openEdit = (job: ScheduledJob) => {
    setEditing(job);
    setEditSubject(job.subject || '');
    setEditBody(''); // body not included in list; will let user set a new one if needed
    try { setEditWhen(toLocalInputValue(new Date(job.scheduledAt))); } catch { setEditWhen(''); }
  };

  const saveEdit = async () => {
    if (!editing) return;
    try {
      setSavingEdit(true);
      if (!token) { setError('Not authenticated'); return; }
      const body: any = {};
      if (editWhen) body.scheduledAt = new Date(editWhen).toISOString();
      if (editSubject.trim().length || editBody.trim().length) {
        body.subject = editSubject;
        if (editBody.trim()) {
          if (editBody.trim().startsWith('<')) body.html = editBody; else body.text = editBody;
        } else {
          // if clearing body, explicitly set text to empty to override
          body.text = '';
          body.html = '';
        }
      }
      await apiFetch(`/api/scheduled-emails/${encodeURIComponent(editing.id)}`, { method: 'PATCH', authToken: token, body });
      setInfo('Scheduled email updated.');
      setEditing(null);
      loadScheduled();
    } catch (e:any) {
      setError(e?.message || 'Failed to update scheduled email');
    } finally {
      setSavingEdit(false);
    }
  };

  const removeJob = async (job: ScheduledJob) => {
    try {
      if (!token) { setError('Not authenticated'); return; }
      await apiFetch(`/api/scheduled-emails/${encodeURIComponent(job.id)}`, { method: 'DELETE', authToken: token });
      setInfo('Scheduled email removed.');
      loadScheduled();
    } catch (e:any) {
      setError(e?.message || 'Failed to remove scheduled email');
    }
  };

  const [subject, setSubject] = useState("");
  const [body, setBody] = useState("");
  const [subjectDirty, setSubjectDirty] = useState(false);
  const [bodyDirty, setBodyDirty] = useState(false);
  const [status, setStatus] = useState<'any'|'paid'|'unpaid'|'partial_paid'|'cancelled'>("any");
  // Attendees list and selection
  const [attendees, setAttendees] = useState<Attendee[]>([]);
  const [selectedAttendeeIds, setSelectedAttendeeIds] = useState<string[]>([]);
  const [loadingAttendees, setLoadingAttendees] = useState(false);

  // Event helper to prefill templates
  const currentEvent = useMemo(() => (events || []).find(e => e.id === eventId), [events, eventId]);

  useEffect(() => {
    const title = currentEvent?.title || 'the event';
    if (templateKey === 'payment_reminder') {
      if (!subjectDirty) setSubject(`Payment reminder: ${title}`);
      if (!bodyDirty) setBody(`Hi {{name}}\n\nThis is a friendly reminder that you have an outstanding balance of {{balance}} for {{event.title}}.\nEvent starts: {{event.start}}\n\nPlease settle your balance to secure your tickets. Thank you!`);
    } else if (templateKey === 'event_reminder') {
      if (!subjectDirty) setSubject(`Reminder: ${title}`);
      if (!bodyDirty) setBody(`Hi {{name}}\n\nA quick reminder about {{event.title}}.\nStart: {{event.start}}\n\nWe look forward to seeing you!`);
    } else if (templateKey === 'tickets') {
      // Tickets template does not require subject/body
      setSubjectDirty(false);
      setBodyDirty(false);
      setSubject('');
      setBody('');
    } else {
      // custom: do not overwrite user content unless not dirty and we have event change
      if (!subjectDirty && subject) setSubject(subject); // keep as-is
      if (!bodyDirty && body) setBody(body);
    }
    // When event changes, refresh defaults if not dirty
  }, [templateKey, currentEvent, subjectDirty, bodyDirty]);

  const [previewCount, setPreviewCount] = useState<number | null>(null);
  const [previewSample, setPreviewSample] = useState<{email:string;name?:string}[] | null>(null);
  const [sending, setSending] = useState(false);
  const [scheduledAtLocal, setScheduledAtLocal] = useState<string>("");

  const mismatchedAttendees = useMemo(
    () => selectedAttendeeIds.filter(id => {
      const a = attendees.find(x => x.id === id);
      return a && a.pref !== 'email' && a.pref !== 'both';
    }),
    [attendees, selectedAttendeeIds]
  );

  // Load attendees when event changes
  useEffect(() => {
    const run = async () => {
      try {
        setLoadingAttendees(true);
        setAttendees([]);
        setSelectedAttendeeIds([]);
        if (!eventId || !token) return;
        const regs = await apiFetch<any[]>(`/api/registrations/event/${encodeURIComponent(eventId)}`, { authToken: token });
        const uniq = new Map<string, Attendee>();
        (regs || []).forEach((r: any) => {
          const u = r?.user;
          if (u?.id && u?.email && !u.email.endsWith('@guest.local') && u.isActive !== false) {
            uniq.set(u.id, { id: u.id, name: u.name || '', email: u.email || '', pref: u.notificationPreference || 'email' });
          }
        });
        const list = Array.from(uniq.values()).sort((a,b) => (a.name || '').localeCompare(b.name || '', undefined, { sensitivity: 'base' }));
        setAttendees(list);
        // Default: select those with email/both preference; fall back to all
        const matching = list.filter(a => a.pref === 'email' || a.pref === 'both').map(a => a.id);
        setSelectedAttendeeIds(matching.length > 0 ? matching : list.map(a => a.id));
      } catch (e) {
        // ignore
      } finally {
        setLoadingAttendees(false);
      }
    };
    run();
  }, [eventId, token]);

  const onPreview = async () => {
    try {
      setError(null); setInfo(null); setPreviewCount(null); setPreviewSample(null);
      if (!token) { setError("Not authenticated"); return; }
      if (!eventId) { setError("Please select an event"); return; }
      if (templateKey !== 'tickets') {
        if (!subject.trim()) { setError("Subject is required"); return; }
        if (!body.trim()) { setError("Message is required"); return; }
      }
      const payload: any = {
        subject: subject || "(no subject)",
        filter: { status: status !== 'any' ? status : undefined, attendeeIds: selectedAttendeeIds && selectedAttendeeIds.length ? selectedAttendeeIds : undefined },
        dryRun: true,
        template: templateKey,
      };
      if (templateKey !== 'tickets') {
        if (body.trim().startsWith('<')) payload.html = body; else payload.text = body;
      }
      const res = await apiFetch(`/api/events/${encodeURIComponent(eventId)}/email-attendees`, { method: 'POST', authToken: token, body: payload });
      setPreviewCount(res?.matched ?? 0);
      setPreviewSample(Array.isArray(res?.recipients) ? res.recipients : null);
      setInfo(`Matched ${res?.matched ?? 0} recipient(s).`);
    } catch (e: any) {
      setError(e?.message || 'Failed to preview recipients');
    }
  };

  const resetAttendeesForm = () => {
    setTemplateKey('custom');
    setSubject(''); setBody('');
    setSubjectDirty(false); setBodyDirty(false);
    setStatus('any');
    setScheduledAtLocal('');
    setPreviewCount(null); setPreviewSample(null);
    // Keep event selection but reselect email/both attendees
    const matching = attendees.filter(a => a.pref === 'email' || a.pref === 'both').map(a => a.id);
    setSelectedAttendeeIds(matching.length > 0 ? matching : attendees.map(a => a.id));
  };

  const onSend = async () => {
    try {
      setError(null); setInfo(null);
      if (!token) { setError("Not authenticated"); return; }
      if (!eventId) { setError("Please select an event"); return; }
      if (templateKey !== 'tickets') {
        if (!subject.trim()) { setError("Subject is required"); return; }
        if (!body.trim()) { setError("Message is required"); return; }
      }
      setSending(true);
      const payload: any = {
        subject,
        filter: { status: status !== 'any' ? status : undefined, attendeeIds: selectedAttendeeIds && selectedAttendeeIds.length ? selectedAttendeeIds : undefined },
        template: templateKey,
      };
      if (templateKey !== 'tickets') {
        if (body.trim().startsWith('<')) payload.html = body; else payload.text = body.replace(/\n/g, '\n');
      }
      const res = await apiFetch(`/api/events/${encodeURIComponent(eventId)}/email-attendees`, { method: 'POST', authToken: token, body: payload });
      const queued = res?.queued ?? res?.matched ?? 0;
      setInfo(`Queued ${queued} recipient(s) for sending.`);
      // Reset form to default state
      resetAttendeesForm();
    } catch (e: any) {
      setError(e?.message || 'Failed to send emails');
    } finally {
      setSending(false);
    }
  };

  return (
    <div className="max-w-3xl mx-auto w-full p-6">
      <div className="flex items-center justify-between mb-4 flex-wrap gap-3">
        <div className="flex items-center gap-3">
          <div className="w-10 h-10 rounded-xl bg-brand-50 flex items-center justify-center shrink-0">
            <Mail className="w-5 h-5 text-brand-600" />
          </div>
          <h1 className="text-2xl font-semibold text-gray-900">Email Attendees</h1>
        </div>
        <div className="flex items-center gap-2">
          <button className="px-3 py-1.5 text-sm rounded-lg bg-gray-100 hover:bg-gray-200 text-gray-800 shadow-sm" onClick={() => router.push('/dashboard')}>Back</button>
        </div>
      </div>

      {!canView && (
        <div className="p-3 border rounded bg-yellow-50 text-yellow-800 text-sm mb-4">
          You need supervisor or admin access to use this page.
        </div>
      )}

      {error && <div className="p-3 mb-3 border rounded bg-red-50 text-red-700 text-sm">{error}</div>}
      {info && <div className="p-3 mb-3 border rounded bg-emerald-50 text-emerald-800 text-sm">{info}</div>}

      {/* Tabs like on Payments page */}
      <div className="mb-4 flex items-center gap-2 flex-wrap">
        <label className={`px-3 py-1.5 text-sm rounded border ${tab === 'attendees' ? 'bg-brand-600 text-white border-brand-600' : 'bg-white text-gray-800 border-gray-200'} cursor-pointer`}>
          <input type="radio" name="emailTab" value="attendees" className="hidden" checked={tab==='attendees'} onChange={() => setTab('attendees')} />
          Attendees
        </label>
        <label className={`px-3 py-1.5 text-sm rounded border ${tab === 'automations' ? 'bg-brand-600 text-white border-brand-600' : 'bg-white text-gray-800 border-gray-200'} cursor-pointer`}>
          <input type="radio" name="emailTab" value="automations" className="hidden" checked={tab==='automations'} onChange={() => setTab('automations')} />
          Automations
        </label>
        <label className={`px-3 py-1.5 text-sm rounded border ${tab === 'broadcasts' ? 'bg-brand-600 text-white border-brand-600' : 'bg-white text-gray-800 border-gray-200'} cursor-pointer`}>
          <input type="radio" name="emailTab" value="broadcasts" className="hidden" checked={tab==='broadcasts'} onChange={() => setTab('broadcasts')} />
          Broadcasts
        </label>
        <label className={`px-3 py-1.5 text-sm rounded border ${tab === 'scheduled' ? 'bg-brand-600 text-white border-brand-600' : 'bg-white text-gray-800 border-gray-200'} cursor-pointer`}>
          <input type="radio" name="emailTab" value="scheduled" className="hidden" checked={tab==='scheduled'} onChange={() => setTab('scheduled')} />
          Scheduled
        </label>
      </div>

      {tab === 'attendees' && (
        <div className="border rounded-xl p-4 bg-white shadow-sm">
          <div className="grid gap-3">
            <div>
              <label className="block text-xs text-gray-600 mb-1">Event</label>
              <div className="flex gap-2 items-center">
                <select className="border rounded px-3 py-2 text-sm flex-1 min-w-0 max-w-full" value={eventId} onChange={e => setEventId(e.target.value)}>
                  <option value="">Select an event…</option>
                  {events.map(ev => (
                    <option key={ev.id} value={ev.id}>{ev.title}{ev.endDate && new Date(ev.endDate) < new Date() ? ' (past)' : ''}</option>
                  ))}
                </select>
                {loadingEvents && <span className="text-xs text-gray-500">Loading…</span>}
              </div>
              <label className="flex items-center gap-1.5 text-xs text-gray-500 mt-1 cursor-pointer">
                <input type="checkbox" checked={evIncludePast} onChange={e => setEvIncludePast(e.target.checked)} />
                Include past events
              </label>
            </div>

            <div className="grid sm:grid-cols-3 gap-3">
              <div>
                <div className="flex items-center justify-between">
                  <label className="block text-xs text-gray-600 mb-1">Template</label>
                  <button type="button" aria-label="About dynamic placeholders" className="text-[11px] text-gray-600 hover:text-gray-900 inline-flex items-center gap-1" onClick={() => setShowInfo(true)}>
                    <span className="inline-flex items-center justify-center w-4 h-4 rounded-full border border-gray-300 text-[10px]">i</span>
                    Info
                  </button>
                </div>
                <select className="w-full border rounded px-3 py-2 text-sm" value={templateKey} onChange={e => setTemplateKey(e.target.value as any)}>
                  <option value="custom">Custom message</option>
                  <option value="payment_reminder">Payment reminder (with outstanding)</option>
                  <option value="event_reminder">Event reminder (date & time)</option>
                  <option value="tickets">Tickets email (attachments)</option>
                </select>
              </div>
              <div className="sm:col-span-2">
                <div className="text-[11px] text-gray-500 mt-6">Available placeholders: {'{{name}}'}, {'{{event.title}}'}, {'{{event.start}}'}, {'{{balance}}'}, {'{{payment.link}}'} <button type="button" className="ml-2 underline hover:no-underline" onClick={() => setShowInfo(true)}>Learn more</button></div>
              </div>
            </div>

            {showInfo && (
              <div className="fixed inset-0 z-20">
                <div className="absolute inset-0 bg-black/30" onClick={() => setShowInfo(false)} />
                <div className="absolute inset-0 flex items-center justify-center p-4">
                  <div className="w-full max-w-lg bg-white rounded-lg shadow-lg border p-4">
                    <div className="flex items-center justify-between mb-2">
                      <h3 className="text-sm font-semibold">Dynamic parameters</h3>
                      <button type="button" className="text-xs px-2 py-1 rounded bg-gray-100 hover:bg-gray-200" onClick={() => setShowInfo(false)}>Close</button>
                    </div>
                    <div className="text-[12px] text-gray-700 break-words">
                      <p className="mb-2">You can personalize your subject and message using these placeholders. They will be replaced per recipient when sending.</p>
                      <ul className="list-disc pl-5 space-y-1 mb-2">
                        <li><code>{'{{name}}'}</code> — attendee’s name.</li>
                        <li><code>{'{{event.title}}'}</code> — the event title.</li>
                        <li><code>{'{{event.start}}'}</code> — the event start date/time (local).</li>
                        <li><code>{'{{balance}}'}</code> — outstanding amount across the attendee’s registrations for the selected event.</li>
                        <li><code>{'{{payment.link}}'}</code> — a direct Yoco payment link for the attendee's outstanding balance (generated per recipient when sending).</li>
                      </ul>
                      <p className="mb-2">Example: Hi <code>{'{{name}}'}</code>, your balance is <code>{'{{balance}}'}</code>. Pay here: <code>{'{{payment.link}}'}</code></p>
                      <p className="text-[11px] text-gray-500">To add new placeholders, extend <span className="font-mono">backend/src/utils/placeholders.js</span> and update this help.</p>
                    </div>
                  </div>
                </div>
              </div>
            )}

            <div className="grid sm:grid-cols-2 gap-3">
              <div>
                <label className="block text-xs text-gray-600 mb-1">Subject</label>
                <input className="w-full border rounded px-3 py-2 text-sm" disabled={templateKey==='tickets'} value={subject} onChange={e => { setSubject(e.target.value); setSubjectDirty(true); }} placeholder="Subject" />
              </div>
              <div>
                <label className="block text-xs text-gray-600 mb-1">Payment status filter</label>
                <select className="w-full border rounded px-3 py-2 text-sm" value={status} onChange={e => setStatus(e.target.value as any)}>
                  <option value="any">Any</option>
                  <option value="paid">Paid</option>
                  <option value="unpaid">Unpaid (pending or partial)</option>
                  <option value="partial_paid">Partial paid</option>
                  <option value="cancelled">Cancelled</option>
                </select>
              </div>
            </div>

            {templateKey !== 'tickets' ? (
              <div>
                <label className="block text-xs text-gray-600 mb-1">Message</label>
                <textarea className="w-full border rounded px-3 py-2 text-sm" rows={8} value={body} onChange={e => { setBody(e.target.value); setBodyDirty(true); }} placeholder="Write your message to attendees..." />
                <div className="text-[11px] text-gray-500 mt-1">Hint: Start with &lt;html&gt; or &lt;div&gt; to send HTML; otherwise plain text will be sent.</div>
              </div>
            ) : (
              <div className="p-3 border rounded bg-gray-50 text-sm text-gray-700">This will send each selected attendee their ticket(s) as attachments for this event.</div>
            )}

            <div className="grid sm:grid-cols-2 gap-3">
              <div>
                <label className="block text-xs text-gray-600 mb-1">Attendees</label>
                <AttendeesCheckboxDropdown
                  attendees={attendees}
                  loading={loadingAttendees}
                  selectedIds={selectedAttendeeIds}
                  onChange={setSelectedAttendeeIds}
                  channel="email"
                />
                <div className="text-[11px] text-gray-500 mb-1">Email/both attendees are pre-selected. Use the dropdown to refine.</div>
              </div>
              <div>
                <label className="block text-xs text-gray-600 mb-1">Send at (optional)</label>
                <input className="w-full border rounded px-3 py-2 text-sm" type="datetime-local" value={scheduledAtLocal} onChange={e => setScheduledAtLocal(e.target.value)} />
                <div className="text-[10px] text-gray-500 mt-1">Leave empty to send immediately. Uses your local timezone.</div>
              </div>
            </div>

            {mismatchedAttendees.length > 0 && (
              <div className="p-3 border rounded bg-amber-50 text-amber-800 text-xs">
                <strong>{mismatchedAttendees.length} selected attendee(s)</strong> prefer WhatsApp only — they will still receive this email but it&apos;s not their preferred channel.
              </div>
            )}

            <div className="flex items-center flex-wrap gap-2">
              <button type="button" disabled={sending} className="px-3 py-1.5 text-sm rounded border bg-white hover:bg-gray-50" onClick={onPreview}>Preview recipients</button>
              <button type="button" disabled={sending} className="px-3 py-1.5 text-sm rounded bg-brand-600 text-white hover:bg-brand-700 disabled:opacity-50" onClick={onSend}>{sending ? 'Sending…' : 'Send now'}</button>
              <button type="button" disabled={sending || !scheduledAtLocal} className="px-3 py-1.5 text-sm rounded bg-emerald-600 text-white hover:bg-emerald-700 disabled:opacity-50" onClick={async () => {
                try {
                  setError(null); setInfo(null);
                  if (!token) { setError('Not authenticated'); return; }
                  if (!eventId) { setError('Please select an event'); return; }
                  if (templateKey !== 'tickets') {
                    if (!subject.trim()) { setError('Subject is required'); return; }
                    if (!body.trim()) { setError('Message is required'); return; }
                  }
                  const whenIso = new Date(scheduledAtLocal).toISOString();
                  const payload = {
                    subject,
                    filter: { status: status !== 'any' ? status : undefined, attendeeIds: selectedAttendeeIds && selectedAttendeeIds.length ? selectedAttendeeIds : undefined },
                    template: templateKey,
                    scheduledAt: whenIso,
                  } as any;
                  if (templateKey !== 'tickets') {
                    if (body.trim().startsWith('<')) payload.html = body; else payload.text = body.replace(/\n/g, '\n');
                  }
                  const res = await apiFetch(`/api/events/${encodeURIComponent(eventId)}/email-attendees/schedule`, { method: 'POST', authToken: token, body: payload });
                  if (res?.job?.id) {
                    setInfo('Email scheduled. It will be sent around the specified time.');
                  } else {
                    setInfo('Scheduled.');
                  }
                  // Reset form to default state
                  resetAttendeesForm();
                } catch (e:any) {
                  setError(e?.message || 'Failed to schedule email');
                }
              }}>Schedule send</button>
              {previewCount != null && (
                <span className="text-xs text-gray-600">Preview: {previewCount} recipient(s)</span>
              )}
            </div>

            {previewSample && previewSample.length > 0 && (
              <div className="mt-2">
                <div className="text-xs text-gray-600 mb-1">First {previewSample.length} recipient(s):</div>
                <ul className="text-xs text-gray-800 list-disc pl-5 space-y-0.5">
                  {previewSample.map((r, idx) => (
                    <li key={idx} className="break-words">{r.name ? `${r.name} <${r.email}>` : r.email}</li>
                  ))}
                </ul>
              </div>
            )}
          </div>
        </div>
      )}

      {tab === 'automations' && (
        <div className="border rounded-xl p-4 bg-white shadow-sm">
          <AutomationsPanel events={events} token={token} onInfo={setInfo} onError={setError} />
        </div>
      )}

      {tab === 'broadcasts' && (
        <div className="border rounded-xl p-4 bg-white shadow-sm">
          <div className="grid gap-3">
            <div className="grid sm:grid-cols-2 gap-3">
              <div>
                <label className="block text-xs text-gray-600 mb-1">Users (optional)</label>
                <AttendeesCheckboxDropdown
                  attendees={users}
                  loading={loadingUsers}
                  selectedIds={selectedUserIds}
                  onChange={setSelectedUserIds}
                  channel="email"
                />
                <div className="text-[11px] text-gray-500 mb-1">Select users from your database to include. Green = Email/both preference. You can also add external emails below.</div>
              </div>
              <div>
                <label className="block text-xs text-gray-600 mb-1">Event (optional for placeholders)</label>
                <select className="w-full border rounded px-3 py-2 text-sm" value={broadcastEventId} onChange={e => setBroadcastEventId(e.target.value)}>
                  <option value="">No event</option>
                  {events.map(ev => (
                    <option key={ev.id} value={ev.id}>{ev.title}</option>
                  ))}
                </select>
              </div>
            </div>

            {selectedUserIds.length > 0 && (
              <PrefWarning attendees={users} selectedIds={selectedUserIds} channel="email" />
            )}

            <div>
              <div className="flex items-center justify-between">
                <label className="block text-xs text-gray-600 mb-1">Subject</label>
                <button type="button" aria-label="About dynamic placeholders" className="text-[11px] text-gray-600 hover:text-gray-900 inline-flex items-center gap-1" onClick={() => setShowInfo(true)}>
                  <span className="inline-flex items-center justify-center w-4 h-4 rounded-full border border-gray-300 text-[10px]">i</span>
                  Info
                </button>
              </div>
              <input className="w-full border rounded px-3 py-2 text-sm" value={broadcastSubject} onChange={e => setBroadcastSubject(e.target.value)} placeholder="Subject (supports {{name}}, {{event.title}}, {{event.start}}, {{event.link}})" />
            </div>

            <div>
              <label className="block text-xs text-gray-600 mb-1">Message</label>
              <textarea className="w-full border rounded px-3 py-2 text-sm" rows={8} value={broadcastBody} onChange={e => setBroadcastBody(e.target.value)} placeholder="Write your message... You can use {{name}}, {{event.title}}, {{event.start}}, {{event.link}}" />
              <div className="text-[11px] text-gray-500 mt-1">Hint: Start with &lt;html&gt; or &lt;div&gt; to send HTML; otherwise plain text will be sent.</div>
            </div>

            <div>
              <label className="block text-xs text-gray-600 mb-1">Additional emails (one per line)</label>
              <textarea className="w-full border rounded px-3 py-2 text-sm" rows={6} value={broadcastEmails} onChange={e => setBroadcastEmails(e.target.value)}
placeholder={
`email@example.com
Jane Doe <jane@example.com>
'John Smith' <john@domain.co.za>`
              } />
              <div className="text-[11px] text-gray-500 mt-1">Tips: You can paste a list. Supported formats: email@example.com or Name &lt;email@example.com&gt;.</div>
            </div>

            <div className="grid sm:grid-cols-2 gap-3">
              <div>
                <label className="block text-xs text-gray-600 mb-1">Send at (optional)</label>
                <input className="w-full border rounded px-3 py-2 text-sm" type="datetime-local" value={broadcastScheduledAtLocal} onChange={e => setBroadcastScheduledAtLocal(e.target.value)} />
                <div className="text-[10px] text-gray-500 mt-1">Leave empty to send immediately. Uses your local timezone.</div>
              </div>
            </div>

            <div className="flex items-center flex-wrap gap-2">
              <button type="button" className="px-3 py-1.5 text-sm rounded border bg-white hover:bg-gray-50" onClick={async () => {
                try {
                  setError(null); setInfo(null); setBroadcastPreviewCount(null); setBroadcastPreviewSample(null);
                  if (!token) { setError('Not authenticated'); return; }
                  if (!broadcastSubject.trim()) { setError('Subject is required'); return; }
                  if (!broadcastBody.trim()) { setError('Message is required'); return; }
                  const body: any = { userIds: selectedUserIds, emails: broadcastEmails, eventId: broadcastEventId || undefined };
                  const res = await apiFetch(`/api/broadcasts/preview`, { method: 'POST', authToken: token, body });
                  setBroadcastPreviewCount(res?.matched ?? 0);
                  setBroadcastPreviewSample(Array.isArray(res?.recipients) ? res.recipients : null);
                  setInfo(`Matched ${res?.matched ?? 0} recipient(s).`);
                } catch (e:any) {
                  setError(e?.message || 'Failed to preview recipients');
                }
              }}>Preview recipients</button>

              <button type="button" className="px-3 py-1.5 text-sm rounded bg-brand-600 text-white hover:bg-brand-700 disabled:opacity-50" onClick={async () => {
                try {
                  setError(null); setInfo(null);
                  if (!token) { setError('Not authenticated'); return; }
                  if (!broadcastSubject.trim()) { setError('Subject is required'); return; }
                  if (!broadcastBody.trim()) { setError('Message is required'); return; }
                  const payload: any = { subject: broadcastSubject, eventId: broadcastEventId || undefined, userIds: selectedUserIds, emails: broadcastEmails };
                  if (broadcastBody.trim().startsWith('<')) payload.html = broadcastBody; else payload.text = broadcastBody;
                  const res = await apiFetch(`/api/broadcasts/send`, { method: 'POST', authToken: token, body: payload });
                  setInfo(`Sent ${res?.sent ?? 0} out of ${res?.matched ?? 0} recipient(s).`);
                  // Reset broadcast form
                  resetBroadcastForm();
                } catch (e:any) {
                  setError(e?.message || 'Failed to send broadcast');
                }
              }}>Send now</button>

              <button type="button" disabled={!broadcastScheduledAtLocal} className="px-3 py-1.5 text-sm rounded bg-emerald-600 text-white hover:bg-emerald-700 disabled:opacity-50" onClick={async () => {
                try {
                  setError(null); setInfo(null);
                  if (!token) { setError('Not authenticated'); return; }
                  if (!broadcastSubject.trim()) { setError('Subject is required'); return; }
                  if (!broadcastBody.trim()) { setError('Message is required'); return; }
                  const whenIso = new Date(broadcastScheduledAtLocal).toISOString();
                  const payload: any = { scheduledAt: whenIso, subject: broadcastSubject, eventId: broadcastEventId || undefined, userIds: selectedUserIds, emails: broadcastEmails };
                  if (broadcastBody.trim().startsWith('<')) payload.html = broadcastBody; else payload.text = broadcastBody;
                  const res = await apiFetch(`/api/broadcasts/schedule`, { method: 'POST', authToken: token, body: payload });
                  if (res?.job?.id) setInfo('Broadcast scheduled. It will be sent around the specified time.'); else setInfo('Scheduled.');
                  // Reset broadcast form
                  resetBroadcastForm();
                } catch (e:any) {
                  setError(e?.message || 'Failed to schedule broadcast');
                }
              }}>Schedule send</button>

              {broadcastPreviewCount != null && (
                <span className="text-xs text-gray-600">Preview: {broadcastPreviewCount} recipient(s)</span>
              )}
            </div>

            {broadcastPreviewSample && broadcastPreviewSample.length > 0 && (
              <div className="mt-2">
                <div className="text-xs text-gray-600 mb-1">First {broadcastPreviewSample.length} recipient(s):</div>
                <ul className="text-xs text-gray-800 list-disc pl-5 space-y-0.5">
                  {broadcastPreviewSample.map((r, idx) => (
                    <li key={idx} className="break-words">{r.name ? `${r.name} <${r.email}>` : r.email}</li>
                  ))}
                </ul>
              </div>
            )}

            {showInfo && (
              <div className="fixed inset-0 z-20">
                <div className="absolute inset-0 bg-black/30" onClick={() => setShowInfo(false)} />
                <div className="absolute inset-0 flex items-center justify-center p-4">
                  <div className="w-full max-w-lg bg-white rounded-lg shadow-lg border p-4">
                    <div className="flex items-center justify-between mb-2">
                      <h3 className="text-sm font-semibold">Dynamic parameters</h3>
                      <button type="button" className="text-xs px-2 py-1 rounded bg-gray-100 hover:bg-gray-200" onClick={() => setShowInfo(false)}>Close</button>
                    </div>
                    <div className="text-[12px] text-gray-700 break-words">
                      <p className="mb-2">You can personalize your subject and message using these placeholders. They will be replaced per recipient when sending.</p>
                      <ul className="list-disc pl-5 space-y-1 mb-2">
                        <li><code>{'{{name}}'}</code> — recipient’s name (if available).</li>
                        <li><code>{'{{event.title}}'}</code> — the event title (when an event is selected).</li>
                        <li><code>{'{{event.start}}'}</code> — the event start date/time (local).</li>
                        <li><code>{'{{event.link}}'}</code> — a link to the event details page.</li>
                      </ul>
                      <p className="mb-2">Example: Hi <code>{'{{name}}'}</code>, check out <code>{'{{event.title}}'}</code>: <code>{'{{event.link}}'}</code>.</p>
                      <p className="text-[11px] text-gray-500">Attendees tab also supports <code>{'{{balance}}'}</code>; broadcasts do not calculate balances.</p>
                    </div>
                  </div>
                </div>
              </div>
            )}
          </div>
        </div>
      )}

      {tab === 'scheduled' && (
        <div className="border rounded-xl p-4 bg-white shadow-sm">
          <div className="flex items-center justify-between mb-3">
            <h2 className="text-lg font-medium">Manage Scheduled Emails</h2>
            <button type="button" className="text-sm px-2 py-1 rounded border bg-white hover:bg-gray-50" onClick={loadScheduled}>
              Refresh
            </button>
          </div>
          {loadingScheduled ? (
            <div className="text-sm text-gray-600">Loading…</div>
          ) : scheduled.length === 0 ? (
            <div className="text-sm text-gray-600">No scheduled items. Items sent more than a week ago are hidden.</div>
          ) : (
            <ul className="divide-y border rounded">
              {scheduled.map(job => (
                <li key={job.id} className="p-3 flex items-start justify-between gap-3">
                  <div className="min-w-0">
                    <div className="text-sm font-medium text-gray-900 flex items-center gap-2">
                      <span className="inline-block px-2 py-0.5 text-xs rounded border bg-gray-50">{job.kind}</span>
                      <span className="truncate">{job.subject || '(no subject)'}</span>
                    </div>
                    <div className="text-xs text-gray-600 mt-1">
                      <span className="mr-2">Status: {job.status}</span>
                      <span className="mr-2">Scheduled: {(() => { try { return new Date(job.scheduledAt).toLocaleString(); } catch { return job.scheduledAt; } })()}</span>
                      {job.sentAt && <span>Sent: {(() => { try { return new Date(job.sentAt!).toLocaleString(); } catch { return job.sentAt; } })()}</span>}
                      {job.lastError && <span className="ml-2 text-red-600 break-words">Error: {job.lastError}</span>}
                    </div>
                  </div>
                  <div className="flex items-center gap-2 shrink-0">
                    <button type="button" disabled={job.status!=='queued'} className="px-2 py-1 text-xs rounded border bg-white hover:bg-gray-50 disabled:opacity-50" onClick={() => openEdit(job)}>Edit</button>
                    <button type="button" disabled={job.status!=='queued'} className="px-2 py-1 text-xs rounded border bg-white hover:bg-gray-50 disabled:opacity-50" onClick={() => removeJob(job)}>Remove</button>
                  </div>
                </li>
              ))}
            </ul>
          )}

          {editing && (
            <div className="fixed inset-0 z-20">
              <div className="absolute inset-0 bg-black/30" onClick={() => setEditing(null)} />
              <div className="absolute inset-0 flex items-center justify-center p-4">
                <div className="w-full max-w-lg bg-white rounded-lg shadow-lg border p-4">
                  <div className="flex items-center justify-between mb-2">
                    <h3 className="text-sm font-semibold">Edit scheduled email</h3>
                    <button type="button" className="text-xs px-2 py-1 rounded bg-gray-100 hover:bg-gray-200" onClick={() => setEditing(null)}>Close</button>
                  </div>
                  <div className="grid gap-3">
                    <div>
                      <label className="block text-xs text-gray-600 mb-1">Subject</label>
                      <input className="w-full border rounded px-3 py-2 text-sm" value={editSubject} onChange={e => setEditSubject(e.target.value)} />
                    </div>
                    <div>
                      <label className="block text-xs text-gray-600 mb-1">Message (optional)</label>
                      <textarea className="w-full border rounded px-3 py-2 text-sm" rows={6} value={editBody} onChange={e => setEditBody(e.target.value)} placeholder="Leave empty to keep current content; or enter new content (HTML supported if starting with <)"></textarea>
                    </div>
                    <div>
                      <label className="block text-xs text-gray-600 mb-1">Send at</label>
                      <input className="w-full border rounded px-3 py-2 text-sm" type="datetime-local" value={editWhen} onChange={e => setEditWhen(e.target.value)} />
                    </div>
                    <div className="flex items-center gap-2">
                      <button type="button" disabled={savingEdit} className="px-3 py-1.5 text-sm rounded bg-brand-600 text-white hover:bg-brand-700 disabled:opacity-50" onClick={saveEdit}>{savingEdit ? 'Saving…' : 'Save changes'}</button>
                      <button type="button" className="px-3 py-1.5 text-sm rounded border bg-white hover:bg-gray-50" onClick={() => setEditing(null)}>Cancel</button>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
}


function toLocalInputValue(d: Date) {
  const pad = (n: number) => String(n).padStart(2, '0');
  const y = d.getFullYear();
  const m = pad(d.getMonth() + 1);
  const day = pad(d.getDate());
  const hh = pad(d.getHours());
  const mm = pad(d.getMinutes());
  return `${y}-${m}-${day}T${hh}:${mm}`;
}

function AutomationsPanel({ events, token, onInfo, onError }:{ events: any[]; token?: string | null; onInfo: (s: string) => void; onError: (s: string) => void }) {
  const [autoEventId, setAutoEventId] = React.useState<string>('');
  const currentEvent = React.useMemo(() => (events || []).find((e:any) => e.id === autoEventId), [events, autoEventId]);

  // Defaults builders
  const preWeekDefault = React.useMemo(() => ({
    subject: `1 Week to Go: {{event.title}}!`,
    body: `Hi {{name}}\n\nJust a friendly reminder that {{event.title}} is one week away.\n\nVenue: [add venue]\nTime: {{event.start}}\nParking: [add parking info]\nPacking list: [add items if needed]\n\nMore details: {{event.link}}`,
  }), []);
  const finalDefault = React.useMemo(() => ({
    subject: `We’ll See You Tomorrow at {{event.title}}!`,
    body: `Hi {{name}}\n\nFinal reminder for {{event.title}}.\nArrival instructions: [add arrival info]\nPlease have your QR code/ticket ready at entry.\n\nEvent details: {{event.link}}`,
  }), []);
  const thanksDefault = React.useMemo(() => ({
    subject: `Thanks for Joining {{event.title}}!`,
    body: `Hi {{name}}\n\nThank you for joining us at {{event.title}}!\nHighlights: [add highlights]\nPhotos/recordings: [add links]\nSponsor shoutouts: [add sponsors]\n\nSee you next time!`,
  }), []);
  const promoDefault = React.useMemo(() => ({
    subject: `Don’t Miss Our Next Event: {{promo.title}}`,
    body: `Hi {{name}}\n\nWe’d love to see you at our next event: {{promo.title}}.\nFind out more and register here: {{promo.link}}`,
  }), []);

  // Enable toggles
  const [enablePre, setEnablePre] = React.useState(true);
  const [enableFinal, setEnableFinal] = React.useState(true);
  const [enableThanks, setEnableThanks] = React.useState(true);
  const [enablePromo, setEnablePromo] = React.useState(false);

  // Subjects/Bodies
  const [preSubject, setPreSubject] = React.useState(preWeekDefault.subject);
  const [preBody, setPreBody] = React.useState(preWeekDefault.body);
  const [finalSubject, setFinalSubject] = React.useState(finalDefault.subject);
  const [finalBody, setFinalBody] = React.useState(finalDefault.body);
  const [thanksSubject, setThanksSubject] = React.useState(thanksDefault.subject);
  const [thanksBody, setThanksBody] = React.useState(thanksDefault.body);
  const [promoSubject, setPromoSubject] = React.useState(promoDefault.subject);
  const [promoBody, setPromoBody] = React.useState(promoDefault.body);

  // Timing
  const [finalHours, setFinalHours] = React.useState<'24'|'48'>('24');
  const [preWhen, setPreWhen] = React.useState<string>('');
  const [finalWhen, setFinalWhen] = React.useState<string>('');
  const [thanksWhen, setThanksWhen] = React.useState<string>('');
  const [promoWhen, setPromoWhen] = React.useState<string>('');
  const [promoEventId, setPromoEventId] = React.useState<string>('');

  // Compute defaults when event changes or finalHours change
  React.useEffect(() => {
    if (!currentEvent) { setPreWhen(''); setFinalWhen(''); setThanksWhen(''); setPromoWhen(''); return; }
    try {
      const start = new Date(currentEvent.startDate);
      const end = new Date(currentEvent.endDate || currentEvent.startDate);
      // Pre-event: 7 days before start at 09:00
      const pre = new Date(start);
      pre.setDate(pre.getDate() - 7);
      pre.setHours(9, 0, 0, 0);
      setPreWhen(toLocalInputValue(pre));
      // Final reminder: hours before start
      const fin = new Date(start);
      fin.setHours(fin.getHours() - (finalHours === '48' ? 48 : 24));
      setFinalWhen(toLocalInputValue(fin));
      // Thanks: day after end at 09:00
      const ty = new Date(end);
      ty.setDate(ty.getDate() + 1);
      ty.setHours(9, 0, 0, 0);
      setThanksWhen(toLocalInputValue(ty));
      // Promo: 3 days after end at 09:00
      const pr = new Date(end);
      pr.setDate(pr.getDate() + 3);
      pr.setHours(9, 0, 0, 0);
      setPromoWhen(toLocalInputValue(pr));
      // Prefill subjects again using event title (user can edit afterward)
      const title = currentEvent.title || 'the event';
      setPreSubject(`1 Week to Go: ${title}!`);
      setFinalSubject(`We’ll See You Tomorrow at ${title}!`);
      setThanksSubject(`Thanks for Joining ${title}!`);
      setPromoSubject(`Don’t Miss Our Next Event: {{promo.title}`);
    } catch {}
  }, [currentEvent, finalHours]);

  const onSchedule = async () => {
    try {
      onError(null as any); onInfo(null as any);
      if (!token) { onError('Not authenticated'); return; }
      if (!autoEventId) { onError('Please select an event'); return; }
      const jobs: any[] = [];
      if (enablePre && preSubject.trim() && preBody.trim() && preWhen) {
        const payload: any = { subject: preSubject, scheduledAt: new Date(preWhen).toISOString() };
        if (preBody.trim().startsWith('<')) payload.html = preBody; else payload.text = preBody;
        jobs.push(payload);
      }
      if (enableFinal && finalSubject.trim() && finalBody.trim() && finalWhen) {
        const payload: any = { subject: finalSubject, scheduledAt: new Date(finalWhen).toISOString() };
        if (finalBody.trim().startsWith('<')) payload.html = finalBody; else payload.text = finalBody;
        jobs.push(payload);
      }
      if (enableThanks && thanksSubject.trim() && thanksBody.trim() && thanksWhen) {
        const payload: any = { subject: thanksSubject, scheduledAt: new Date(thanksWhen).toISOString() };
        if (thanksBody.trim().startsWith('<')) payload.html = thanksBody; else payload.text = thanksBody;
        jobs.push(payload);
      }
      if (enablePromo && promoSubject.trim() && promoBody.trim() && promoWhen) {
        const payload: any = { subject: promoSubject, scheduledAt: new Date(promoWhen).toISOString(), promoEventId: promoEventId || undefined };
        if (promoBody.trim().startsWith('<')) payload.html = promoBody; else payload.text = promoBody;
        jobs.push(payload);
      }
      if (jobs.length === 0) { onError('Please enable at least one automation and fill in details'); return; }
      const res = await apiFetch(`/api/automations/schedule`, { method: 'POST', authToken: token, body: { eventId: autoEventId, jobs } });
      onInfo(res?.message || `Scheduled ${jobs.length} automation(s).`);
      // Reset to defaults (keep event selection)
      setEnablePre(true); setEnableFinal(true); setEnableThanks(true); setEnablePromo(false);
      setPreSubject(preWeekDefault.subject); setPreBody(preWeekDefault.body);
      setFinalSubject(finalDefault.subject); setFinalBody(finalDefault.body); setFinalHours('24');
      setThanksSubject(thanksDefault.subject); setThanksBody(thanksDefault.body);
      setPromoSubject(promoDefault.subject); setPromoBody(promoDefault.body); setPromoEventId('');
    } catch (e:any) {
      onError(e?.message || 'Failed to schedule automations');
    }
  };

  return (
    <div className="grid gap-4">
      <div>
        <label className="block text-xs text-gray-600 mb-1">Event</label>
        <select className="w-full border rounded px-3 py-2 text-sm" value={autoEventId} onChange={e => setAutoEventId(e.target.value)}>
          <option value="">Select an event…</option>
          {(events||[]).map((ev:any) => (
            <option key={ev.id} value={ev.id}>{ev.title}</option>
          ))}
        </select>
      </div>

      <div className="grid gap-4">
        <fieldset className="border rounded p-3">
          <legend className="text-sm font-medium">Pre-Event Reminder (1 week before)</legend>
          <label className="inline-flex items-center gap-2 text-sm mb-2">
            <input type="checkbox" checked={enablePre} onChange={e => setEnablePre(e.target.checked)} /> Enable
          </label>
          <div className="grid sm:grid-cols-2 gap-3">
            <div>
              <label className="block text-xs text-gray-600 mb-1">Subject</label>
              <input className="w-full border rounded px-3 py-2 text-sm" value={preSubject} onChange={e => setPreSubject(e.target.value)} placeholder="1 Week to Go: {{event.title}}!" />
            </div>
            <div>
              <label className="block text-xs text-gray-600 mb-1">Send at</label>
              <input className="w-full border rounded px-3 py-2 text-sm" type="datetime-local" value={preWhen} onChange={e => setPreWhen(e.target.value)} />
            </div>
          </div>
          <label className="block text-xs text-gray-600 mb-1 mt-2">Message</label>
          <textarea className="w-full border rounded px-3 py-2 text-sm" rows={5} value={preBody} onChange={e => setPreBody(e.target.value)} />
        </fieldset>

        <fieldset className="border rounded p-3">
          <legend className="text-sm font-medium">Final Reminder (24–48 hrs before)</legend>
          <div className="flex items-center gap-4 mb-2">
            <label className="inline-flex items-center gap-2 text-sm">
              <input type="checkbox" checked={enableFinal} onChange={e => setEnableFinal(e.target.checked)} /> Enable
            </label>
            <label className="text-xs text-gray-600">Hours before: </label>
            <select className="border rounded px-2 py-1 text-sm" value={finalHours} onChange={e => setFinalHours(e.target.value as any)}>
              <option value="24">24</option>
              <option value="48">48</option>
            </select>
          </div>
          <div className="grid sm:grid-cols-2 gap-3">
            <div>
              <label className="block text-xs text-gray-600 mb-1">Subject</label>
              <input className="w-full border rounded px-3 py-2 text-sm" value={finalSubject} onChange={e => setFinalSubject(e.target.value)} placeholder="We’ll See You Tomorrow at {{event.title}}!" />
            </div>
            <div>
              <label className="block text-xs text-gray-600 mb-1">Send at</label>
              <input className="w-full border rounded px-3 py-2 text-sm" type="datetime-local" value={finalWhen} onChange={e => setFinalWhen(e.target.value)} />
            </div>
          </div>
          <label className="block text-xs text-gray-600 mb-1 mt-2">Message</label>
          <textarea className="w-full border rounded px-3 py-2 text-sm" rows={5} value={finalBody} onChange={e => setFinalBody(e.target.value)} />
        </fieldset>

        <fieldset className="border rounded p-3">
          <legend className="text-sm font-medium">Thank You / Wrap Up</legend>
          <label className="inline-flex items-center gap-2 text-sm mb-2">
            <input type="checkbox" checked={enableThanks} onChange={e => setEnableThanks(e.target.checked)} /> Enable
          </label>
          <div className="grid sm:grid-cols-2 gap-3">
            <div>
              <label className="block text-xs text-gray-600 mb-1">Subject</label>
              <input className="w-full border rounded px-3 py-2 text-sm" value={thanksSubject} onChange={e => setThanksSubject(e.target.value)} placeholder="Thanks for Joining {{event.title}}!" />
            </div>
            <div>
              <label className="block text-xs text-gray-600 mb-1">Send at</label>
              <input className="w-full border rounded px-3 py-2 text-sm" type="datetime-local" value={thanksWhen} onChange={e => setThanksWhen(e.target.value)} />
            </div>
          </div>
          <label className="block text-xs text-gray-600 mb-1 mt-2">Message</label>
          <textarea className="w-full border rounded px-3 py-2 text-sm" rows={5} value={thanksBody} onChange={e => setThanksBody(e.target.value)} />
        </fieldset>

        <fieldset className="border rounded p-3">
          <legend className="text-sm font-medium">Next Event Promo</legend>
          <div className="flex items-center gap-4 mb-2">
            <label className="inline-flex items-center gap-2 text-sm">
              <input type="checkbox" checked={enablePromo} onChange={e => setEnablePromo(e.target.checked)} /> Enable
            </label>
          </div>
          <div className="grid sm:grid-cols-2 gap-3 mb-2">
            <div>
              <label className="block text-xs text-gray-600 mb-1">Promo Event</label>
              <select className="w-full border rounded px-3 py-2 text-sm" value={promoEventId} onChange={e => setPromoEventId(e.target.value)}>
                <option value="">Select event to promote…</option>
                {(events||[]).map((ev:any) => (
                  <option key={ev.id} value={ev.id}>{ev.title}</option>
                ))}
              </select>
            </div>
            <div>
              <label className="block text-xs text-gray-600 mb-1">Send at</label>
              <input className="w-full border rounded px-3 py-2 text-sm" type="datetime-local" value={promoWhen} onChange={e => setPromoWhen(e.target.value)} />
            </div>
          </div>
          <div className="grid sm:grid-cols-2 gap-3">
            <div>
              <label className="block text-xs text-gray-600 mb-1">Subject</label>
              <input className="w-full border rounded px-3 py-2 text-sm" value={promoSubject} onChange={e => setPromoSubject(e.target.value)} placeholder="Don’t Miss Our Next Event: {{promo.title}}" />
            </div>
          </div>
          <label className="block text-xs text-gray-600 mb-1 mt-2">Message</label>
          <textarea className="w-full border rounded px-3 py-2 text-sm" rows={5} value={promoBody} onChange={e => setPromoBody(e.target.value)} />
        </fieldset>
      </div>

      <div className="flex items-center gap-2">
        <button type="button" className="px-3 py-1.5 text-sm rounded bg-emerald-600 text-white hover:bg-emerald-700" onClick={onSchedule}>Schedule selected</button>
        <div className="text-[11px] text-gray-500">Placeholders supported: {'{{name}}'}, {'{{event.title}}'}, {'{{event.start}}'}, {'{{event.link}}'}, {'{{promo.title}}'}, {'{{promo.link}}'}. Start body with &lt;html&gt; or &lt;div&gt; to send HTML.</div>
      </div>
    </div>
  );
}
