// ============================================================================
// IMS — Requests (full two-way ticket flow) + Admin Inbox
// Status: Open → Awaiting Specialist → (follow-up) → Open → Resolved
// Admin: respond, resolve, reopen
// OS/CM: follow-up after admin responds
// All actions generate notifications to the other party
// ============================================================================

function RequestsPage({ openReqId } = {}) {
  const { data, role, activePersonId, notify, respondToRequest, addFollowUpMessage, resolveRequest, reopenRequest } = useApp();
  const all = data.requests;

  // OS/CM see only their own requests (matched by activePersonId)
  const mine = role === "admin"
    ? all
    : all.filter(r => r.raisedBy.id === activePersonId);

  const [openId, setOpenId] = useState(openReqId || null);
  const [reply, setReply] = useState("");
  const [followUp, setFollowUp] = useState("");
  const [activeTab, setActiveTab] = useState("all");
  const [searchQ, setSearchQ] = useState("");
  const [statusFilter, setStatusFilter] = useState(null);
  const [typeFilter, setTypeFilter] = useState(null);
  const [pg, setPg] = useState(1);
  const [threadPg, setThreadPg] = useState(1);
  const perPage = 8;
  const threadPerPage = 10;

  // Always derive open from live data so thread updates reflect immediately
  const open = openId ? data.requests.find(r => r.id === openId) : null;

  const osReqs = mine.filter(r => r.raisedBy.kind === "OS");
  const cmReqs = mine.filter(r => r.raisedBy.kind === "CM");

  // Build bundleId → campaignName map from collab in-progress
  const bundleCampaignMap = useMemo(() => {
    const m = {};
    (data.collabInProgress || []).forEach(r => { if (r.bundleId && r.campaignName) m[r.bundleId] = { name: r.campaignName, id: r.campaignId }; });
    (data.cmInbox || []).forEach(b => { if (b.id && b.campaignName) m[b.id] = { name: b.campaignName, id: b.campaignId }; });
    return m;
  }, [data.collabInProgress, data.cmInbox]);

  const tabFiltered = role === "admin"
    ? (activeTab === "os" ? osReqs : activeTab === "cm" ? cmReqs : mine)
    : mine;

  const visibleReqs = tabFiltered.filter(r => {
    if (statusFilter && r.status !== statusFilter) return false;
    if (typeFilter && r.type !== typeFilter) return false;
    if (searchQ) {
      const q = searchQ.toLowerCase();
      if (!r.summary.toLowerCase().includes(q) && !r.id.toLowerCase().includes(q) && !r.influencer.name.toLowerCase().includes(q)) return false;
    }
    return true;
  });

  const totalPages = Math.max(1, Math.ceil(visibleReqs.length / perPage));
  const pagedReqs = visibleReqs.slice((pg - 1) * perPage, pg * perPage);
  const switchTab = (t) => { setActiveTab(t); setPg(1); setStatusFilter(null); setTypeFilter(null); };
  const statuses = [...new Set(mine.map(r => r.status))];
  const types    = [...new Set(mine.map(r => r.type))].sort();

  // Counts for header badges
  const openCount = mine.filter(r => r.status === "Open").length;
  const awaitingCount = mine.filter(r => r.status === "Awaiting Specialist").length;

  const handleRespond = () => {
    if (!reply.trim() || !open) return;
    respondToRequest(open.id, reply.trim());
    setReply("");
    notify("Response sent — specialist has been notified.");
    // Jump to last thread page so new reply is visible
    const newCount = (open.thread?.length || 0) + 1;
    setThreadPg(Math.ceil(newCount / threadPerPage));
  };

  const handleFollowUp = () => {
    if (!followUp.trim() || !open) return;
    const senderName = open.raisedBy.name;
    addFollowUpMessage(open.id, followUp.trim(), senderName);
    setFollowUp("");
    notify("Follow-up sent — Admin has been notified.");
    const newCount = (open.thread?.length || 0) + 1;
    setThreadPg(Math.ceil(newCount / threadPerPage));
  };

  const handleResolve = () => {
    if (!open) return;
    resolveRequest(open.id);
    notify(`Request ${open.id} marked as Resolved.`);
  };

  const handleReopen = () => {
    if (!open) return;
    reopenRequest(open.id);
    notify(`Request ${open.id} reopened.`);
  };

  const statusColor = (s) => {
    if (s === "Open") return "warn";
    if (s === "Awaiting Specialist") return "info";
    if (s === "Resolved") return "ok";
    return "neutral";
  };

  if (open) {
    const isResolved = open.status === "Resolved";
    const canAdminRespond = role === "admin" && !isResolved;
    const canFollowUp = (role === "outreach" || role === "collab") && open.adminViewed && !isResolved;
    const hasUnread = (role === "outreach" || role === "collab") && open.status === "Awaiting Specialist";

    return (
      <div className="page">
        <button className="btn ghost sm" onClick={() => { setOpenId(null); setReply(""); setFollowUp(""); }}>
          <Ic.arrowLeft /> Back to requests
        </button>

        <div className="page-head" style={{ marginTop: 12 }}>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", marginBottom: 6 }}>
              <span className="pill">{open.id}</span>
              <Chip tone={open.type === "High Percentage" ? "warn" : "info"}>{open.type}</Chip>
              <StatusChip status={open.status} />
              {hasUnread && <Chip tone="accent" xs>New response from Admin</Chip>}
            </div>
            <h1 style={{ fontSize: 18, marginBottom: 4 }}>{open.summary}</h1>
            <div className="subtitle">
              {open.raisedBy.name} ({open.raisedBy.kind === "OS" ? "Outreach Specialist" : "Collaboration Manager"})
              · {open.influencer.name} ({open.influencer.handle})
              {open.bundle && <> · Bundle {open.bundle}</>}
              {open.bundle && bundleCampaignMap[open.bundle] && <> · <span style={{ color: "var(--accent)" }}>{bundleCampaignMap[open.bundle].name}</span></>}
              · {open.at}
            </div>
          </div>
          {role === "admin" && (
            <div style={{ display: "flex", gap: 8, flexShrink: 0 }}>
              {!isResolved && (
                <button className="btn" onClick={handleResolve}>
                  <Ic.check /> Mark Resolved
                </button>
              )}
              {isResolved && (
                <button className="btn ghost" onClick={handleReopen}>
                  Reopen
                </button>
              )}
            </div>
          )}
        </div>

        {/* AI Summary */}
        <div className="card" style={{ marginBottom: 14 }}>
          <div className="section-label">AI Summary</div>
          <div style={{ fontSize: 13.5, color: "var(--ink-2)", lineHeight: 1.5 }}>{open.aiSummary}</div>
          {open.transcript && (
            <details style={{ marginTop: 10 }}>
              <summary className="text-xs text-mute" style={{ cursor: "pointer", fontFamily: "var(--font-mono)", letterSpacing: "0.06em" }}>VIEW TRANSCRIPT</summary>
              <pre style={{ marginTop: 8, fontSize: 12, lineHeight: 1.6, whiteSpace: "pre-wrap", color: "var(--ink-3)", background: "var(--bg-2)", padding: 10, borderRadius: 6 }}>{open.transcript}</pre>
            </details>
          )}
        </div>

        {/* Thread */}
        <div style={{ marginBottom: 14 }}>
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 8 }}>
            <div className="section-label" style={{ margin: 0 }}>
              Conversation Thread · {open.thread.length} message{open.thread.length !== 1 ? "s" : ""}
            </div>
            {open.thread.length > threadPerPage && (
              <span className="text-mono text-xs text-mute">
                {(threadPg - 1) * threadPerPage + 1}–{Math.min(threadPg * threadPerPage, open.thread.length)} of {open.thread.length}
              </span>
            )}
          </div>
          {open.thread.slice((threadPg - 1) * threadPerPage, threadPg * threadPerPage).map((m, i) => {
            const isAdmin = m.from.toLowerCase().includes("admin");
            return (
              <div key={(threadPg - 1) * threadPerPage + i} className={`thread-msg ${isAdmin ? "admin" : ""}`}>
                <div className="who-row">
                  <span className="who">{m.from}</span>
                  <span className="when">{m.at}</span>
                </div>
                <div>{m.body}</div>
              </div>
            );
          })}
          {Math.ceil(open.thread.length / threadPerPage) > 1 && (
            <div style={{ marginTop: 8 }}>
              <TablePagination
                page={threadPg}
                totalPages={Math.ceil(open.thread.length / threadPerPage)}
                onPage={setThreadPg}
                total={open.thread.length}
                perPage={threadPerPage}
              />
            </div>
          )}
        </div>

        {/* Admin: respond box (only when not resolved) */}
        {canAdminRespond && (
          <div className="card" style={{ marginBottom: 14 }}>
            <div className="section-label">
              {open.thread.length > 1 ? "Continue Thread" : "Respond"}
            </div>
            <textarea className="textarea" rows="4" value={reply}
              onChange={e => setReply(e.target.value)}
              placeholder="Your response to the specialist…" />
            <div style={{ marginTop: 10, display: "flex", justifyContent: "flex-end", gap: 8 }}>
              <button className="btn" onClick={() => setReply("")} disabled={!reply.trim()}>Clear</button>
              <button className="btn primary" disabled={!reply.trim()} onClick={handleRespond}>
                Send Response
              </button>
            </div>
          </div>
        )}

        {/* OS/CM: follow-up box (only after admin has viewed) */}
        {canFollowUp && (
          <div className="card" style={{ marginBottom: 14 }}>
            <div className="section-label">Add Follow-up</div>
            <div className="text-small text-mute" style={{ marginBottom: 8 }}>
              Admin has responded. Add a follow-up message or provide more context.
            </div>
            <textarea className="textarea" rows="3" value={followUp}
              onChange={e => setFollowUp(e.target.value)}
              placeholder="Add another message or more context…" />
            <div style={{ marginTop: 10, display: "flex", justifyContent: "flex-end" }}>
              <button className="btn primary" disabled={!followUp.trim()} onClick={handleFollowUp}>
                Send Follow-up
              </button>
            </div>
          </div>
        )}

        {/* OS/CM: waiting state (admin hasn't viewed yet) */}
        {(role === "outreach" || role === "collab") && !open.adminViewed && !isResolved && (
          <div className="banner info" style={{ marginBottom: 14 }}>
            <Ic.info />
            <div>Admin has not yet viewed this request. You'll be notified in your inbox as soon as they respond.</div>
          </div>
        )}

        {/* Resolved state banner */}
        {isResolved && (
          <div className="banner ok" style={{ marginBottom: 14 }}>
            <Ic.check />
            <div><strong>This request has been resolved.</strong> No further action needed. {role === "admin" ? "You can reopen it if needed." : "Contact Admin if you need to discuss further."}</div>
          </div>
        )}
      </div>
    );
  }

  return (
    <div className="page">
      <div className="page-head">
        <div>
          <h1>Requests</h1>
          <div className="subtitle">
            {role === "admin"
              ? "Tickets raised by outreach specialists and collaboration managers."
              : "Your request tickets to Admin. You'll be notified when Admin responds."}
          </div>
        </div>
        <div className="meta">
          {openCount > 0 && <Chip tone="warn" xs>{openCount} open</Chip>}
          {awaitingCount > 0 && <Chip tone="info" xs>{awaitingCount} awaiting your reply</Chip>}
        </div>
      </div>

      {role === "admin" && (
        <div className="tabs" style={{ marginBottom: 0, position: "relative", top: "auto", background: "transparent" }}>
          {[
            { k: "all", label: "All", count: mine.length },
            { k: "os", label: "Outreach", count: osReqs.length },
            { k: "cm", label: "Collaboration", count: cmReqs.length },
          ].map(t => (
            <div key={t.k} className={`tab ${activeTab === t.k ? "active" : ""}`} onClick={() => switchTab(t.k)}>
              {t.label} <span className="count">{t.count}</span>
            </div>
          ))}
        </div>
      )}

      <div className="toolbar" style={{ flexWrap: "wrap", gap: 6 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 4, flexWrap: "wrap" }}>
          <span className="text-mono" style={{ fontSize: 11, color: "var(--ink-3)", marginRight: 2 }}>STATUS</span>
          {statuses.map(s => (
            <button key={s} className={`btn sm ${statusFilter === s ? "primary" : ""}`}
              onClick={() => { setStatusFilter(statusFilter === s ? null : s); setPg(1); }}>
              {s}
            </button>
          ))}
        </div>
        {types.length > 0 && (
          <div style={{ display: "flex", alignItems: "center", gap: 4, flexWrap: "wrap" }}>
            <span className="text-mono" style={{ fontSize: 11, color: "var(--ink-3)", marginRight: 2, marginLeft: 4 }}>TYPE</span>
            {types.map(t => (
              <button key={t} className={`btn sm ${typeFilter === t ? "primary" : ""}`}
                onClick={() => { setTypeFilter(typeFilter === t ? null : t); setPg(1); }}>
                {t}
              </button>
            ))}
          </div>
        )}
        {(statusFilter || typeFilter) && (
          <button className="btn sm ghost" onClick={() => { setStatusFilter(null); setTypeFilter(null); setPg(1); }}>
            <Ic.x /> Clear filters
          </button>
        )}
        <div className="spacer" />
        <div className="search">
          <Ic.search />
          <input placeholder="Search tickets…" value={searchQ} onChange={e => { setSearchQ(e.target.value); setPg(1); }} />
          {searchQ && <button className="search-clear" onClick={() => { setSearchQ(""); setPg(1); }}><Ic.x /></button>}
        </div>
      </div>

      <div className="table-wrap">
        <table className="ims">
          <thead>
            <tr>
              <th style={{ width: 90, whiteSpace: "nowrap" }}>Ticket</th>
              <th>Summary</th>
              {role === "admin" && <th>Raised By</th>}
              <th>Influencer</th>
              <th>Campaign</th>
              <th>Type</th>
              <th>Status</th>
              <th style={{ width: 110 }}>Date</th>
              <th style={{ width: 40 }}></th>
            </tr>
          </thead>
          <tbody>
            {pagedReqs.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 filter
              </td></tr>
            )}
            {pagedReqs.map(r => {
              const hasUnread = (role === "outreach" || role === "collab") && r.status === "Awaiting Specialist";
              return (
                <tr key={r.id} className="clickable" onClick={() => { setOpenId(r.id); setReply(""); setFollowUp(""); }}>
                  <td style={{ whiteSpace: "nowrap" }}>
                    <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                      {hasUnread && <span style={{ width: 7, height: 7, borderRadius: 99, background: "var(--accent)", flexShrink: 0 }} />}
                      <span className="pill">{r.id}</span>
                    </div>
                  </td>
                  <td>
                    <div style={{ fontWeight: hasUnread ? 700 : 500, marginBottom: 2, maxWidth: 280, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                      {r.summary}
                    </div>
                    <div style={{ fontSize: 11, color: "var(--ink-4)", fontFamily: "var(--font-mono)" }}>
                      {r.thread.length} message{r.thread.length !== 1 ? "s" : ""}
                    </div>
                  </td>
                  {role === "admin" && (
                    <td>
                      <div style={{ display: "flex", alignItems: "center", gap: 6, whiteSpace: "nowrap" }}>
                        <span style={{ fontSize: 12.5 }}>{r.raisedBy.name}</span>
                        <Chip xs tone={r.raisedBy.kind === "OS" ? "info" : "accent"}>{r.raisedBy.kind}</Chip>
                      </div>
                    </td>
                  )}
                  <td><InfCell name={r.influencer.name} handle={r.influencer.handle} /></td>
                  <td>
                    {r.bundle && bundleCampaignMap[r.bundle]
                      ? <span style={{ fontSize: 12, color: "var(--ink-2)", whiteSpace: "nowrap" }}>{bundleCampaignMap[r.bundle].name}</span>
                      : <span className="text-mute" style={{ fontSize: 12 }}>—</span>}
                  </td>
                  <td><Chip tone={r.type === "High Percentage" ? "warn" : "info"} xs>{r.type}</Chip></td>
                  <td><StatusChip status={r.status} /></td>
                  <td style={{ fontFamily: "var(--mono)", fontSize: 11, color: "var(--ink-3)", whiteSpace: "nowrap" }}>{r.at}</td>
                  <td><Ic.arrowRight style={{ color: "var(--ink-4)" }} /></td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>

      <TablePagination page={pg} totalPages={totalPages} onPage={setPg} total={visibleReqs.length} perPage={perPage} />
    </div>
  );
}

// ============================================================================
// Table Pagination — MUI/Antd-style with rows-per-page info
// ============================================================================

function TablePagination({ page, totalPages, onPage, total, perPage }) {
  const from = Math.min((page - 1) * perPage + 1, total);
  const to = Math.min(page * perPage, total);

  const pages = [];
  if (totalPages <= 7) {
    for (let i = 1; i <= totalPages; i++) pages.push(i);
  } else {
    pages.push(1);
    if (page > 3) pages.push("...");
    for (let i = Math.max(2, page - 1); i <= Math.min(totalPages - 1, page + 1); i++) pages.push(i);
    if (page < totalPages - 2) pages.push("...");
    pages.push(totalPages);
  }

  return (
    <div style={{ padding: "12px 0", display: "flex", justifyContent: "space-between", alignItems: "center", borderTop: "1px solid var(--line)", marginTop: 2 }}>
      <span style={{ fontSize: 12, color: "var(--ink-3)", fontFamily: "var(--mono)" }}>
        {total === 0 ? "0 results" : `${from}–${to} of ${total}`}
      </span>
      {totalPages > 1 && (
        <div style={{ display: "flex", gap: 2, alignItems: "center" }}>
          <button className="btn sm" disabled={page <= 1} onClick={() => onPage(page - 1)} style={{ padding: "4px 6px" }}>
            <Ic.arrowLeft />
          </button>
          {pages.map((p, i) => (
            p === "..." ? (
              <span key={`e${i}`} style={{ padding: "0 4px", color: "var(--ink-4)", fontSize: 12 }}>…</span>
            ) : (
              <button key={p} className={`btn sm ${page === p ? "primary" : ""}`} onClick={() => onPage(p)} style={{ minWidth: 28, justifyContent: "center", padding: "4px 2px" }}>
                {p}
              </button>
            )
          ))}
          <button className="btn sm" disabled={page >= totalPages} onClick={() => onPage(page + 1)} style={{ padding: "4px 6px" }}>
            <Ic.arrowRight />
          </button>
        </div>
      )}
    </div>
  );
}

// ============================================================================
// Admin Inbox — rejections, overrides, new request alerts, follow-ups
// ============================================================================

function AdminInboxPage() {
  const { data, notify, setPage, addToUnassigned, removeFromInbox, archiveInfluencerFromInbox, restoreDroppedInfluencer, addRequest } = useApp();

  const [readIds, setReadIds] = useState(new Set(
    data.adminInbox.slice(0, 2).map(it => it.id)
  ));
  const [mainTab, setMainTab]       = useState("alerts");   // "alerts" | "activity"
  const [readFilter, setReadFilter] = useState("all");       // "all" | "unread" | "read"
  const [kindFilter, setKindFilter] = useState(null);        // null | kind string
  const [searchQ, setSearchQ]       = useState("");
  const [pg, setPg]                 = useState(1);
  const [replyFor, setReplyFor]     = useState(null);
  const [replyText, setReplyText]   = useState("");
  const perPage = 8;

  const items = data.adminInbox.map(it => ({ ...it, read: readIds.has(it.id) }));
  const unreadCount = items.filter(it => !it.read).length;

  const markRead = (id) => setReadIds(s => new Set([...s, id]));

  const dismiss = (it) => {
    removeFromInbox(it.id);
    setReadIds(s => { const n = new Set(s); n.delete(it.id); return n; });
  };

  const moveBack = (it, e) => {
    e.stopPropagation();
    const variant = it.variant || "outreach";
    addToUnassigned(variant, it.influencer, it);
    removeFromInbox(it.id);
    setReadIds(s => { const n = new Set(s); n.delete(it.id); return n; });
    notify(`${it.influencer.name} returned to ${variant === "leads" ? "Unassigned Potential Leads" : "Unassigned Outreach"}.`);
  };

  const archiveFromInbox = (it, e) => {
    e.stopPropagation();
    archiveInfluencerFromInbox(it);
    removeFromInbox(it.id);
    setReadIds(s => { const n = new Set(s); n.delete(it.id); return n; });
    notify(`${it.influencer?.name} archived. Reason recorded in their history.`);
  };

  const acknowledge = (it, e) => {
    e.stopPropagation();
    removeFromInbox(it.id);
    setReadIds(s => { const n = new Set(s); n.delete(it.id); return n; });
    notify(`Acknowledged — ${it.specialist} notified.`);
  };

  const sendReply = () => {
    if (!replyText.trim() || !replyFor) return;
    // Create a proper request thread so the OS/CM can see and respond
    const reqId = "REQ-" + Math.floor(Math.random() * 9000 + 1000);
    const now = new Date();
    const at = now.toLocaleDateString("en-GB", { day: "2-digit", month: "short" }) + ", " + now.toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit" });
    const isCM = !!replyFor.isCM;
    const raisedById = isCM ? replyFor.cmId : replyFor.specialistId;
    const req = {
      id: reqId,
      type: "Status Dispute",
      summary: `Re: status override on ${replyFor.influencer?.name}`,
      status: "Waiting for Specialist",
      raisedBy: { id: raisedById || "unknown", name: replyFor.specialist, role: isCM ? "collab" : "outreach" },
      influencer: replyFor.influencer || { name: "Unknown", handle: "" },
      campaign: null,
      raisedAt: at,
      thread: [
        { from: "admin", name: "Farah K. (Admin)", message: replyText.trim(), at },
      ],
    };
    addRequest(req);
    removeFromInbox(replyFor.id);
    setReadIds(s => { const n = new Set(s); n.delete(replyFor.id); return n; });
    notify(`Reply sent to ${replyFor.specialist} — a request thread has been opened.`);
    setReplyFor(null);
    setReplyText("");
  };

  const openRequest = (it, e) => {
    e.stopPropagation();
    markRead(it.id);
    setPage({ key: "requests" });
  };

  // Alerts = action-required items; Activity = informational FYI items
  const ACTIVITY_KINDS = ["stage-complete", "os-bundle-accepted", "cm-bundle-accepted"];
  const alertItems    = items.filter(it => !ACTIVITY_KINDS.includes(it.kind));
  const activityItems = items.filter(it =>  ACTIVITY_KINDS.includes(it.kind));

  const tabItems = mainTab === "alerts" ? alertItems : activityItems;

  const unreadAlerts   = alertItems.filter(it => !it.read).length;
  const unreadActivity = activityItems.filter(it => !it.read).length;

  const filtered = useMemo(() => {
    let list = mainTab === "alerts" ? alertItems : activityItems;
    if (readFilter === "unread") list = list.filter(it => !it.read);
    else if (readFilter === "read") list = list.filter(it => it.read);
    if (kindFilter) list = list.filter(it => it.kind === kindFilter);
    if (searchQ) {
      const q = searchQ.toLowerCase();
      list = list.filter(it => {
        const name    = it.influencer?.name?.toLowerCase() || "";
        const id      = it.id?.toLowerCase() || "";
        const summary = (it.summary || it.message || "").toLowerCase();
        return name.includes(q) || id.includes(q) || summary.includes(q);
      });
    }
    return list;
  }, [mainTab, alertItems, activityItems, readFilter, kindFilter, searchQ]);

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

  const switchMainTab = (t) => { setMainTab(t); setReadFilter("all"); setKindFilter(null); setSearchQ(""); setPg(1); };

  const kindLabel = (it) => {
    if (it.kind === "rejected-from-bundle")  return { tone: "alert",  text: "Bundle Rejection" };
    if (it.kind === "override-disputed" || it.kind === "admin-override-response") return { tone: "warn", text: "Override Disputed" };
    if (it.kind === "new-request")           return { tone: "info",   text: "New Request" };
    if (it.kind === "request-followup")      return { tone: "accent", text: "Request Follow-up" };
    if (it.kind === "os-removed" || it.kind === "cm-removed") return { tone: "alert", text: "Person Removed" };
    if (it.kind === "bundle-dropped") return { tone: "warn", text: "Bundle Dropped" };
    if (it.kind === "stage-complete")        return { tone: "ok",     text: "Stage Completed" };
    if (it.kind === "os-bundle-accepted")    return { tone: "ok",     text: "Bundle Accepted (OS)" };
    if (it.kind === "cm-bundle-accepted")    return { tone: "ok",     text: "Bundle Accepted (CM)" };
    if (it.kind === "os-no-response")        return { tone: "warn",   text: "No Response" };
    if (it.kind === "os-influencer-rejected") return { tone: "alert", text: "Influencer Declined" };
    if (it.kind === "influencer-dropped")    return { tone: "alert",  text: "Dropped by CM" };
    return { tone: "neutral", text: "System" };
  };

  return (
    <div className="page">
      <div className="page-head">
        <div>
          <h1>Inbox</h1>
          <div className="subtitle">Bundle rejections, no-response alerts, CM drops, override disputes, and specialist follow-ups.</div>
        </div>
        <div className="meta">
          {unreadCount > 0 && <Chip tone="alert" xs>{unreadCount} unread</Chip>}
          <span>{items.length} total</span>
        </div>
      </div>

      {/* ── Main tabs — position:relative + z-index keeps them above card content ── */}
      <div className="tabs" style={{ marginBottom: 0, background: "transparent", position: "relative", zIndex: 10 }}>
        <div className={`tab ${mainTab === "alerts" ? "active" : ""}`} onClick={() => switchMainTab("alerts")}>
          Alerts &amp; Actions
          <span className="count">{alertItems.length}</span>
          {unreadAlerts > 0 && <span style={{ width: 6, height: 6, borderRadius: 99, background: "var(--accent)", display: "inline-block", marginLeft: 2 }} />}
        </div>
        <div className={`tab ${mainTab === "activity" ? "active" : ""}`} onClick={() => switchMainTab("activity")}>
          Activity
          <span className="count">{activityItems.length}</span>
          {unreadActivity > 0 && <span style={{ width: 6, height: 6, borderRadius: 99, background: "var(--accent)", display: "inline-block", marginLeft: 2 }} />}
        </div>
      </div>

      {/* ── Toolbar row 1: read filter + mark as read + search ── */}
      <div className="toolbar" style={{ marginTop: 14 }}>
        {[
          { k: "all",    label: "All",    count: (mainTab === "alerts" ? alertItems : activityItems).length },
          { k: "unread", label: "Unread", count: (mainTab === "alerts" ? alertItems : activityItems).filter(it => !it.read).length },
          { k: "read",   label: "Read",   count: (mainTab === "alerts" ? alertItems : activityItems).filter(it => it.read).length },
        ].map(f => (
          <button key={f.k} className={`btn sm ${readFilter === f.k ? "primary" : "ghost"}`}
            style={{ display: "flex", alignItems: "center", gap: 5 }}
            onClick={() => { setReadFilter(f.k); setPg(1); }}>
            {f.label}
            <span style={{ background: readFilter === f.k ? "rgba(255,255,255,0.25)" : "var(--line-2)", color: readFilter === f.k ? "#fff" : "var(--ink-3)", borderRadius: 4, padding: "0 5px", fontSize: 10, fontFamily: "var(--font-mono)" }}>{f.count}</span>
          </button>
        ))}
        {paged.some(it => !it.read) && (
          <button className="btn ghost sm" style={{ fontSize: 11 }}
            onClick={() => paged.filter(it => !it.read).forEach(it => markRead(it.id))}>
            Mark page as read
          </button>
        )}
        <div className="spacer" />
        <div className="search">
          <Ic.search />
          <input placeholder="Search…" value={searchQ} onChange={e => { setSearchQ(e.target.value); setPg(1); }} />
          {searchQ && <button className="search-clear" onClick={() => { setSearchQ(""); setPg(1); }}><Ic.x /></button>}
        </div>
      </div>

      {/* ── Toolbar row 2: kind filters ── */}
      {mainTab === "alerts" && (
        <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 4 }}>
          {[
            { k: null,                       label: "All types" },
            { k: "rejected-from-bundle",     label: "Bundle Rejection" },
            { k: "override-disputed",         label: "Override Disputed" },
            { k: "new-request",              label: "New Request" },
            { k: "request-followup",         label: "Request Follow-up" },
            { k: "os-no-response",           label: "No Response" },
            { k: "os-influencer-rejected",   label: "Influencer Declined" },
            { k: "influencer-dropped",       label: "Dropped by CM" },
          ].filter(f => f.k === null || alertItems.some(it => it.kind === f.k)).map(f => (
            <button key={String(f.k)} className={`btn sm ${kindFilter === f.k ? "primary" : "ghost"}`}
              onClick={() => { setKindFilter(kindFilter === f.k ? null : f.k); setPg(1); }}>
              {f.label}
            </button>
          ))}
        </div>
      )}
      {mainTab === "activity" && (
        <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 4 }}>
          {[
            { k: null,                   label: "All types" },
            { k: "stage-complete",       label: "Stage Completed" },
            { k: "os-bundle-accepted",   label: "Bundle Accepted (OS)" },
            { k: "cm-bundle-accepted",   label: "Bundle Accepted (CM)" },
          ].filter(f => f.k === null || activityItems.some(it => it.kind === f.k)).map(f => (
            <button key={String(f.k)} className={`btn sm ${kindFilter === f.k ? "primary" : "ghost"}`}
              onClick={() => { setKindFilter(kindFilter === f.k ? null : f.k); setPg(1); }}>
              {f.label}
            </button>
          ))}
        </div>
      )}

      {filtered.length === 0 ? (
        <div className="card" style={{ textAlign: "center", padding: "48px 20px" }}>
          <div style={{ fontSize: 14, color: "var(--ink-3)", fontWeight: 500 }}>
            {readFilter === "all" && !kindFilter && !searchQ ? "Inbox empty — all caught up." : "No items match this filter."}
          </div>
        </div>
      ) : (
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          {paged.map(it => {
            const kl = kindLabel(it);
            const isRequest = it.kind === "new-request" || it.kind === "request-followup";
            return (
              <div key={it.id} className="card"
                style={{ borderLeft: it.read ? undefined : "3px solid var(--accent)", cursor: "pointer" }}
                onClick={() => markRead(it.id)}>
                {/* Header */}
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 10 }}>
                  <div style={{ display: "flex", gap: 6, alignItems: "center", flexWrap: "wrap" }}>
                    {!it.read && <span style={{ width: 7, height: 7, borderRadius: 99, background: "var(--accent)", flexShrink: 0 }} />}
                    <span className="pill">{it.id}</span>
                    <Chip tone={kl.tone} xs>{kl.text}</Chip>
                    {it.bundle && <BundleIdChip id={it.bundle} />}
                    {isRequest && it.reqId && <span className="pill" style={{ opacity: 0.7 }}>{it.reqId}</span>}
                  </div>
                  <div style={{ fontFamily: "var(--mono)", fontSize: 11, color: "var(--ink-3)", whiteSpace: "nowrap", marginLeft: 8 }}>{it.at}</div>
                </div>

                {/* Body */}
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 16 }}>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    {it.influencer && <InfCell name={it.influencer.name} handle={it.influencer.handle} />}
                    <div style={{ fontSize: 13, color: "var(--ink-2)", marginTop: 8, lineHeight: 1.5 }}>
                      {it.kind === "rejected-from-bundle" && (
                        it.isReturning
                          ? <><strong>{it.rejectedBy}</strong> rejected this returning influencer during bundle acceptance. They remain eligible for re-assignment via the campaign's "Assign Returning Influencer" flow.</>
                          : <><strong>{it.rejectedBy}</strong> rejected this influencer during bundle acceptance. Move them back to {it.variant === "leads" ? "Unassigned Leads" : "Unassigned Outreach"} to reassign.</>
                      )}
                      {(it.kind === "override-disputed" || it.kind === "admin-override-response") && (
                        <><strong>{it.specialist}</strong> has reviewed your status override and changed it back. Acknowledge to accept, or reply to explain.</>
                      )}
                      {it.kind === "new-request" && (
                        <><strong>{it.raisedBy?.name}</strong> ({it.raisedBy?.kind}) raised a <strong>{it.type}</strong> request: {it.summary}</>
                      )}
                      {it.kind === "request-followup" && (
                        <><strong>{it.raisedBy?.name}</strong> added a follow-up to <strong>{it.reqId}</strong>: {it.summary}</>
                      )}
                      {(it.kind === "stage-complete" || it.kind === "os-bundle-accepted" || it.kind === "cm-bundle-accepted") && (
                        <>{it.message}</>
                      )}
                      {it.kind === "os-no-response" && (
                        <><strong>{it.specialist}</strong> marked <strong>{it.influencer?.name}</strong> as No Response after 2 contact attempts. Move back to retry with a different specialist, or archive them.</>
                      )}
                      {it.kind === "os-influencer-rejected" && (
                        <><strong>{it.influencer?.name}</strong> declined the collaboration. Reported by <strong>{it.specialist}</strong>. Move back to reassign, or archive if no longer relevant.</>
                      )}
                      {it.kind === "influencer-dropped" && (
                        <><strong>{it.specialist}</strong> dropped {it.influencer?.name}{it.campaignName ? ` from ${it.campaignName}` : ""}. The influencer has been removed from the collaboration pipeline.</>
                      )}
                      {it.kind === "bundle-dropped" && (
                        <>{it.message}</>
                      )}
                    </div>
                    {it.reason && (
                      <div className="card tinted" style={{ marginTop: 8, padding: "8px 12px", fontSize: 12.5, fontStyle: "italic", lineHeight: 1.5 }}>"{it.reason}"</div>
                    )}
                  </div>

                  {/* Actions */}
                  <div style={{ display: "flex", flexDirection: "column", gap: 6, alignItems: "flex-end", flexShrink: 0 }}>
                    {isRequest && (
                      <button className="btn primary" onClick={(e) => openRequest(it, e)}>
                        Open Request <Ic.arrowRight />
                      </button>
                    )}
                    {it.kind === "rejected-from-bundle" && (
                      it.isReturning
                        ? <button className="btn primary" onClick={(e) => { e.stopPropagation(); dismiss(it); notify(`Acknowledged — ${it.influencer?.name} remains eligible for returning assignment.`); }}>
                            <Ic.check /> Acknowledge
                          </button>
                        : <button className="btn primary" onClick={(e) => moveBack(it, e)}>
                            <Ic.arrowLeft /> Move Back to List
                          </button>
                    )}
                    {(it.kind === "override-disputed" || it.kind === "admin-override-response") && (
                      <>
                        <button className="btn primary" onClick={(e) => acknowledge(it, e)}><Ic.check /> Acknowledge</button>
                        <button className="btn" onClick={(e) => { e.stopPropagation(); markRead(it.id); setReplyFor(it); setReplyText(""); }}>Reply</button>
                      </>
                    )}
                    {(it.kind === "os-no-response" || it.kind === "os-influencer-rejected") && (
                      <>
                        <button className="btn primary" onClick={(e) => moveBack(it, e)}>
                          <Ic.arrowLeft /> Move Back to Unassigned
                        </button>
                        <button className="btn" onClick={(e) => archiveFromInbox(it, e)}>
                          Archive Influencer
                        </button>
                      </>
                    )}
                    {it.kind === "influencer-dropped" && (
                      <>
                        <button className="btn primary" onClick={(e) => {
                          e.stopPropagation();
                          if (it.assignmentId) restoreDroppedInfluencer(it.assignmentId);
                          removeFromInbox(it.id);
                          setReadIds(s => { const n = new Set(s); n.delete(it.id); return n; });
                          notify(`${it.influencer?.name} restored to Unassigned Leads.`);
                        }}>
                          <Ic.arrowLeft /> Restore to Unassigned Leads
                        </button>
                        <button className="btn" onClick={(e) => archiveFromInbox(it, e)}>
                          Archive Influencer
                        </button>
                      </>
                    )}
                    <button className="btn ghost sm" onClick={(e) => { e.stopPropagation(); dismiss(it); }}>Dismiss</button>
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      )}

      <TablePagination page={pg} totalPages={totalPages} onPage={setPg} total={filtered.length} perPage={perPage} />

      {replyFor && (
        <Modal open={true} onClose={() => { setReplyFor(null); setReplyText(""); }}
          title={`Reply to ${replyFor.specialist}`}
          sub={`Re: status override on ${replyFor.influencer?.name}`}
          foot={<>
            <span className="text-xs text-mute">Your reply is sent to the specialist and this item is closed.</span>
            <div style={{ display: "flex", gap: 8 }}>
              <button className="btn" onClick={() => { setReplyFor(null); setReplyText(""); }}>Cancel</button>
              <button className="btn primary" disabled={!replyText.trim()} onClick={sendReply}>Send Reply</button>
            </div>
          </>}>
          <div className="card tinted" style={{ marginBottom: 14, fontSize: 13 }}>
            <div className="text-mono text-xs text-mute" style={{ marginBottom: 6, textTransform: "uppercase", letterSpacing: "0.1em" }}>
              Context · {replyFor.influencer?.name}
            </div>
            {replyFor.message || replyFor.reason || "Specialist changed status back after your override."}
          </div>
          <div className="field">
            <label>Your message to {replyFor.specialist}</label>
            <textarea className="textarea" rows="5" value={replyText} onChange={e => setReplyText(e.target.value)}
              placeholder={`Explain your reasoning or next steps to ${replyFor.specialist}…`} autoFocus />
          </div>
        </Modal>
      )}
    </div>
  );
}

Object.assign(window, { RequestsPage, AdminInboxPage, TablePagination });
