// ============================================================================
// IMS — Admin: Unassigned Outreach + Unassigned Potential Leads
// Includes: Create Bundle (auto 3-step), Manual Selection flow, Notes
// ============================================================================

function UnassignedPage({ variant }) {
  // variant: "outreach" | "leads"
  const { data, setPage, notify, removeFromUnassigned, createBundle, updateInfluencer } = useApp();
  const [settings] = useSettings();
  const bundleMax = settings.bundleSize || 2;
  const rows = variant === "outreach" ? data.unassignedOutreach : data.unassignedLeads;

  const [manualMode, setManualMode] = useState(false);
  const [selected, setSelected] = useState(new Set());
  const [bundleFlow, setBundleFlow] = useState(null);
  const [notesFor, setNotesFor] = useState(null);
  const [search, setSearch] = useState("");
  const [rejHistoryFor, setRejHistoryFor] = useState(null);
  const [pg, setPg] = useState(1);
  const perPage = 8;
  // notes state: Map of influencer id → array of {by, at, body}
  const [notesMap, setNotesMap] = useState(() => {
    const m = {};
    rows.forEach(r => {
      if (r._notes?.length) m[r.id] = r._notes;
      else if (r.note) m[r.id] = [{ by: "Farah K.", at: "Apr 12, 2026", body: r.note }];
    });
    return m;
  });
  const addNote = (influencerId, body) => {
    const now = new Date();
    const at = now.toLocaleDateString("en-GB", { day: "numeric", month: "short", year: "numeric" }).replace(",", "").replace(/(\d+) (\w+) (\d+)/, "$2 $1, $3");
    const newNote = { by: "Farah K.", at, body };
    setNotesMap(m => ({
      ...m,
      [influencerId]: [newNote, ...(m[influencerId] || [])],
    }));
    // Persist to localStorage via updateInfluencer
    const influencer = rows.find(r => r.id === influencerId);
    if (influencer) {
      const existingNotes = notesMap[influencerId] || [];
      updateInfluencer(influencerId, { note: body, _notes: [newNote, ...existingNotes] });
    }
  };

  const columns = useMemo(() => [
    { key: "platform", label: "Platform", accessor: r => r.platform },
    { key: "category", label: "Category", accessor: r => r.category },
    { key: "location", label: "Location", accessor: r => r.location },
  ], []);
  const { filtered, filters, set, clear, openFor, setOpenFor, distinctFor } = useColumnFilter(rows, columns);

  const searchFiltered = useMemo(() => {
    if (!search.trim()) return filtered;
    const q = search.toLowerCase();
    return filtered.filter(r =>
      r.name.toLowerCase().includes(q) ||
      r.handle.toLowerCase().includes(q) ||
      r.location.toLowerCase().includes(q) ||
      (r.category || "").toLowerCase().includes(q) ||
      (r.platform || "").toLowerCase().includes(q)
    );
  }, [filtered, search]);

  const totalPages = Math.max(1, Math.ceil(searchFiltered.length / perPage));
  const paged = searchFiltered.slice((pg - 1) * perPage, pg * perPage);

  const toggleSelect = (id) => {
    const n = new Set(selected);
    n.has(id) ? n.delete(id) : n.add(id);
    setSelected(n);
  };

  const title = variant === "outreach" ? "Unassigned Outreach" : "Unassigned Potential Leads";
  const subtitle = variant === "outreach"
    ? "Influencers synced from the upstream source-of-truth table, not yet bundled to an outreach specialist."
    : "Influencers marked Interested by an outreach specialist. Bundle and assign to a collaboration manager.";

  const startAuto = () => setBundleFlow({ step: 1, count: Math.min(bundleMax, rows.length), specialistId: null, manual: false });
  const startManual = () => {
    if (selected.size === 0) return;
    setBundleFlow({ step: 2, count: selected.size, specialistId: null, manual: true });
  };

  const cancelManual = () => { setManualMode(false); setSelected(new Set()); };

  return (
    <div className="page">
      <div className="page-head">
        <div>
          <h1>{title}</h1>
          <div className="subtitle">{subtitle}</div>
        </div>
        <div className="meta">
          <span>{searchFiltered.length} of {rows.length} influencers</span>
        </div>
      </div>

      <div className="toolbar">
        {!manualMode && (
          <>
            <button className="btn primary" onClick={startAuto} disabled={rows.length === 0} title={rows.length === 0 ? "No influencers available to bundle" : undefined}>
              <Ic.plus /> Create Bundle
            </button>
            <button className="btn" onClick={() => setManualMode(true)} disabled={rows.length === 0} title={rows.length === 0 ? "No influencers available to select" : undefined}>
              <Ic.filter /> Manual Selection
            </button>
          </>
        )}
        <div className="spacer" />
        <div className="search">
          <Ic.search />
          <input
            placeholder="Search name, handle, location…"
            value={search}
            onChange={(e) => { setSearch(e.target.value); setPg(1); }}
          />
          {search && <button className="search-clear" onClick={() => { setSearch(""); setPg(1); }}><Ic.x /></button>}
        </div>
      </div>

      <ActiveFilterChips filters={filters} columns={columns} onClear={clear} />

      {manualMode && (
        <div className="sticky-widget">
          <span className="count">{selected.size} selected</span>
          <span className="hint">Hover a row's notes column to read the latest note · pick who to assign</span>
          <div className="spacer" />
          <button className="btn primary" disabled={selected.size === 0} onClick={startManual}>
            Create Bundle from Selection <Ic.arrowRight />
          </button>
          <button className="x" onClick={cancelManual} aria-label="Cancel selection"><Ic.x /></button>
        </div>
      )}

      <div className="table-wrap">
        <table className="ims">
          <thead>
            <tr>
              {manualMode && <th style={{ width: 42 }}></th>}
              <th>Influencer</th>
              <FilterHeader col={columns[0]} filters={filters} openFor={openFor} setOpenFor={setOpenFor} distincts={distinctFor("platform")} onPick={(v) => { set("platform", v); setPg(1); }} onClear={() => { clear("platform"); setPg(1); }} />
              <FilterHeader col={columns[1]} filters={filters} openFor={openFor} setOpenFor={setOpenFor} distincts={distinctFor("category")} onPick={(v) => { set("category", v); setPg(1); }} onClear={() => { clear("category"); setPg(1); }} />
              <FilterHeader col={columns[2]} filters={filters} openFor={openFor} setOpenFor={setOpenFor} distincts={distinctFor("location")} onPick={(v) => { set("location", v); setPg(1); }} onClear={() => { clear("location"); setPg(1); }} />
              <th className="num">Followers</th>
              <th className="num">ER</th>
              {variant === "leads" && <th>Interested By</th>}
              <th>Synced / Moved</th>
              <th style={{ width: 260 }}>Notes</th>
            </tr>
          </thead>
          <tbody>
            {paged.length === 0 && rows.length === 0 && (
              <tr><td colSpan={99} style={{ textAlign: "center", padding: "56px 0" }}>
                <div style={{ color: "var(--ink-3)", fontWeight: 600, fontSize: 13, marginBottom: 6 }}>
                  {variant === "outreach" ? "No unassigned influencers" : "No unassigned potential leads"}
                </div>
                <div style={{ color: "var(--ink-3)", fontSize: 12, fontFamily: "var(--font-mono)", letterSpacing: "0.06em", marginTop: 4 }}>
                  {variant === "outreach" ? "SYNC FROM AIRTABLE · PRESS REFRESH TO PULL APPROVED INFLUENCERS" : "MARKED INTERESTED BY OUTREACH → APPEARS HERE"}
                </div>
              </td></tr>
            )}
            {paged.length === 0 && rows.length > 0 && (
              <tr><td colSpan={99} style={{ textAlign: "center", padding: "48px 0", color: "var(--ink-3)", fontFamily: "var(--font-mono)", fontSize: 12, letterSpacing: "0.06em" }}>
                NO RESULTS — try a different search or filter
              </td></tr>
            )}
            {paged.map(r => (
              <tr key={r.id} className={`${!manualMode ? "clickable" : ""} ${manualMode && selected.has(r.id) ? "selected" : ""}`}
                  onClick={() => {
                    if (manualMode) { toggleSelect(r.id); }
                    else { setPage({ key: "profile", influencer: r, from: variant === "outreach" ? "os-unassigned" : "cm-unassigned" }); }
                  }}>
                {manualMode && (
                  <td>
                    <label className="checkbox" onClick={(e) => e.stopPropagation()}>
                      <input type="checkbox" checked={selected.has(r.id)} onChange={() => toggleSelect(r.id)} />
                      <span className="box" />
                    </label>
                  </td>
                )}
                <td>
                  <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                    <InfCell name={r.name} handle={r.handle} />
                    {r.previouslyRejected && (
                      <span
                        className="pill"
                        style={{ color: "var(--bad)", borderColor: "var(--bad-bg)", background: "var(--bad-bg)", cursor: "pointer" }}
                        onClick={(e) => { e.stopPropagation(); setRejHistoryFor(r); }}
                        title="Click to see rejection history"
                      >
                        <Ic.info /> Previously Rejected
                      </span>
                    )}
                  </div>
                </td>
                <td>{r.platform}</td>
                <td>{r.category}</td>
                <td className="mono">{r.location}</td>
                <td className="num">{r.followers}</td>
                <td className="num">{r.er}</td>
                {variant === "leads" && <td className="text-small">{r.markedInterestedBy}</td>}
                <td className="mono text-xs text-mute">{r.syncedAt || r.markedAt}</td>
                <td className="notes-cell">
                  {notesMap[r.id]?.length > 0 ? (
                    <button className="btn ghost sm note-has-content" onClick={(e) => { e.stopPropagation(); setNotesFor(r); }} style={{ textAlign: "left", padding: "4px 6px", width: "100%" }}>
                      <div className="note-preview">{notesMap[r.id][0].body}</div>
                      <div className="note-tooltip">
                        <div style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.1em", textTransform: "uppercase", opacity: 0.6, marginBottom: 6 }}>Latest · {notesMap[r.id][0].by}</div>
                        {notesMap[r.id][0].body}
                        <div style={{ marginTop: 8, paddingTop: 8, borderTop: "1px dashed rgba(255,255,255,0.15)", fontSize: 10, opacity: 0.6 }}>Click to view all {notesMap[r.id].length} note{notesMap[r.id].length > 1 ? "s" : ""} + add</div>
                      </div>
                    </button>
                  ) : (
                    <button className="btn ghost sm" style={{ color: "var(--ink-3)" }} onClick={(e) => { e.stopPropagation(); setNotesFor(r); }}>
                      <Ic.plus /> Add note
                    </button>
                  )}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      {!manualMode && <TablePagination page={pg} totalPages={totalPages} onPage={setPg} total={searchFiltered.length} perPage={perPage} />}

      {bundleFlow && (
        <BundleFlowModal
          variant={variant}
          flow={bundleFlow}
          setFlow={setBundleFlow}
          manualCount={selected.size}
          totalAvailable={rows.length}
          bundleMax={bundleMax}
          selectedIds={[...selected]}
          allRows={rows}
          onComplete={(summary) => {
            if (summary.bundledIds && summary.bundledIds.length > 0) {
              removeFromUnassigned(variant, summary.bundledIds);
              createBundle?.(summary.bundleId, summary.specialistId, summary.specialist, summary.bundledIds, variant, rows, summary.campaignId, summary.campaignName, summary.isReturning);
            }
            setBundleFlow(null);
            setManualMode(false);
            setSelected(new Set());
            setPg(1);
            notify(`Bundle ${summary.bundleId} assigned to ${summary.specialist}. Notified via IMS Inbox.`);
          }}
        />
      )}

      {notesFor && <AddNoteModal influencer={notesFor} notes={notesMap[notesFor.id] || []} onSave={(body) => { addNote(notesFor.id, body); }} onClose={() => setNotesFor(null)} />}

      {rejHistoryFor && (
        <Modal
          open={true}
          onClose={() => setRejHistoryFor(null)}
          sub="Rejection history"
          title={`Previously Rejected · ${rejHistoryFor.name}`}
          foot={<button className="btn primary" onClick={() => setRejHistoryFor(null)}>Close</button>}
        >
          <div className="text-mute text-xs" style={{ marginBottom: 14 }}>
            This influencer has been rejected during bundle acceptance. Full history below.
          </div>
          <div className="stack-sm">
            {(rejHistoryFor.rejectionHistory || []).length === 0
              ? <div className="text-mute text-small" style={{ padding: "12px 0" }}>No detailed history recorded.</div>
              : null}
            {(rejHistoryFor.rejectionHistory || []).map((entry, i) => (
              <div key={i} className="card tinted">
                <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 6 }}>
                  <div style={{ fontWeight: 500, fontSize: 12.5 }}>{entry.by}</div>
                  <div className="text-mono text-xs text-mute">{entry.at}</div>
                </div>
                <div className="text-small">{entry.reason}</div>
              </div>
            ))}
          </div>
        </Modal>
      )}
    </div>
  );
}

// ---------------- Bundle creation (3-step for outreach, 4-step for leads) ----------------

function BundleFlowModal({ variant, flow, setFlow, manualCount, totalAvailable, bundleMax, onComplete, selectedIds, allRows }) {
  const { data } = useApp();
  const allSpecialists = variant === "outreach" ? data.outreachSpecialists : data.collabManagers;
  const activeSpecialists = useMemo(() => (allSpecialists || []).filter(s => !s.deletedAt), [allSpecialists]);
  const sp = activeSpecialists.find(s => s.id === flow.specialistId);
  const isLeads = variant === "leads";
  const maxStep = isLeads ? 4 : 3;

  // Search + pagination for step 2 specialist list
  const [spSearch, setSpSearch] = useState("");
  const [spPg, setSpPg] = useState(1);
  const SP_PER_PAGE = 6;

  const filteredSpecialists = useMemo(() => {
    const q = spSearch.trim().toLowerCase();
    return q ? activeSpecialists.filter(s => s.name.toLowerCase().includes(q) || s.id.toLowerCase().includes(q)) : activeSpecialists;
  }, [activeSpecialists, spSearch]);

  const spTotalPages = Math.max(1, Math.ceil(filteredSpecialists.length / SP_PER_PAGE));
  const pagedSpecialists = filteredSpecialists.slice((spPg - 1) * SP_PER_PAGE, spPg * SP_PER_PAGE);

  const handleSpSearch = (v) => { setSpSearch(v); setSpPg(1); };

  // Detect if any selected influencers are returning (have signed contract)
  const selectedRows = allRows ? allRows.filter(r => (selectedIds || []).includes(r.id) || (!flow.manual && (allRows || []).slice(0, flow.count).map(r2 => r2.id).includes(r.id))) : [];
  const hasReturning = selectedRows.some(r => r.hasSignedContract);

  const next = () => {
    const nextStep = flow.step + 1;
    const reviewStep = maxStep;
    const updates = nextStep === reviewStep && !flow.bundleId
      ? { bundleId: (variant === "outreach" ? "OB-" : "LB-") + (750 + Math.floor(Math.random() * 50)) }
      : {};
    setFlow({ ...flow, step: nextStep, ...updates });
  };
  const back = () => setFlow({ ...flow, step: flow.step - 1 });

  const [conflicts, setConflicts] = useState(null);

  const confirm = () => {
    if (flow.step === maxStep) {
      const bundleId = flow.bundleId || (variant === "outreach" ? "OB-" : "LB-") + (750 + Math.floor(Math.random() * 50));
      const bundledIds = flow.manual
        ? [...(selectedIds || [])]
        : (allRows || []).slice(0, flow.count).map(r => r.id);

      // Check for real previously-rejected influencers assigned to this specialist
      if (!flow.conflictResolved && variant === "outreach" && sp) {
        const bundledIdSet = new Set(bundledIds);
        const rejected = (allRows || []).filter(r =>
          bundledIdSet.has(r.id) && r.previouslyRejected && r.rejectedBy === sp.id
        );
        if (rejected.length > 0) {
          setConflicts({ bundleId, bundledIds, rejected });
          return;
        }
      }
      onComplete({ bundleId, specialistId: sp.id, specialist: sp.name, bundledIds, campaignId: flow.campaignId || "", campaignName: flow.campaignName || "", isReturning: flow.isReturning || false });
    } else {
      next();
    }
  };

  const stepTitle = () => {
    if (flow.step === 1) return "How many to bundle?";
    if (flow.step === 2) return `Select ${variant === "outreach" ? "outreach specialist" : "collaboration manager"}`;
    if (flow.step === 3 && isLeads) return "Select Campaign";
    return "Review & confirm";
  };

  return (
    <Modal
      open={true}
      onClose={() => setFlow(null)}
      sub={`Step ${flow.step} of ${maxStep} · ${variant === "outreach" ? "Outreach Bundle" : "Lead Bundle"}`}
      title={stepTitle()}
      foot={
        <>
          <div className="step-dots">
            {Array.from({ length: maxStep }, (_, i) => (
              <span key={i} className={`dot ${flow.step >= i + 1 ? "active" : ""}`} />
            ))}
            <span style={{ marginLeft: 8 }}>Step {flow.step}/{maxStep}</span>
          </div>
          <div style={{ display: "flex", gap: 8 }}>
            {flow.step > 1 && !flow.manual && <button className="btn" onClick={back}><Ic.arrowLeft /> Back</button>}
            {flow.step === 2 && flow.manual && <button className="btn" onClick={() => setFlow(null)}>Cancel</button>}
            <button className="btn primary"
              disabled={(flow.step === 2 && !flow.specialistId) || (flow.step === 3 && isLeads && !flow.campaignId)}
              onClick={confirm}>
              {flow.step === maxStep ? "Create Bundle" : "Continue"} <Ic.arrowRight />
            </button>
          </div>
        </>
      }
    >
      {flow.step === 1 && (
        <>
          <div className="text-mute" style={{ marginBottom: 14 }}>
            You have <strong style={{ color: "var(--ink)" }}>{totalAvailable} available {variant === "outreach" ? "influencers" : "potential leads"}</strong>. How many do you want to bundle?
          </div>
          <input
            className="input big"
            type="number"
            value={flow.count}
            min="1"
            max={Math.min(bundleMax, totalAvailable)}
            onChange={(e) => setFlow({ ...flow, count: Math.max(1, Math.min(Math.min(bundleMax, totalAvailable), +e.target.value || 1)) })}
            autoFocus
          />
          <div className="text-mute text-xs" style={{ marginTop: 10, fontFamily: "var(--font-mono)", textTransform: "uppercase", letterSpacing: "0.1em" }}>
            The system will auto-select {flow.count} influencers from the top of the list · max {bundleMax} per bundle
          </div>
        </>
      )}

      {flow.step === 2 && (
        <>
          {flow.manual && (
            <div className="banner info" style={{ marginBottom: 14 }}>
              <Ic.info />
              <div>Manual selection — using <strong>{manualCount} hand-picked</strong> influencers.</div>
            </div>
          )}
          <div className="field">
            <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 10 }}>
              <label style={{ margin: 0 }}>Available {variant === "outreach" ? "Outreach Specialists" : "Collaboration Managers"}</label>
              <span style={{ fontSize: 11, color: "var(--ink-3)", fontFamily: "var(--font-mono)" }}>
                {filteredSpecialists.length === activeSpecialists.length
                  ? `${activeSpecialists.length} total`
                  : `${filteredSpecialists.length} of ${activeSpecialists.length}`}
              </span>
            </div>
            {activeSpecialists.length > SP_PER_PAGE && (
              <div className="search" style={{ marginBottom: 10 }}>
                <Ic.search />
                <input
                  placeholder={`Search ${variant === "outreach" ? "specialist" : "manager"} by name or ID…`}
                  value={spSearch}
                  onChange={e => handleSpSearch(e.target.value)}
                />
                {spSearch && <button className="search-clear" onClick={() => handleSpSearch("")}><Ic.x /></button>}
              </div>
            )}
            <div className="stack-sm">
              {pagedSpecialists.length === 0 && (
                <div className="text-mute text-small" style={{ padding: "12px 0" }}>No results for "{spSearch}".</div>
              )}
              {pagedSpecialists.map(s => (
                <div key={s.id}
                  className={`radio ${flow.specialistId === s.id ? "checked" : ""}`}
                  onClick={() => setFlow({ ...flow, specialistId: s.id })}>
                  <div className="dot" />
                  <div style={{ width: 28, height: 28, background: "var(--bg-3)", color: "var(--ink)", borderRadius: 999, display: "grid", placeItems: "center", fontFamily: "var(--font-mono)", fontSize: 10, fontWeight: 600, border: "1px solid var(--line-2)", flexShrink: 0 }}>
                    {s.initials}
                  </div>
                  <div style={{ flex: 1 }}>
                    <div style={{ fontWeight: 500 }}>{s.name}</div>
                    <div className="text-mono text-xs text-mute">
                      {s.id} · {s.active} active · {variant === "outreach" ? `$${s.perContact}/contact · $${s.bonus} bonus` : `Stages $${s.stages[1]}/$${s.stages[2]}/$${s.stages[3]}/$${s.stages[4]} · ${s.commission} / ${s.commissionDuration}`}
                    </div>
                  </div>
                </div>
              ))}
            </div>
            {spTotalPages > 1 && (
              <div style={{ marginTop: 10 }}>
                <TablePagination page={spPg} totalPages={spTotalPages} onPage={setSpPg} total={filteredSpecialists.length} perPage={SP_PER_PAGE} />
              </div>
            )}
          </div>
        </>
      )}

      {flow.step === 3 && isLeads && (
        <>
          <div className="text-mute" style={{ marginBottom: 14 }}>
            Select which campaign these influencers will be assigned to.
            {hasReturning && <span style={{ color: "var(--accent-2)", marginLeft: 8 }}>Some influencers have a signed contract — they can skip Stage 1.</span>}
          </div>
          <div className="stack-sm" style={{ maxHeight: 260, overflowY: "auto", marginBottom: 12 }}>
            {(data.campaigns || []).map(c => (
              <div key={c.id} className={`radio ${flow.campaignId === c.id ? "checked" : ""}`} onClick={() => setFlow({ ...flow, campaignId: c.id, campaignName: c.name })}>
                <div className="dot" />
                <div style={{ flex: 1 }}>
                  <div style={{ fontWeight: 500 }}>{c.name}</div>
                  <div className="text-mono text-xs text-mute">{c.id} · {c.brand} · {c.status}</div>
                </div>
                <Chip tone={c.status === "Active" ? "ok" : "neutral"} xs>{c.status}</Chip>
              </div>
            ))}
            {(data.campaigns || []).length === 0 && (
              <div className="text-mute text-small">No campaigns yet. Create one on the Campaigns page first.</div>
            )}
          </div>
          {hasReturning && flow.campaignId && (
            <div className="field" style={{ marginTop: 8 }}>
              <label>Returning collaborators detected</label>
              <div style={{ display: "flex", gap: 8 }}>
                <div className={`radio ${flow.isReturning ? "checked" : ""}`} onClick={() => setFlow({ ...flow, isReturning: true })} style={{ flex: 1 }}>
                  <div className="dot" />
                  <span>Returning — skip Stage 1</span>
                </div>
                <div className={`radio ${!flow.isReturning ? "checked" : ""}`} onClick={() => setFlow({ ...flow, isReturning: false })} style={{ flex: 1 }}>
                  <div className="dot" />
                  <span>First-time — all 4 stages</span>
                </div>
              </div>
            </div>
          )}
        </>
      )}

      {flow.step === maxStep && sp && (
        <>
          <div className="text-mute" style={{ marginBottom: 14 }}>
            Assigning <strong style={{ color: "var(--ink)" }}>Bundle ID {flow.bundleId || (variant === "outreach" ? "OB-" : "LB-") + "—"}</strong> to <strong style={{ color: "var(--ink)" }}>{sp.name}</strong>, {variant === "outreach" ? "Outreach Specialist" : "Collaboration Manager"}.
          </div>
          <div className="card tinted">
            <div className="kv-list">
              <div className="kv"><div className="k">Count</div><div className="v text-mono">{flow.manual ? manualCount : flow.count} influencers</div></div>
              <div className="kv"><div className="k">Bundle Type</div><div className="v">{variant === "outreach" ? "Outreach" : "Lead"}</div></div>
              {variant === "outreach" && (
                <>
                  <div className="kv"><div className="k">Agreement</div><div className="v text-mono">${sp.perContact} per contact · ${sp.bonus} bonus on Interested</div></div>
                </>
              )}
              {variant === "leads" && (
                <>
                  <div className="kv"><div className="k">Stage Payments</div><div className="v text-mono">S1 ${sp.stages[1]} · S2 ${sp.stages[2]} · S3 ${sp.stages[3]} · S4 ${sp.stages[4]}</div></div>
                  <div className="kv"><div className="k">Commission</div><div className="v">{sp.commission} · {sp.commissionDuration}</div></div>
                  {flow.campaignName && (
                    <div className="kv"><div className="k">Campaign</div><div className="v"><Chip tone="info">{flow.campaignName}</Chip></div></div>
                  )}
                  {flow.isReturning && (
                    <div className="kv"><div className="k">Returning</div><div className="v"><Chip tone="accent">Yes — Stage 1 skipped · Stages 2-4 only</Chip></div></div>
                  )}
                </>
              )}
              <div className="kv"><div className="k">Notifications</div><div className="v text-xs text-mute">IMS Inbox</div></div>
            </div>
          </div>

          {conflicts && (
            <div className="banner bad" style={{ marginTop: 14, alignItems: "flex-start" }}>
              <Ic.warn />
              <div>
                <strong>{conflicts.rejected.map(r => r.name).join(", ")} {conflicts.rejected.length === 1 ? "was" : "were"} previously rejected by {sp.name}</strong> and will be removed from your bundle.
                <div style={{ marginTop: 10, display: "flex", gap: 8 }}>
                  <button className="btn sm" onClick={() => {
                    setConflicts(null);
                    setFlow({ ...flow, conflictResolved: true });
                    onComplete({ bundleId: conflicts.bundleId, specialistId: sp.id, specialist: sp.name, bundledIds: conflicts.bundledIds, campaignId: flow.campaignId || "", campaignName: flow.campaignName || "", isReturning: flow.isReturning || false });
                  }}>Continue anyway</button>
                  <button className="btn sm primary" onClick={() => {
                    setConflicts(null);
                    setFlow({ ...flow, conflictResolved: true });
                    const filteredIds = conflicts.bundledIds.filter(id => !conflicts.rejected.find(r => r.id === id));
                    onComplete({ bundleId: conflicts.bundleId, specialistId: sp.id, specialist: sp.name, bundledIds: filteredIds, campaignId: flow.campaignId || "", campaignName: flow.campaignName || "", isReturning: flow.isReturning || false });
                  }}>Continue without them</button>
                </div>
              </div>
            </div>
          )}
        </>
      )}
    </Modal>
  );
}

// ---------------- Add Note modal (WhisperFlow-style) ----------------

function AddNoteModal({ influencer, notes, onSave, onClose }) {
  const [text, setText] = useState("");
  const [pg, setPg]     = useState(1);
  const perPage = 5;

  const handleSave = () => {
    if (!text.trim()) return;
    onSave(text.trim());
    setText("");
    setPg(1); // jump back to page 1 so new note is visible
  };

  const totalPages = Math.max(1, Math.ceil(notes.length / perPage));
  const paged      = notes.slice((pg - 1) * perPage, pg * perPage);

  return (
    <Modal
      open={true}
      onClose={onClose}
      sub="Private · admin only"
      title={`Notes · ${influencer.name}`}
      size="wide"
      foot={<>
        <span className="text-xs text-mute text-mono" style={{ textTransform: "uppercase", letterSpacing: "0.1em" }}>Visible to admins only — OS & CM cannot see notes</span>
        <div style={{ display: "flex", gap: 8 }}>
          <button className="btn" onClick={onClose}>Close</button>
          <button className="btn primary" disabled={!text.trim()} onClick={handleSave}>Save Note</button>
        </div>
      </>}
    >
      <div className="field">
        <label>New note</label>
        <textarea className="textarea" placeholder="Type a private annotation for this influencer…" value={text} onChange={(e) => setText(e.target.value)} autoFocus />
      </div>

      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginTop: 18, marginBottom: 8 }}>
        <div className="text-mono text-xs text-mute" style={{ textTransform: "uppercase", letterSpacing: "0.1em" }}>
          Note history · {notes.length} {notes.length === 0 ? "— none yet" : ""}
        </div>
        {notes.length > 0 && (
          <span className="text-mono text-xs text-mute">
            {(pg - 1) * perPage + 1}–{Math.min(pg * perPage, notes.length)} of {notes.length}
          </span>
        )}
      </div>

      {notes.length === 0 && (
        <div className="text-mute text-small" style={{ padding: "12px 0" }}>No notes yet. Add the first one above.</div>
      )}

      <div className="stack-sm">
        {paged.map((p, i) => (
          <div key={i} className="card tinted">
            <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 6 }}>
              <div style={{ fontWeight: 500, fontSize: 12.5 }}>{p.by}</div>
              <div className="text-mono text-xs text-mute">{p.at}</div>
            </div>
            <div>{p.body}</div>
          </div>
        ))}
      </div>

      {totalPages > 1 && (
        <div style={{ marginTop: 10 }}>
          <TablePagination page={pg} totalPages={totalPages} onPage={setPg} total={notes.length} perPage={perPage} />
        </div>
      )}
    </Modal>
  );
}

Object.assign(window, { UnassignedPage, AddNoteModal });
