// screens-campaigns.jsx — campaign list + 7-step wizard
const { useState } = React;
const CAMP_STATUS = {
  outreach_active: { tone: "green", label: "Active", c: "#22C55E" },
  ready: { tone: "blue", label: "Ready to launch", c: "#2563EB" },
  paused: { tone: "orange", label: "Paused", c: "#EA580C" },
  draft: { tone: "neutral", label: "Draft", c: "#9CA3AF" },
  archived: { tone: "neutral", label: "Archived", c: "#9CA3AF" },
};
const SERVICE_META = {
  shopify: { label: "Shopify", icon: "store", c: "#22C55E" },
  web: { label: "Web design", icon: "image", c: "#7E22CE" },
  // Premium Salla store design (on Salla, no migration) — agent Sara (ag_salla_design).
  salla: { label: "Salla design", icon: "store", c: "#14B8A6" },
  automation: { label: "Automation / SEO", icon: "zap", c: "#EA580C" },
  // Maxab Hub app subscription (Shopify/Salla app-store agents Yousef/Layan).
  app_sub: { label: "App subscription", icon: "store", c: "#7C3AED" },
  seo: { label: "Automation / SEO", icon: "zap", c: "#EA580C" },
};
// Never let an unknown/empty service crash the Campaigns screen (defense-in-depth).
const SERVICE_FALLBACK = { label: "Service", icon: "store", c: "#6B7280" };
const serviceMeta = (s) => SERVICE_META[s] || SERVICE_FALLBACK;

function Funnel({ c }) {
  const stages = [["Sent", c.sent], ["Replied", c.replied], ["Interested", c.interested], ["Won", c.won]];
  const max = c.contacts || 1;
  return (
    <div className="grid" style={{ gridTemplateColumns: "repeat(4,1fr)", gap: 10 }}>
      {stages.map(([k, v], i) => (
        <div key={k}>
          <div style={{ fontSize: 20, fontWeight: 800, letterSpacing: "-0.02em" }}>{v}</div>
          <div style={{ fontSize: 11, color: "var(--fg-4)", marginBottom: 6 }}>{k}</div>
          <div style={{ height: 4, borderRadius: 999, background: "var(--border-1)" }}>
            <div style={{ height: "100%", borderRadius: 999, width: Math.round((v / max) * 100) + "%", background: ["#9CA3AF", "#2563EB", "#4A6400", "#22C55E"][i] }} />
          </div>
        </div>
      ))}
    </div>
  );
}

function CampaignCard({ c, onOpen, onStatusChange, onResume }) {
  const st = CAMP_STATUS[c.status];
  const sv = serviceMeta(c.service);
  const agent = DATA.AGENTS.find((a) => a.id === c.agentId) || DATA.AGENTS.find((a) => a.name === c.agent);
  const sess = DATA.SESSIONS.find((s) => s.id === c.session);
  const stop = (e, fn) => { e.stopPropagation(); fn(); };
  return (
    <Card hover style={{ cursor: "pointer" }} onClick={() => onOpen(c)}>
      <div className="between" style={{ marginBottom: 14 }}>
        <div className="row" style={{ gap: 12 }}>
          <span className="opp" style={{ width: 40, height: 40, borderRadius: 12, background: "var(--bg-2)", color: sv.c }}><Icon name={sv.icon} size={20} /></span>
          <div>
            <div style={{ fontWeight: 700, fontSize: 15 }}>{c.name}</div>
            <div className="row" style={{ gap: 8, marginTop: 3, fontSize: 12, color: "var(--fg-4)" }}>
              <span className="row" style={{ gap: 4 }}><Icon name="mapPin" size={12} />{c.city}, {c.country}</span>
              <span>·</span><span>{c.goal}</span>
            </div>
          </div>
        </div>
        <Badge tone={st.tone} dot={st.c}>{st.label}</Badge>
      </div>
      <Funnel c={c} />
      <hr className="divider" style={{ margin: "16px 0" }} />
      <div className="between">
        <div className="row" style={{ gap: 8 }}>
          <Avatar name={c.agent} size="sm" color={agent?.color} />
          <span style={{ fontSize: 13, fontWeight: 600 }}>{c.agent}</span>
          <span className="subtle" style={{ fontSize: 12 }}>·</span>
          <WaChip state={sess?.state || "connected"} />
        </div>
        <div className="row" style={{ gap: 6 }}>
          {c.status === "outreach_active" && <button className="btn btn--subtle btn--sm" onClick={(e) => stop(e, () => onStatusChange(c.id, "paused"))}><Icon name="pause" size={14} />Pause</button>}
          {c.status === "ready" && <button className="btn btn--primary btn--sm" onClick={(e) => stop(e, () => onStatusChange(c.id, "outreach_active"))}><Icon name="play" size={14} />Launch</button>}
          {c.status === "draft" && <button className="btn btn--ghost btn--sm" onClick={(e) => stop(e, () => onResume(c))}><Icon name="edit" size={14} />Continue setup</button>}
          {c.status === "paused" && <button className="btn btn--ghost btn--sm" onClick={(e) => stop(e, () => onStatusChange(c.id, "outreach_active"))}><Icon name="play" size={14} />Resume</button>}
        </div>
      </div>
    </Card>
  );
}

function CampaignsScreen() {
  const { startWizard, go } = useApp();
  const data = useStore();
  const campaigns = data.CAMPAIGNS;
  const [detail, setDetail] = useState(null);
  const [metrics, setMetrics] = useState(null);
  React.useEffect(() => {
    let alive = true;
    API.metrics.campaigns().then((m) => { if (alive) setMetrics(m); }).catch((e) => console.error("campaign metrics failed", e));
    return () => { alive = false; };
  }, []);
  const changeStatus = (id, status) => { Actions.updateCampaign(id, { status }).catch((e) => console.error("campaign update failed", e)); };
  const active = campaigns.filter((c) => c.status === "outreach_active");
  const others = campaigns.filter((c) => c.status !== "outreach_active");
  const cardProps = { onOpen: setDetail, onStatusChange: changeStatus, onResume: () => startWizard() };
  const dash = (v) => (metrics == null ? "—" : v);
  const stats = [
    ["Active campaigns", String(active.length), "megaphone", "var(--color-blue)"],
    ["Sent today", dash(String(metrics?.sentToday ?? 0)), "send", "var(--color-secondary)"],
    ["Reply rate", dash((metrics?.replyRate ?? 0) + "%"), "reply", "var(--color-purple)"],
    ["Won this month", dash(String(metrics?.wonThisMonth ?? 0)), "trophy", "var(--color-success)"],
  ];
  return (
    <div className="content__inner fade-up">
      <FallbackBanner />
      <div className="grid" style={{ gridTemplateColumns: "repeat(4,1fr)", marginBottom: 28 }}>
        {stats.map(([l, v, ic, cl]) => (
          <Card key={l} style={{ padding: 18 }}>
            <div className="row" style={{ gap: 10, marginBottom: 10 }}><Icon name={ic} size={18} style={{ color: cl }} /><span style={{ fontSize: 12, color: "var(--fg-4)", fontWeight: 600 }}>{l}</span></div>
            <div style={{ fontSize: 28, fontWeight: 800, letterSpacing: "-0.02em" }}>{v}</div>
          </Card>
        ))}
      </div>

      <div className="between" style={{ marginBottom: 14 }}><h5>Active</h5></div>
      <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", marginBottom: 28 }}>
        {active.length ? active.map((c) => <CampaignCard key={c.id} c={c} {...cardProps} />) : <p className="muted" style={{ fontSize: 13 }}>No active campaigns right now.</p>}
      </div>

      <div className="between" style={{ marginBottom: 14 }}><h5>Drafts &amp; scheduled</h5></div>
      <div className="grid" style={{ gridTemplateColumns: "1fr 1fr" }}>
        {others.map((c) => <CampaignCard key={c.id} c={c} {...cardProps} />)}
        <button className="card card--hover" onClick={() => startWizard()} style={{ border: "1.5px dashed var(--border-2)", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 10, minHeight: 160, color: "var(--fg-3)", cursor: "pointer" }}>
          <span className="opp" style={{ width: 44, height: 44, borderRadius: 12, background: "var(--color-primary-tint)", color: "var(--color-secondary)" }}><Icon name="plus" size={22} /></span>
          <span style={{ fontWeight: 700, color: "var(--fg-1)" }}>New campaign</span>
          <span style={{ fontSize: 12 }}>7 steps · about 3 minutes</span>
        </button>
      </div>
      {detail && <CampaignDetailDrawer campaign={campaigns.find((c) => c.id === detail.id) || detail} onClose={() => setDetail(null)} onStatusChange={changeStatus} go={go} />}
    </div>
  );
}

function CampaignDetailDrawer({ campaign: c, onClose, onStatusChange, go }) {
  const { openAgent } = useApp();
  const st = CAMP_STATUS[c.status];
  const sv = serviceMeta(c.service);
  const agent = DATA.AGENTS.find((a) => a.id === c.agentId) || DATA.AGENTS.find((a) => a.name === c.agent);
  const sess = DATA.SESSIONS.find((s) => s.id === c.session);
  const leads = DATA.CONTACTS.filter((x) => x.campaign === c.id);
  const replyRate = c.sent ? Math.round((c.replied / c.sent) * 100) : 0;
  const goAgent = () => { onClose(); openAgent(agent); };
  // Delete is allowed for any NON-running campaign (paused/ready/draft/archived).
  const [confirmDel, setConfirmDel] = useState(false);
  const [deleting, setDeleting] = useState(false);
  const [delErr, setDelErr] = useState(null);
  const canDelete = c.status !== "outreach_active";
  const doDelete = () => {
    setDeleting(true); setDelErr(null);
    Actions.deleteCampaign(c.id)
      .then(() => { setConfirmDel(false); onClose(); })
      .catch((e) => setDelErr(/409|active/.test(e.message) ? "Pause the campaign before deleting it." : (e.message || "Delete failed")))
      .finally(() => setDeleting(false));
  };
  return (
    <Drawer onClose={onClose}>
      <DrawerHead title={c.name} sub={`${c.goal} · ${c.city}, ${c.country}`} onClose={onClose}
        right={<Badge tone={st.tone} dot={st.c}>{st.label}</Badge>} />
      <div style={{ overflowY: "auto", padding: 24, display: "flex", flexDirection: "column", gap: 16 }}>
        {/* primary action */}
        <div className="row" style={{ gap: 10 }}>
          {c.status === "outreach_active" && <Button variant="subtle" icon="pause" onClick={() => onStatusChange(c.id, "paused")}>Pause campaign</Button>}
          {(c.status === "paused" || c.status === "ready") && <Button variant="primary" icon="play" onClick={() => onStatusChange(c.id, "outreach_active")}>{c.status === "ready" ? "Launch" : "Resume"} campaign</Button>}
          <Button variant="dark" icon="message" onClick={() => { go("conversations"); onClose(); }}>Open conversations</Button>
          {canDelete && <button className="btn btn--subtle btn--sm" style={{ color: "var(--color-danger)", marginInlineStart: "auto" }} onClick={() => setConfirmDel(true)}><Icon name="trash" size={14} />Delete</button>}
        </div>
        {!canDelete && <p className="subtle" style={{ fontSize: 12, marginTop: -6 }}>Pause this campaign to enable deleting it.</p>}

        <Card title="Funnel"><Funnel c={c} /></Card>

        {/* Agent running this campaign — jump in to coach it */}
        <Card>
          <div className="between">
            <button className="row" style={{ gap: 12, background: "none", border: "none", cursor: "pointer", textAlign: "start", padding: 0 }} onClick={goAgent}>
              <Avatar name={c.agent} size="lg" color={agent?.color} />
              <div>
                <div style={{ fontWeight: 700, fontSize: 14 }}>{c.agent}</div>
                <div style={{ fontSize: 12, color: "var(--fg-4)" }}>{agent?.role} · writing every message</div>
              </div>
            </button>
            <Button variant="ghost" size="sm" icon="edit" onClick={goAgent}>Coach agent</Button>
          </div>
          <p className="subtle" style={{ fontSize: 12, marginTop: 12, lineHeight: 1.5 }}>Messages sounding off? Open the agent to add knowledge, fix wording, or teach it a correction.</p>
        </Card>

        <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          {[["Contacts", c.contacts, "users"], ["Sent", c.sent, "send"], ["Reply rate", replyRate + "%", "reply"], ["Won", c.won, "trophy"]].map(([k, v, ic]) => (
            <div key={k} className="card" style={{ padding: 16 }}>
              <div className="row" style={{ gap: 8, marginBottom: 6, color: "var(--fg-4)" }}><Icon name={ic} size={15} /><span style={{ fontSize: 12, fontWeight: 600 }}>{k}</span></div>
              <div style={{ fontSize: 24, fontWeight: 800, letterSpacing: "-0.02em" }}>{v}</div>
            </div>
          ))}
        </div>

        <Card title="Setup">
          <div className="col" style={{ gap: 12 }}>
            <div className="between"><span className="muted" style={{ fontSize: 13 }}>Service</span><Badge tone="neutral"><Icon name={sv.icon} size={13} />{sv.label}</Badge></div>
            <div className="between"><span className="muted" style={{ fontSize: 13 }}>Agent</span><button className="row" style={{ gap: 8, background: "none", border: "none", cursor: "pointer", padding: 0 }} onClick={goAgent}><Avatar name={c.agent} size="sm" color={agent?.color} /><span style={{ fontSize: 13, fontWeight: 600, color: "var(--color-secondary)" }}>{c.agent}</span><Icon name="chevronRight" size={14} style={{ color: "var(--fg-disabled)" }} /></button></div>
            <div className="between"><span className="muted" style={{ fontSize: 13 }}>WhatsApp line</span><WaChip state={sess?.state || "connected"} /></div>
            <div className="between"><span className="muted" style={{ fontSize: 13 }}>Tone</span><span style={{ fontSize: 13, fontWeight: 600 }}>{c.tone}</span></div>
            <div className="between"><span className="muted" style={{ fontSize: 13 }}>Created</span><span style={{ fontSize: 13 }}>{c.created}</span></div>
          </div>
        </Card>

        <Card title={`Leads in this campaign · ${leads.length}`} flush>
          {leads.length ? leads.map((l) => (
            <div key={l.id} className="between" style={{ padding: "12px 20px", borderBottom: "1px solid var(--border-1)" }}>
              <div className="row" style={{ gap: 10 }}><Avatar name={l.person} size="sm" /><div><div style={{ fontSize: 13, fontWeight: 600 }}>{l.name}</div><div style={{ fontSize: 11, color: "var(--fg-4)" }}>{l.lastReply}</div></div></div>
              <StatusPill status={l.status} />
            </div>
          )) : <div style={{ padding: 20 }}><span className="muted" style={{ fontSize: 13 }}>No leads yet — launch to start reaching contacts.</span></div>}
        </Card>
      </div>

      {/* Delete confirmation popup */}
      {confirmDel && (
        <Scrim onClose={() => !deleting && setConfirmDel(false)}>
          <div className="modal" style={{ width: 420, maxWidth: "92vw", padding: 24 }} onClick={(e) => e.stopPropagation()}>
            <div className="row" style={{ gap: 12, marginBottom: 12 }}>
              <span className="opp" style={{ width: 44, height: 44, borderRadius: 12, background: "var(--color-danger-soft)", color: "var(--color-danger)" }}><Icon name="trash" size={22} /></span>
              <div><div style={{ fontWeight: 800, fontSize: 16 }}>Delete campaign?</div><div style={{ fontSize: 13, color: "var(--fg-4)" }}>{c.name}</div></div>
            </div>
            <p style={{ fontSize: 13.5, color: "var(--fg-2)", lineHeight: 1.55 }}>This removes the campaign and its queued (not-yet-sent) messages. Your leads stay in the CRM. This can’t be undone.</p>
            {delErr && <div className="row" style={{ gap: 8, marginTop: 10, background: "var(--color-danger-soft)", color: "var(--color-danger)", borderRadius: 10, padding: "10px 12px", fontSize: 12.5 }}><Icon name="alert" size={14} />{delErr}</div>}
            <div className="row" style={{ gap: 10, justifyContent: "flex-end", marginTop: 18 }}>
              <Button variant="ghost" onClick={() => setConfirmDel(false)} disabled={deleting}>Cancel</Button>
              <button className="btn btn--sm" style={{ background: "var(--color-danger)", color: "#fff", borderColor: "var(--color-danger)" }} onClick={doDelete} disabled={deleting}><Icon name="trash" size={14} />{deleting ? "Deleting…" : "Delete campaign"}</button>
            </div>
          </div>
        </Scrim>
      )}
    </Drawer>
  );
}

/* ============================ WIZARD ==================================== */
const WIZ_STEPS = ["Contacts", "AI Agent", "WhatsApp", "Goal", "Drafts", "Review", "Launch"];
// Real contact groups derived live from the CRM — counts and recipients come
// from actual contacts (no hardcoded numbers). Each group carries contactIds so
// launch can enqueue the real recipients.
const STATUS_GROUP = { interested: "Interested leads", new: "New leads", replied: "Replied leads", followup: "Follow-up needed" };
function buildGroups(contacts) {
  const list = contacts || [];
  const out = [{ id: "all", name: "All contacts", icon: "users", src: "Live CRM", contactIds: list.map((c) => c.id), city: "", country: "" }];
  const by = (keyFn) => { const m = {}; list.forEach((c) => { const k = keyFn(c); if (k) (m[k] = m[k] || []).push(c.id); }); return m; };
  const byStatus = by((c) => c.status);
  Object.keys(STATUS_GROUP).forEach((st) => { if ((byStatus[st] || []).length) out.push({ id: "status_" + st, name: STATUS_GROUP[st], icon: "filter", src: "By CRM stage", contactIds: byStatus[st], city: "", country: "" }); });
  const byCity = by((c) => c.city);
  Object.entries(byCity).sort((a, b) => b[1].length - a[1].length).slice(0, 3).forEach(([city, ids]) => out.push({ id: "city_" + city, name: city + " stores", icon: "store", src: "By city", contactIds: ids, city, country: "" }));
  const byPlat = by((c) => (c.platform && c.platform !== "Unknown") ? c.platform : null);
  Object.entries(byPlat).sort((a, b) => b[1].length - a[1].length).slice(0, 3).forEach(([plat, ids]) => out.push({ id: "plat_" + plat, name: plat + " stores", icon: "layers", src: "By platform", contactIds: ids, city: "", country: "" }));
  return out.map((g) => ({ ...g, count: g.contactIds.length }));
}
const GOALS = [
  { id: "shopify", label: "Sell Shopify Service", desc: "Pitch a managed Shopify build or setup", icon: "store" },
  { id: "web", label: "Sell Website Design", desc: "Custom storefront or landing page", icon: "image" },
  { id: "retarget", label: "Retarget Interested Leads", desc: "Re-engage leads who went quiet", icon: "refresh" },
  { id: "call", label: "Book Discovery Call", desc: "Get a 20-minute intro call on the calendar", icon: "calendar" },
  { id: "migrate", label: "Migrate Salla / Zid → Shopify", desc: "Move an existing store with no SEO loss", icon: "layers" },
  { id: "seo", label: "Sell SEO Service", desc: "Organic growth and search audit offer", icon: "trending" },
];

function WizStepper({ step }) {
  return (
    <div className="stepper" style={{ overflowX: "auto" }}>
      {WIZ_STEPS.map((s, i) => (
        <React.Fragment key={s}>
          <div className={"step" + (i === step ? " is-active" : i < step ? " is-done" : "")}>
            <span className="step__num">{i < step ? <Icon name="check" size={15} /> : i + 1}</span>
            <span className="step__label" style={{ whiteSpace: "nowrap" }}>{s}</span>
          </div>
          {i < WIZ_STEPS.length - 1 && <span className={"step__line" + (i < step ? " is-done" : "")} />}
        </React.Fragment>
      ))}
    </div>
  );
}

const DEFAULT_BASE_MSG = "السلام عليكم، معك {agent} من ماكساب هَب 👋 لاحظت أن متجركم على سلة، ونقدر نساعدكم تنتقلون لشوبيفاي بإتمام طلبات أعلى وبدون توقف المبيعات. تحبون أرسل لكم نبذة سريعة عن الخطوات والتكلفة؟";

function SampleDraft({ agent, text, onChange, editable, onRegenerate, busy }) {
  const [editing, setEditing] = useState(false);
  const resolved = (text || DEFAULT_BASE_MSG).replace("{agent}", agent?.name || "نورة");
  return (
    <div style={{ background: "#fff", border: "1px solid var(--border-1)", borderRadius: 14, padding: 16 }}>
      <div className="between" style={{ marginBottom: 10 }}>
        <div className="row" style={{ gap: 8 }}><Avatar name={agent?.name} size="sm" color={agent?.color} /><b style={{ fontSize: 13 }}>{agent?.name}</b><Badge tone="lime">Base message</Badge></div>
        <span style={{ fontSize: 12, color: "var(--fg-4)" }}>preview</span>
      </div>
      {editing ? (
        <textarea className="textarea" rows={4} dir="rtl" value={text || DEFAULT_BASE_MSG} onChange={(e) => onChange && onChange(e.target.value)} style={{ marginBottom: 10 }} autoFocus />
      ) : (
        <p style={{ fontSize: 14, lineHeight: 1.6, color: "var(--fg-2)" }} dir="rtl">{resolved}</p>
      )}
      <div className="row" style={{ gap: 6, marginTop: 12 }}>
        {editable && (editing
          ? <button className="btn btn--primary btn--sm" onClick={() => setEditing(false)}><Icon name="check" size={14} />Done editing</button>
          : <button className="btn btn--subtle btn--sm" onClick={() => setEditing(true)}><Icon name="edit" size={14} />Edit message</button>)}
        {onRegenerate && <button className="btn btn--subtle btn--sm" disabled={busy} onClick={onRegenerate}><Icon name="refresh" size={14} />{busy ? "Regenerating…" : "Regenerate"}</button>}
      </div>
      {editable && <p className="subtle" style={{ fontSize: 12, marginTop: 10 }}>Your edits become the base for all {"{contact}"} messages — the agent personalises each one.</p>}
    </div>
  );
}

// Campaign Builder panel (Blocker 7) — Templates / Dynamic filters / Saved
// audiences. Every action hits the real backend; counts are live. Selecting a
// template or building an audience flows back into the wizard via callbacks.
function CampaignBuilderPanel({ onAudience, onTemplate }) {
  const [tab, setTab] = useState("templates"); // templates | filters | saved
  const [templates, setTemplates] = useState(null);
  const [saved, setSaved] = useState(null);
  const [filters, setFilters] = useState({});
  const [preview, setPreview] = useState(null);
  const [busy, setBusy] = useState(false);
  const [saveName, setSaveName] = useState("");
  React.useEffect(() => { API.campaignBuilder.templates().then((r) => setTemplates(r.templates || [])).catch(() => setTemplates([])); }, []);
  React.useEffect(() => { if (tab === "saved" && saved === null) API.campaignBuilder.audiences().then((r) => setSaved(r.audiences || [])).catch(() => setSaved([])); }, [tab]);

  const STATUSES = ["new", "contacted", "replied", "interested", "proposal", "followup", "won", "lost"];
  const PLATFORMS = ["Shopify", "Salla", "Zid", "WooCommerce", "Custom", "Unknown"];
  const toggleIn = (key, val) => setFilters((f) => { const arr = new Set(f[key] || []); arr.has(val) ? arr.delete(val) : arr.add(val); return { ...f, [key]: [...arr] }; });
  const setF = (key, val) => setFilters((f) => ({ ...f, [key]: val }));
  const runPreview = (f = filters) => { setBusy(true); API.campaignBuilder.previewAudience(f).then(setPreview).catch(() => setPreview({ count: 0, contactIds: [] })).finally(() => setBusy(false)); };
  const useFiltered = () => { if (preview) onAudience({ name: "Filtered audience", contactIds: preview.contactIds, src: "Dynamic filters", filters }); };
  const saveAudience = () => { if (!saveName.trim()) return; API.campaignBuilder.createAudience({ name: saveName.trim(), filters }).then(() => { setSaveName(""); setSaved(null); setTab("saved"); }).catch(() => {}); };
  const useSaved = (a) => { API.campaignBuilder.previewAudience(a.filters).then((p) => onAudience({ name: a.name, contactIds: p.contactIds, src: "Saved audience" })).catch(() => {}); };
  const delSaved = (id) => { API.campaignBuilder.deleteAudience(id).then(() => setSaved((s) => (s || []).filter((a) => a.id !== id))).catch(() => {}); };
  const applyTpl = (t) => {
    API.campaignBuilder.applyTemplate(t.id).then((r) => {
      onTemplate && onTemplate({ goal: r.draft.goal, message: null, agentId: r.draft.agentId, templateId: t.id, name: r.draft.name, strategy: r.draft.strategy });
      if (r.audience && r.audience.contactIds && r.audience.contactIds.length) onAudience({ name: t.name + " audience", contactIds: r.audience.contactIds, src: "Template", filters: r.filters });
    }).catch(() => {});
  };

  const chip = (on, label, onClick, count) => (
    <button key={label} onClick={onClick} style={{ height: 30, padding: "0 12px", borderRadius: 999, fontSize: 12.5, fontWeight: 600, border: "1px solid " + (on ? "var(--color-secondary)" : "var(--border-2)"), background: on ? "var(--color-secondary)" : "#fff", color: on ? "#fff" : "var(--fg-2)" }}>{label}{count != null && <span style={{ opacity: 0.6, marginInlineStart: 4 }}>{count}</span>}</button>
  );
  return (
    <div className="col" style={{ gap: 14, border: "1px solid var(--border-1)", borderRadius: 14, padding: 16, background: "var(--bg-2)" }}>
      <div className="row" style={{ gap: 4 }}>
        {[["templates", "Templates", "sparkles"], ["filters", "Dynamic filters", "filter"], ["saved", "Saved audiences", "bookmark"]].map(([k, lbl, ic]) => (
          <button key={k} onClick={() => setTab(k)} className="row" style={{ gap: 6, padding: "7px 12px", fontSize: 12.5, fontWeight: 700, borderRadius: 8, cursor: "pointer", border: "none", color: tab === k ? "var(--color-secondary)" : "var(--fg-3)", background: tab === k ? "#fff" : "transparent" }}><Icon name={ic} size={14} />{lbl}</button>
        ))}
      </div>

      {tab === "templates" && (
        <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 10 }}>
          {templates === null ? <p className="muted" style={{ fontSize: 13 }}>Loading templates…</p> : templates.map((t) => (
            <button key={t.id} className="optcard" onClick={() => applyTpl(t)} style={{ textAlign: "start" }}>
              <span className="optcard__icon" style={{ background: "var(--color-primary-tint)", color: "var(--color-secondary)" }}><Icon name="megaphone" size={18} /></span>
              <div style={{ flex: 1, minWidth: 0 }}>
                <b style={{ fontSize: 13.5 }}>{t.name}</b>
                <div className="muted" style={{ fontSize: 11.5, marginTop: 2, lineHeight: 1.4 }} dir="auto">{t.objective}</div>
                <div className="row" style={{ gap: 6, marginTop: 6 }}><Badge tone="neutral">{t.nextStep}</Badge>{typeof t.audiencePreview === "number" && <Badge tone="blue">{t.audiencePreview} match</Badge>}</div>
              </div>
            </button>
          ))}
        </div>
      )}

      {tab === "filters" && (
        <div className="col" style={{ gap: 12 }}>
          <div><div className="muted" style={{ fontSize: 12, marginBottom: 6 }}>CRM status</div><div className="row wrap" style={{ gap: 6 }}>{STATUSES.map((s) => chip((filters.crmStatus || []).includes(s), s, () => toggleIn("crmStatus", s)))}</div></div>
          <div><div className="muted" style={{ fontSize: 12, marginBottom: 6 }}>Platform</div><div className="row wrap" style={{ gap: 6 }}>{PLATFORMS.map((s) => chip((filters.platform || []).includes(s), s, () => toggleIn("platform", s)))}</div></div>
          <div className="row wrap" style={{ gap: 10 }}>
            <Field label="City"><input className="input" style={{ width: 140 }} value={filters.city || ""} onChange={(e) => setF("city", e.target.value)} placeholder="Riyadh" /></Field>
            <Field label="Website intel"><select className="select" value={filters.websiteIntel || ""} onChange={(e) => setF("websiteIntel", e.target.value || undefined)}><option value="">Any</option>{["not_analyzed", "queued", "analyzing", "completed", "failed"].map((s) => <option key={s} value={s}>{s}</option>)}</select></Field>
            <Field label="BANT ≥"><input className="input" type="number" style={{ width: 80 }} value={filters.bantMin ?? ""} onChange={(e) => setF("bantMin", e.target.value)} placeholder="0" /></Field>
          </div>
          <div className="row wrap" style={{ gap: 8 }}>
            {chip(filters.hasWebsite === true, "Has website", () => setF("hasWebsite", filters.hasWebsite === true ? undefined : true))}
            {chip(filters.hasMaps === true, "Has Google Maps", () => setF("hasMaps", filters.hasMaps === true ? undefined : true))}
            {chip(filters.campaignHistory === "never", "Never in a campaign", () => setF("campaignHistory", filters.campaignHistory === "never" ? undefined : "never"))}
          </div>
          <div className="between" style={{ gap: 10, flexWrap: "wrap" }}>
            <Button variant="dark" size="sm" icon="search" disabled={busy} onClick={() => runPreview()}>{busy ? "Resolving…" : "Preview audience"}</Button>
            {preview && <span style={{ fontSize: 13, fontWeight: 700 }}>{preview.count} contact{preview.count === 1 ? "" : "s"} match</span>}
          </div>
          {preview && (
            <div className="row wrap" style={{ gap: 10, alignItems: "center" }}>
              <Button variant="primary" size="sm" icon="check" disabled={!preview.count} onClick={useFiltered}>Use this audience</Button>
              <input className="input" style={{ width: 160 }} value={saveName} onChange={(e) => setSaveName(e.target.value)} placeholder="Save as…" />
              <Button variant="ghost" size="sm" icon="bookmark" disabled={!saveName.trim()} onClick={saveAudience}>Save audience</Button>
            </div>
          )}
        </div>
      )}

      {tab === "saved" && (
        <div className="col" style={{ gap: 8 }}>
          {saved === null ? <p className="muted" style={{ fontSize: 13 }}>Loading…</p> : saved.length === 0 ? <p className="muted" style={{ fontSize: 13 }}>No saved audiences yet — build one in Dynamic filters and save it.</p> : saved.map((a) => (
            <div key={a.id} className="between" style={{ background: "#fff", border: "1px solid var(--border-1)", borderRadius: 10, padding: "10px 12px" }}>
              <div><div style={{ fontWeight: 700, fontSize: 13 }}>{a.name}</div><div className="muted" style={{ fontSize: 11.5 }}>{a.count} contacts</div></div>
              <div className="row" style={{ gap: 6 }}><Button variant="ghost" size="sm" onClick={() => useSaved(a)}>Use</Button><button className="iconbtn" onClick={() => delSaved(a.id)}><Icon name="trash" size={15} /></button></div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function CampaignWizard({ onClose, preset }) {
  const { startImport, go } = useApp();
  const data = useStore();
  const [step, setStep] = useState(0);
  // Campaign Builder: a custom audience (dynamic filters / saved / template) and
  // the template that seeds the campaign context (Blocker 7).
  const [customGroup, setCustomGroup] = useState(null);
  const [templateId, setTemplateId] = useState(null);
  const [showBuilder, setShowBuilder] = useState(false);
  const dynamicGroups = buildGroups(data.CONTACTS);
  const presetReal = preset?.group && Array.isArray(preset.group.contactIds) && preset.group.contactIds.length ? preset.group : null;
  const groups = [customGroup, presetReal, ...dynamicGroups].filter(Boolean);
  const [group, setGroup] = useState((presetReal && presetReal.id) || (dynamicGroups[0] && dynamicGroups[0].id) || "all");
  // Build/select a custom audience from the builder panel.
  const applyAudience = (a) => { const g = { id: "custom_aud", name: a.name, count: (a.contactIds || []).length, contactIds: a.contactIds || [], src: a.src || "Custom audience", icon: "filter", country: "", city: "", fromImport: true }; setCustomGroup(g); setGroup("custom_aud"); };
  const applyTemplateMeta = (t) => { if (t.goal) { setName((n) => n || t.name || ""); } if (t.agentId) setAgentId(t.agentId); if (t.templateId) setTemplateId(t.templateId); };
  // default to a real, existing agent / line so the wizard never derefs an
  // id that was renamed or removed (prefer the seeded sales agent / main line).
  const [agentId, setAgentId] = useState(() => ((DATA.AGENTS || []).some((a) => a.id === "ag_sales") ? "ag_sales" : ((DATA.AGENTS || [])[0]?.id || "")));
  // sender routing: "auto" = rotate across all active lines (safe default), or a
  // specific real line id (chosen from the connected WhatsApp lines below).
  const [session, setSession] = useState("auto");
  const [goal, setGoal] = useState(preset?.goal || "shopify");
  const [name, setName] = useState("");
  const [customGoals, setCustomGoals] = useState([]);
  const [addingGoal, setAddingGoal] = useState(false);
  const [newGoal, setNewGoal] = useState({ label: "", desc: "" });
  const [baseMsg, setBaseMsg] = useState(DEFAULT_BASE_MSG);
  const [language, setLanguage] = useState("arabic");
  const [generating, setGenerating] = useState(false);
  const [generated, setGenerated] = useState(false);
  const [launching, setLaunching] = useState(false);
  const [launchErr, setLaunchErr] = useState(null);
  const [noSender, setNoSender] = useState(false);
  const [enqueued, setEnqueued] = useState(0);
  const [sendMode, setSendMode] = useState("approval"); // approval-only (safe default) | live
  const [launchedMode, setLaunchedMode] = useState("approval");
  const [waStatus, setWaStatus] = useState(null);
  React.useEffect(() => { API.whatsapp.status().then(setWaStatus).catch(() => {}); }, [step]);
  const [drafts, setDrafts] = useState([]);

  // resolve with hard fallbacks — the render must never crash on a missing
  // agent / line / group (the reported "screen closes / needs refresh" bug).
  const agent = (DATA.AGENTS || []).find((a) => a.id === agentId) || (DATA.AGENTS || [])[0] || { id: null, name: "Agent", role: "Sales Consultant", service: "shopify", style: "Consultative", lang: "ar", color: "#00654B" };
  const grp = groups.find((g) => g.id === group) || groups[0] || { id: "all", name: "All contacts", count: 0, contactIds: [], country: "", city: "" };
  // real connected WhatsApp lines (web mode) — the live-send sender pool
  const webMode = waStatus?.channel === "web";
  const waLines = waStatus?.lines || [];
  const activeLines = waLines.filter((l) => l.canSend);
  const selectedLine = session !== "auto" ? waLines.find((l) => l.id === session) : null;
  const sess = { id: session, label: session === "auto" ? (activeLines.length ? `Auto-rotate · ${activeLines.length} active line${activeLines.length > 1 ? "s" : ""}` : "Auto-rotate (no active line)") : (selectedLine?.label || "Selected line") };
  const allGoals = [...GOALS, ...customGoals];
  const goalObj = allGoals.find((g) => g.id === goal) || GOALS[0];
  const flagged = drafts.filter((d) => (d.confidence ?? 1) < 0.85).length;

  const addGoal = () => {
    if (!newGoal.label.trim()) return;
    const g = { id: "custom_" + Date.now(), label: newGoal.label.trim(), desc: newGoal.desc.trim() || "Custom goal for this campaign", icon: "target", custom: true };
    setCustomGoals([...customGoals, g]);
    setGoal(g.id);
    setNewGoal({ label: "", desc: "" });
    setAddingGoal(false);
  };

  const runGenerate = async () => {
    setGenerating(true);
    try {
      const r = await API.ai.generateDrafts({ service: agent.service, agentId, goal: goalObj.label, tone: agent.style, count: 3, language });
      if (r.drafts && r.drafts.length) { setDrafts(r.drafts); setBaseMsg(r.drafts[0].draft); }
    } catch (e) { console.error("generate drafts failed", e); }
    setGenerating(false);
    setGenerated(true);
  };

  const launch = async () => {
    setLaunching(true);
    setLaunchErr(null);
    setNoSender(false);
    try {
      // the actual edited / regenerated message (with the agent name resolved)
      const message = (baseMsg || DEFAULT_BASE_MSG).replace(/\{agent\}/g, agent?.name || "");
      const recipients = (grp.contactIds || []).slice();
      const camp = await Actions.createCampaign({
        name: name || `${goalObj.label} · ${grp.name}`,
        goal: goalObj.label, service: agent.service, agentId, session,
        country: grp.country, city: grp.city, contacts: recipients.length,
        message, language, templateId: templateId || undefined,
        tone: agent.style, locale: agent.lang === "ar" ? "Saudi professional" : "GCC neutral",
        launch: true,
      });
      // Approval-only (default): drafts → approval queue, no sender needed.
      // Live: enqueue real sends — needs an active WhatsApp sender.
      if (recipients.length) {
        const r = await API.messaging.campaign({ campaignId: camp.id, contactIds: recipients, text: message, mode: sendMode, senderIds: session !== "auto" ? [session] : null, rotation: "auto" });
        setEnqueued((r && (r.jobs ?? r.drafts)) || 0);
        setLaunchedMode((r && r.mode) || sendMode);
      } else {
        setLaunchedMode(sendMode);
      }
      setStep(6);
    } catch (e) {
      console.error("create/launch campaign failed", e);
      if (/no_active_senders/.test(e.message || "")) {
        setNoSender(true);
        setLaunchErr("No active WhatsApp sender connected yet. Switch to “Save drafts for approval”, or connect WhatsApp in Settings before sending live.");
      } else {
        setLaunchErr(e.message || "Launch failed");
      }
    }
    setLaunching(false);
  };

  const next = () => {
    if (step === 4 && !generated) { runGenerate(); return; }
    if (step === 5) { launch(); return; }
    setStep((s) => Math.min(s + 1, WIZ_STEPS.length - 1));
  };
  const busy = generating || launching;
  // Live-send needs an active sender; in web mode that's the real connection.
  const liveBlocked = sendMode === "live" && waStatus?.channel === "web" && !waStatus?.activeSender;

  return (
    <Scrim onClose={onClose}>
      <div className="modal" style={{ width: 920, maxWidth: "94vw", height: "88vh", maxHeight: 760, display: "flex", flexDirection: "column", padding: 0 }} onClick={(e) => e.stopPropagation()}>
        {/* header */}
        <div className="between" style={{ padding: "18px 24px", borderBottom: "1px solid var(--border-1)" }}>
          <div><div style={{ fontWeight: 800, fontSize: 16 }}>New campaign</div><div style={{ fontSize: 12, color: "var(--fg-4)" }}>Step {step + 1} of {WIZ_STEPS.length} · {WIZ_STEPS[step]}</div></div>
          <button className="iconbtn" onClick={onClose}><Icon name="x" size={20} /></button>
        </div>
        <div style={{ padding: "16px 24px", borderBottom: "1px solid var(--border-1)", background: "var(--bg-2)", overflowX: "auto" }}><WizStepper step={step} /></div>

        {/* body */}
        <div style={{ flex: 1, overflowY: "auto", padding: 28 }}>
          <FallbackBanner />
          {step === 0 && (
            <div className="fade-up">
              <h5 style={{ marginBottom: 4 }}>Choose your audience</h5>
              <p className="muted" style={{ fontSize: 14, marginBottom: 16 }}>Pick a quick group, build a targeted audience with filters, reuse a saved audience, or start from a template.</p>
              {/* Audience source: quick groups (below) + the builder (templates / dynamic filters / saved audiences) */}
              <div className="row" style={{ gap: 10, marginBottom: 16 }}>
                <Button variant={showBuilder ? "primary" : "dark"} size="sm" icon="sparkles" onClick={() => setShowBuilder((v) => !v)}>{showBuilder ? "Hide builder" : "Templates & filters"}</Button>
                <button className="btn btn--ghost btn--sm" onClick={() => { onClose(); startImport(); }}><Icon name="upload" size={16} />Import a new list</button>
              </div>
              {showBuilder && <div style={{ marginBottom: 18 }}><CampaignBuilderPanel onAudience={applyAudience} onTemplate={applyTemplateMeta} /></div>}
              <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 12 }}>
                {groups.map((g) => (
                  <button key={g.id} className={"optcard" + (group === g.id ? " is-selected" : "")} onClick={() => setGroup(g.id)}>
                    <span className="optcard__icon" style={{ background: g.fromImport ? "var(--color-primary-tint)" : "var(--bg-2)", color: "var(--color-secondary)" }}><Icon name={g.icon} size={20} /></span>
                    <div style={{ flex: 1 }}>
                      <div className="between"><b style={{ fontSize: 14 }}>{g.name}</b>{group === g.id && <Icon name="checkcircle" size={18} style={{ color: "var(--color-secondary)" }} />}</div>
                      <div style={{ fontSize: 12, color: "var(--fg-4)", marginTop: 3 }}>{g.count} contacts · {g.src}</div>
                    </div>
                  </button>
                ))}
              </div>
              {templateId && <div className="row" style={{ gap: 8, marginTop: 14, background: "var(--color-primary-tint-soft)", border: "1px solid var(--color-primary-tint)", borderRadius: 10, padding: "10px 12px", fontSize: 12.5 }}><Icon name="sparkles" size={14} style={{ color: "var(--color-secondary)" }} />Template applied — its strategy will shape every message the agent writes.</div>}
            </div>
          )}

          {step === 1 && (
            <div className="fade-up">
              <h5 style={{ marginBottom: 4 }}>Choose an AI agent</h5>
              <p className="muted" style={{ fontSize: 14, marginBottom: 20 }}>This agent writes and sends the messages. Each has a specialty and a trust level it earned.</p>
              <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 12 }}>
                {DATA.AGENTS.map((a) => (
                  <button key={a.id} className={"optcard" + (agentId === a.id ? " is-selected" : "")} onClick={() => setAgentId(a.id)}>
                    <Avatar name={a.name} color={a.color} />
                    <div style={{ flex: 1 }}>
                      <div className="between"><b style={{ fontSize: 14 }}>{a.name}</b>{agentId === a.id && <Icon name="checkcircle" size={18} style={{ color: "var(--color-secondary)" }} />}</div>
                      <div style={{ fontSize: 12, color: "var(--fg-3)", marginTop: 2 }}>{a.role}</div>
                      <div className="row" style={{ gap: 8, marginTop: 8 }}><Badge tone="neutral">{a.winRate}% win</Badge><Badge tone="lime">Trust {a.trust}/5</Badge></div>
                    </div>
                  </button>
                ))}
              </div>
            </div>
          )}

          {step === 2 && (
            <div className="fade-up">
              <h5 style={{ marginBottom: 4 }}>Choose how to send</h5>
              <p className="muted" style={{ fontSize: 14, marginBottom: 20 }}>Live campaigns send from your connected WhatsApp lines. Connected lines only — no silent failures.</p>
              {!webMode ? (
                <div className="row" style={{ gap: 10, background: "var(--bg-2)", border: "1px solid var(--border-1)", borderRadius: 12, padding: 14, fontSize: 13, color: "var(--fg-2)" }}>
                  <Icon name="info" size={16} style={{ color: "var(--color-blue)", flexShrink: 0 }} />Sends use your configured WhatsApp sender. To link real WhatsApp lines (a separate QR / phone per number) run in WhatsApp Web mode and add lines in Settings.
                </div>
              ) : activeLines.length === 0 ? (
                <div className="col" style={{ gap: 12 }}>
                  <div className="row" style={{ gap: 10, background: "var(--bg-2)", border: "1px solid var(--border-1)", borderRadius: 12, padding: 14, fontSize: 13, color: "var(--fg-2)" }}>
                    <Icon name="alert" size={16} style={{ color: "var(--color-warning)", flexShrink: 0, marginTop: 1 }} />No active WhatsApp line yet. You can still <b>save drafts for approval</b> — connect a line to send live.
                  </div>
                  <Button variant="ghost" icon="settings" onClick={() => { onClose(); go("settings"); }}>Connect a line in Settings</Button>
                </div>
              ) : (
                <div className="col" style={{ gap: 12 }}>
                  {/* auto-rotate (recommended) */}
                  <button className={"optcard" + (session === "auto" ? " is-selected" : "")} onClick={() => setSession("auto")}>
                    <span className="optcard__icon" style={{ background: "var(--color-primary-tint)", color: "var(--color-secondary)" }}><Icon name="refresh" size={20} /></span>
                    <div style={{ flex: 1 }}>
                      <div className="between"><b style={{ fontSize: 14 }}>Auto-rotate across active lines</b>{session === "auto" && <Icon name="checkcircle" size={18} style={{ color: "var(--color-secondary)" }} />}</div>
                      <div style={{ fontSize: 12, color: "var(--fg-4)", marginTop: 3 }}>{activeLines.length} active line{activeLines.length > 1 ? "s" : ""} · spreads sends to reduce per-number risk (recommended)</div>
                    </div>
                  </button>
                  {/* pick one specific active line */}
                  {activeLines.map((l) => (
                    <button key={l.id} className={"optcard" + (session === l.id ? " is-selected" : "")} onClick={() => setSession(l.id)}>
                      <span className="optcard__icon" style={{ background: "var(--bg-2)", color: "var(--fg-3)" }}><Icon name="phoneDevice" size={20} /></span>
                      <div style={{ flex: 1 }}>
                        <div className="between"><b style={{ fontSize: 14 }}>{l.label}</b>{session === l.id ? <Icon name="checkcircle" size={18} style={{ color: "var(--color-secondary)" }} /> : <WaChip state="connected" />}</div>
                        <div style={{ fontSize: 12, color: "var(--fg-4)", marginTop: 3 }}>{l.phoneNumber ? `+${l.phoneNumber} · ` : ""}{l.sentToday || 0}/{l.dailyLimit ?? 500} sent today</div>
                      </div>
                    </button>
                  ))}
                  {/* not-sendable lines, shown disabled for honesty */}
                  {waLines.filter((l) => !l.canSend).map((l) => (
                    <button key={l.id} className="optcard" disabled style={{ opacity: 0.55 }}>
                      <span className="optcard__icon" style={{ background: "var(--bg-2)", color: "var(--fg-3)" }}><Icon name="phoneDevice" size={20} /></span>
                      <div style={{ flex: 1 }}>
                        <div className="between"><b style={{ fontSize: 14 }}>{l.label}</b><WaChip state={l.status === "connected" ? "connected" : "disconnected"} /></div>
                        <div style={{ fontSize: 12, color: "var(--color-warning)", marginTop: 3, fontWeight: 600 }}>{l.enabled === false ? "Disabled" : "Not connected"} — connect in Settings to use it.</div>
                      </div>
                    </button>
                  ))}
                  {activeLines.length === 1 && (
                    <div className="row" style={{ gap: 8, background: "var(--color-warning-soft, #FEF3C7)", border: "1px solid #FDE68A", borderRadius: 10, padding: "10px 12px", color: "#92400E", fontSize: 12.5, alignItems: "center" }}>
                      <Icon name="alert" size={14} style={{ flexShrink: 0 }} />High volume from one number increases ban risk. Add more lines for safer rotation.
                      <button className="btn btn--ghost btn--sm" style={{ marginInlineStart: "auto" }} onClick={() => { onClose(); go("settings"); }}>Settings</button>
                    </div>
                  )}
                </div>
              )}
            </div>
          )}

          {step === 3 && (
            <div className="fade-up">
              <h5 style={{ marginBottom: 4 }}>What's the goal?</h5>
              <p className="muted" style={{ fontSize: 14, marginBottom: 20 }}>The agent shapes every message around this outcome. Add your own if none fit.</p>
              <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 12 }}>
                {allGoals.map((g) => (
                  <button key={g.id} className={"optcard" + (goal === g.id ? " is-selected" : "")} onClick={() => setGoal(g.id)}>
                    <span className="optcard__icon" style={{ background: "var(--color-primary-tint-soft)", color: "var(--color-secondary)" }}><Icon name={g.icon} size={20} /></span>
                    <div style={{ flex: 1 }}>
                      <div className="between"><b style={{ fontSize: 14 }}>{g.label}{g.custom && <Badge tone="purple" >Custom</Badge>}</b>{goal === g.id && <Icon name="checkcircle" size={18} style={{ color: "var(--color-secondary)" }} />}</div>
                      <div style={{ fontSize: 12, color: "var(--fg-4)", marginTop: 3 }}>{g.desc}</div>
                    </div>
                  </button>
                ))}
                {!addingGoal && (
                  <button className="optcard" onClick={() => setAddingGoal(true)} style={{ borderStyle: "dashed", justifyContent: "center", alignItems: "center", color: "var(--fg-3)" }}>
                    <span className="optcard__icon" style={{ background: "var(--bg-2)", color: "var(--color-secondary)" }}><Icon name="plus" size={20} /></span>
                    <div><b style={{ fontSize: 14, color: "var(--fg-1)" }}>Add a goal</b><div style={{ fontSize: 12, color: "var(--fg-4)", marginTop: 3 }}>Write a custom outcome</div></div>
                  </button>
                )}
              </div>
              {addingGoal && (
                <Card style={{ marginTop: 12, border: "1.5px solid var(--color-secondary)" }}>
                  <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 12 }}>
                    <Field label="Goal name"><input className="input" autoFocus placeholder="e.g. Sell loyalty program" value={newGoal.label} onChange={(e) => setNewGoal({ ...newGoal, label: e.target.value })} onKeyDown={(e) => e.key === "Enter" && addGoal()} /></Field>
                    <Field label="Short description"><input className="input" placeholder="What should the agent achieve?" value={newGoal.desc} onChange={(e) => setNewGoal({ ...newGoal, desc: e.target.value })} onKeyDown={(e) => e.key === "Enter" && addGoal()} /></Field>
                  </div>
                  <div className="row" style={{ gap: 8, justifyContent: "flex-end" }}>
                    <Button variant="ghost" size="sm" onClick={() => { setAddingGoal(false); setNewGoal({ label: "", desc: "" }); }}>Cancel</Button>
                    <Button variant="primary" size="sm" icon="plus" onClick={addGoal}>Add goal</Button>
                  </div>
                </Card>
              )}
              <div style={{ marginTop: 20, maxWidth: 460 }}>
                <Field label="Campaign name" hint="We suggested one — edit if you like.">
                  <input className="input" value={name || `${goalObj.label} · ${grp.name}`} onChange={(e) => setName(e.target.value)} />
                </Field>
              </div>
            </div>
          )}

          {step === 4 && (
            <div className="fade-up" style={{ height: "100%" }}>
              <h5 style={{ marginBottom: 4 }}>Generate drafts</h5>
              <p className="muted" style={{ fontSize: 14, marginBottom: 16 }}>{agent.name} will write a personalised first message for each of the {grp.count} contacts.</p>
              <div style={{ maxWidth: 360, marginBottom: 18 }}>
                <Field label="Message language" hint="The agent writes (and replies) in this language for the whole campaign.">
                  <select className="select" value={language} onChange={(e) => { setLanguage(e.target.value); setGenerated(false); }}>
                    <option value="arabic">Arabic (MSA)</option>
                    <option value="saudi">Saudi Arabic</option>
                    <option value="gulf">Gulf Arabic</option>
                    <option value="egyptian">Egyptian Arabic</option>
                    <option value="english">English</option>
                    <option value="bilingual">Bilingual (Arabic + English)</option>
                  </select>
                </Field>
              </div>
              {!generated && !generating && (
                <div style={{ textAlign: "center", padding: "40px 0" }}>
                  <span className="opp" style={{ width: 64, height: 64, borderRadius: 18, background: "var(--color-primary-tint)", color: "var(--color-secondary)", margin: "0 auto 18px" }}><Icon name="sparkles" size={30} /></span>
                  <div style={{ fontWeight: 700, marginBottom: 6 }}>Ready when you are</div>
                  <p className="muted" style={{ fontSize: 13, maxWidth: 360, margin: "0 auto" }}>Each draft is reviewed by the agent's self-check before it reaches your approval queue.</p>
                  <Button variant="primary" icon="sparkles" style={{ marginTop: 18 }} onClick={next}>Generate {grp.count} drafts</Button>
                </div>
              )}
              {generating && (
                <div style={{ textAlign: "center", padding: "40px 0" }}>
                  <div className="skel" style={{ width: 64, height: 64, borderRadius: 18, margin: "0 auto 18px" }} />
                  <div style={{ fontWeight: 700, marginBottom: 16 }}>Writing drafts…</div>
                  <div style={{ maxWidth: 420, margin: "0 auto" }}>
                    {[0, 1, 2].map((i) => <div key={i} className="skel" style={{ height: 14, margin: "8px 0", width: ["100%", "92%", "70%"][i] }} />)}
                  </div>
                </div>
              )}
              {generated && (
                <div>
                  <div className="row" style={{ gap: 8, marginBottom: 14, color: "var(--color-success)", fontWeight: 600, fontSize: 14 }}><Icon name="checkcircle" size={18} />{grp.count} drafts ready{flagged ? ` · ${flagged} flagged for a closer look` : " · all passed self-check"}</div>
                  <SampleDraft agent={agent} text={baseMsg} onChange={setBaseMsg} editable onRegenerate={runGenerate} busy={generating} />
                </div>
              )}
            </div>
          )}

          {step === 5 && (
            <div className="fade-up">
              <h5 style={{ marginBottom: 16 }}>Review &amp; confirm</h5>
              <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 16 }}>
                {[["Contacts", `${grp.count} · ${grp.name}`, "users"], ["Agent", `${agent.name} · ${agent.role}`, "bot"],
                  ["WhatsApp line", sess.label, "phoneDevice"], ["Goal", goalObj.label, "target"]].map(([k, v, ic]) => (
                  <div key={k} className="card" style={{ padding: 16 }}>
                    <div className="row" style={{ gap: 8, marginBottom: 6, color: "var(--fg-4)" }}><Icon name={ic} size={16} /><span style={{ fontSize: 12, fontWeight: 600 }}>{k}</span></div>
                    <div style={{ fontWeight: 700, fontSize: 14 }}>{v}</div>
                  </div>
                ))}
              </div>
              <SampleDraft agent={agent} text={baseMsg} onChange={setBaseMsg} editable onRegenerate={runGenerate} busy={generating} />
              {/* How to launch — approval-only (safe, no WhatsApp needed) vs live send */}
              {(() => {
                const webMode = waStatus?.channel === "web";
                const liveActive = webMode ? !!waStatus?.activeSender : true;
                const senderCount = webMode ? (waStatus?.activeSenderCount ?? (waStatus?.activeSender ? 1 : 0)) : null;
                const connNum = waStatus?.connectedNumber;
                const liveDesc = webMode
                  ? (liveActive ? `Sends now via your connected WhatsApp${connNum ? ` (+${connNum})` : ""}.` : "No active WhatsApp sender connected. Connect WhatsApp first or use approval-only.")
                  : "Messages are queued and sent via WhatsApp.";
                const liveBlocked = sendMode === "live" && webMode && !liveActive;
                return (
                  <>
                    <div style={{ marginTop: 16, fontSize: 12, fontWeight: 700, color: "var(--fg-4)", marginBottom: 8 }}>HOW TO LAUNCH</div>
                    <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 10 }}>
                      {[["approval", "shield", "Save drafts for approval", "Recommended. Each message lands in Conversations to review before it sends. No WhatsApp connection needed."],
                        ["live", "send", "Send live now", liveDesc]].map(([m, ic, t, d]) => (
                        <button key={m} type="button" onClick={() => { setSendMode(m); setNoSender(false); setLaunchErr(null); }} className="card" style={{ textAlign: "left", padding: 14, cursor: "pointer", border: sendMode === m ? "2px solid var(--color-secondary)" : "1px solid var(--border-1)", background: sendMode === m ? "var(--color-primary-tint-soft)" : "#fff" }}>
                          <div className="between"><div className="row" style={{ gap: 8, fontWeight: 700, fontSize: 13.5 }}><Icon name={ic} size={16} />{t}</div>
                            {m === "live" && senderCount != null && <Badge tone={liveActive ? "green" : "neutral"} dot={liveActive ? "#22C55E" : "#9CA3AF"}>{senderCount} active</Badge>}</div>
                          <div className="muted" style={{ fontSize: 12, marginTop: 4 }}>{d}</div>
                        </button>
                      ))}
                    </div>
                    {liveBlocked && <div className="row" style={{ gap: 10, marginTop: 12, background: "var(--color-warn-soft, var(--bg-2))", color: "var(--fg-2)", borderRadius: 12, padding: "12px 14px", fontSize: 13 }}><Icon name="alert" size={16} />No active WhatsApp sender. Connect WhatsApp, or use “Save drafts for approval”.</div>}
                    {(noSender || liveBlocked) && <Button variant="ghost" icon="settings" style={{ marginTop: 10 }} onClick={() => { onClose(); go("settings"); }}>Open WhatsApp Settings</Button>}
                  </>
                );
              })()}
              {launchErr && <div className="row" style={{ gap: 10, marginTop: 12, background: "var(--color-danger-soft)", color: "var(--color-danger)", borderRadius: 12, padding: "12px 14px", fontSize: 13 }}><Icon name="alert" size={16} />{launchErr}</div>}
            </div>
          )}

          {step === 6 && (
            <div className="fade-up" style={{ textAlign: "center", padding: "30px 0" }}>
              <span className="opp" style={{ width: 76, height: 76, borderRadius: 22, background: "var(--color-primary)", color: "var(--color-secondary)", margin: "0 auto 20px" }}><Icon name="checkcircle" size={36} /></span>
              <h4 style={{ marginBottom: 8 }}>{launchedMode === "live" ? "Campaign is live" : "Drafts ready for approval"}</h4>
              <p className="muted" style={{ fontSize: 14, maxWidth: 420, margin: "0 auto 24px" }}>
                {launchedMode === "live"
                  ? <>{agent.name} queued <b>{enqueued || grp.count}</b> message{(enqueued || grp.count) === 1 ? "" : "s"} to the messaging queue. New replies and drafts will appear on your dashboard.</>
                  : <>{agent.name} prepared <b>{enqueued || grp.count}</b> draft{(enqueued || grp.count) === 1 ? "" : "s"} in your approval queue. Review and approve them in Conversations — they send once approved (and WhatsApp is connected).</>}
              </p>
              <div className="row" style={{ gap: 10, justifyContent: "center" }}>
                <Button variant="ghost" onClick={onClose}>Back to campaigns</Button>
                <Button variant="primary" icon="message" onClick={() => { onClose(); go("conversations"); }}>Go to conversations</Button>
              </div>
            </div>
          )}
        </div>

        {/* footer */}
        {step < 6 && (
          <div className="between" style={{ padding: "16px 24px", borderTop: "1px solid var(--border-1)" }}>
            <button className="btn btn--ghost" onClick={() => step === 0 ? onClose() : setStep(step - 1)}><Icon name="chevronLeft" size={18} />{step === 0 ? "Cancel" : "Back"}</button>
            <div className="row" style={{ gap: 10 }}>
              {step === 4 && generated && <span className="subtle" style={{ fontSize: 12 }}>Looks good?</span>}
              <Button variant={step === 5 ? "primary" : "dark"} onClick={next} disabled={busy || (step === 5 && liveBlocked)} iconEnd={step === 5 ? "send" : "chevronRight"}>
                {launching ? "Launching…" : step === 5 ? "Launch campaign" : step === 4 && !generated ? (generating ? "Generating…" : "Generate drafts") : "Continue"}
              </Button>
            </div>
          </div>
        )}
      </div>
    </Scrim>
  );
}

window.CampaignsScreen = CampaignsScreen;
window.CampaignWizard = CampaignWizard;
window.CAMP_STATUS = CAMP_STATUS;
window.SERVICE_META = SERVICE_META;
