// screens-operations.jsx — Messaging Queue (design visuals, live backend).
// Plus shared operations helpers used here and in screens-operations-2.jsx.
// Every action calls the real API (/api/messaging/*) and refetches.
const { useState: useOpsState, useEffect: useOpsEffect, useRef: useOpsRef, useCallback: useOpsCallback } = React;

/* ---- shared async hook: { loading, error, data } + refetch() ---------- */
function useOpsAsync(fn, deps = []) {
  const [state, setState] = useOpsState({ loading: true, error: null, data: null });
  const mounted = useOpsRef(true);
  useOpsEffect(() => () => { mounted.current = false; }, []);
  const run = useOpsCallback(() => {
    setState((s) => ({ ...s, loading: true, error: null }));
    return Promise.resolve().then(fn).then((d) => { if (mounted.current) setState({ loading: false, error: null, data: d }); return d; })
      .catch((e) => { if (mounted.current) setState({ loading: false, error: e.message || "Request failed", data: null }); });
  }, deps); // eslint-disable-line
  useOpsEffect(() => { run(); }, [run]);
  return [state, run];
}

/* ---- shared time helpers ---------------------------------------------- */
function relTime(iso) {
  if (!iso) return "—";
  const d = new Date(iso).getTime();
  if (isNaN(d)) return "—";
  const s = Math.floor((Date.now() - d) / 1000);
  if (s < 0) return "just now";
  if (s < 60) return "just now";
  if (s < 3600) return Math.floor(s / 60) + " min ago";
  if (s < 86400) return Math.floor(s / 3600) + " hr ago";
  if (s < 172800) return "Yesterday";
  return Math.floor(s / 86400) + " days ago";
}
const fmtClock = (iso) => { try { return new Date(iso).toLocaleString("en-GB", { day: "2-digit", month: "short", hour: "2-digit", minute: "2-digit" }); } catch { return "—"; } };

/* ---- shared status / priority metadata (from the design tokens) ------- */
const QUEUE_STATUS = {
  queued: { tone: "neutral", label: "Queued", c: "#9CA3AF" },
  scheduled: { tone: "blue", label: "Scheduled", c: "#2563EB" },
  sending: { tone: "blue", label: "Sending", c: "#2563EB" },
  sent: { tone: "purple", label: "Sent", c: "#7E22CE" },
  delivered: { tone: "lime", label: "Delivered", c: "#4A6400" },
  read: { tone: "green", label: "Read", c: "#22C55E" },
  failed: { tone: "red", label: "Failed", c: "#B91C1C" },
  retry: { tone: "orange", label: "Retry scheduled", c: "#EA580C" },
  cancelled: { tone: "neutral", label: "Cancelled", c: "#9CA3AF" },
  uncertain: { tone: "orange", label: "Send uncertain", c: "#EA580C" },
};
const SENDER_STATUS = {
  active: { tone: "green", label: "Active", c: "#22C55E" },
  paused: { tone: "neutral", label: "Paused", c: "#9CA3AF" },
  cooled: { tone: "orange", label: "Cooled down", c: "#EA580C" },
  over: { tone: "red", label: "Over limit", c: "#B91C1C" },
};
const ESC_STATUS = {
  open: { tone: "orange", label: "Open", c: "#EA580C" },
  review: { tone: "blue", label: "In review", c: "#2563EB" },
  waiting: { tone: "purple", label: "Waiting customer", c: "#7E22CE" },
  resolved: { tone: "green", label: "Resolved", c: "#22C55E" },
  closed: { tone: "neutral", label: "Closed", c: "#9CA3AF" },
};
const REQ_STATUS = {
  new: { tone: "blue", label: "New", c: "#2563EB" },
  pricing: { tone: "orange", label: "Needs pricing", c: "#EA580C" },
  reviewed: { tone: "purple", label: "Reviewed", c: "#7E22CE" },
  proposal: { tone: "lime", label: "Proposal sent", c: "#4A6400" },
  won: { tone: "green", label: "Won", c: "#22C55E" },
  lost: { tone: "red", label: "Lost", c: "#B91C1C" },
};
// numeric queue priority (backend) → design priority key
function prioFromNum(p) { const n = typeof p === "number" ? p : 1; return n >= 3 ? "urgent" : n === 2 ? "high" : n >= 1 ? "medium" : "low"; }
// a backend job re-scheduled after a failed attempt is shown as "retry"
function jobDispStatus(j) { return (j.status === "scheduled" && (j.attempts || 0) > 0) ? "retry" : j.status; }
// derive sender display status from the live record
function senderDisp(s) {
  if ((s.sentToday || 0) >= (s.dailyCapacity || 0) && (s.dailyCapacity || 0) > 0) return "over";
  if (s.status === "cooldown") return "cooled";
  return s.status === "paused" ? "paused" : "active";
}

/* ---- shared UI atoms (design) ----------------------------------------- */
function OverviewCard({ label, value, icon, c, active, onClick }) {
  return (
    <button onClick={onClick} className={"card" + (onClick ? " card--hover" : "")} style={{ padding: 16, textAlign: "start", cursor: onClick ? "pointer" : "default", border: active ? "1.5px solid var(--color-secondary)" : "1px solid var(--border-1)" }}>
      <div className="row" style={{ gap: 8, marginBottom: 10, color: "var(--fg-4)" }}><Icon name={icon} size={16} style={{ color: c || "var(--fg-3)" }} /><span style={{ fontSize: 12, fontWeight: 600 }}>{label}</span></div>
      <div style={{ fontSize: 26, fontWeight: 800, letterSpacing: "-0.02em" }}>{value}</div>
    </button>
  );
}
function FilterPill({ on, onClick, children }) {
  return (
    <button onClick={onClick} style={{ height: 34, padding: "0 14px", borderRadius: 999, fontSize: 13, fontWeight: 600,
      border: "1px solid " + (on ? "var(--color-secondary)" : "var(--border-2)"),
      background: on ? "var(--color-secondary)" : "#fff", color: on ? "#fff" : "var(--fg-2)" }}>{children}</button>
  );
}
function PrioTag({ p }) {
  const m = PRIORITY_META[p] || PRIORITY_META.medium;
  return <span className="row" style={{ gap: 6, fontWeight: 600, fontSize: 13 }}><span className="sdot" style={{ background: m.c }} />{m.label}</span>;
}
function OpsToast({ msg }) {
  if (!msg) return null;
  return <div className="fade-up" style={{ position: "fixed", bottom: 24, insetInlineStart: "50%", transform: "translateX(-50%)", background: "var(--color-secondary)", color: "#fff", padding: "12px 20px", borderRadius: "var(--radius-md)", boxShadow: "var(--shadow-lg)", fontSize: 13.5, fontWeight: 600, zIndex: 60, display: "flex", alignItems: "center", gap: 8 }}><Icon name="checkcircle" size={16} />{msg}</div>;
}
function OpsError({ msg }) {
  if (!msg) return null;
  return <div className="row" style={{ gap: 10, background: "var(--color-danger-soft)", color: "var(--color-danger)", borderRadius: 10, padding: "10px 12px", fontSize: 12.5, marginBottom: 14 }}><Icon name="alert" size={15} />{msg}</div>;
}

/* ============================ MESSAGING QUEUE ========================== */
function SenderRow({ s, busy, onPause, onResume, onReset }) {
  const disp = senderDisp(s);
  const m = SENDER_STATUS[disp];
  const limit = s.dailyCapacity || 0, used = s.sentToday || 0;
  const pct = limit ? Math.round((used / limit) * 100) : 0;
  return (
    <div className="card" style={{ padding: 16 }}>
      <div className="between" style={{ marginBottom: 12 }}>
        <div className="row" style={{ gap: 10, minWidth: 0 }}>
          <span className="opp" style={{ width: 36, height: 36, borderRadius: 10, background: "var(--bg-2)", color: "var(--fg-3)", flexShrink: 0 }}><Icon name="phoneDevice" size={18} /></span>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontWeight: 700, fontSize: 13.5, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{s.label}</div>
            <div style={{ fontSize: 11.5, color: "var(--fg-4)", fontFamily: "monospace" }} dir="ltr">{s.phone}</div>
          </div>
        </div>
        <Badge tone={m.tone} dot={m.c}>{m.label}</Badge>
      </div>
      <div className="between" style={{ fontSize: 11.5, color: "var(--fg-4)", marginBottom: 5 }}>
        <span>{used}/{limit} sent · {Math.max(0, limit - used)} left</span>
        <span className="row" style={{ gap: 4 }}><Icon name="shield" size={12} />{s.healthScore ?? 100}</span>
      </div>
      <div style={{ height: 6, borderRadius: 999, background: "var(--border-1)", overflow: "hidden", marginBottom: 12 }}>
        <div style={{ height: "100%", width: Math.min(100, pct) + "%", borderRadius: 999, background: pct >= 100 ? "var(--color-danger)" : pct >= 80 ? "var(--color-orange)" : "var(--color-success)" }} />
      </div>
      <div className="between">
        <span style={{ fontSize: 11, color: "var(--fg-disabled)" }}>health {s.healthScore ?? 100}%</span>
        {disp === "active"
          ? <button className="btn btn--subtle btn--sm" disabled={busy} onClick={() => onPause(s.id)}><Icon name="pause" size={13} />Pause</button>
          : disp === "paused"
            ? <button className="btn btn--ghost btn--sm" disabled={busy} onClick={() => onResume(s.id)}><Icon name="play" size={13} />Resume</button>
            : <button className="btn btn--subtle btn--sm" disabled={busy} onClick={() => onReset(s.id)}><Icon name="refresh" size={13} />Reset</button>}
      </div>
    </div>
  );
}

function MessagingQueueScreen() {
  const data = useStore();
  const [statusF, setStatusF] = useOpsState("all");
  const [failedOnly, setFailedOnly] = useOpsState(false);
  const [m, refetchM] = useOpsAsync(() => API.messaging.metrics(), []);
  const [q, refetchQ] = useOpsAsync(() => API.messaging.queue("limit=300"), []);
  const [selected, setSelected] = useOpsState(() => new Set());
  const [detailId, setDetailId] = useOpsState(null);
  const [busy, setBusy] = useOpsState(null);
  const [actErr, setActErr] = useOpsState(null);
  const [toast, setToast] = useOpsState("");

  const flash = (msg) => { setToast(msg); setTimeout(() => setToast(""), 2200); };
  const refetch = () => { refetchM(); refetchQ(); };
  const act = async (name, fn, ok) => { setBusy(name); setActErr(null); try { await fn(); refetch(); setSelected(new Set()); if (ok) flash(ok); } catch (e) { setActErr(e.message); } finally { setBusy(null); } };

  const metrics = m.data || {};
  const by = metrics.byStatus || {};
  const senders = metrics.senders || [];
  const allJobs = q.data?.jobs || [];
  const campaignName = (id) => (data.CAMPAIGNS || []).find((c) => c.id === id)?.name || "—";
  const leadName = (id) => (data.CONTACTS || []).find((c) => c.id === id)?.name;
  const leadPerson = (id) => (data.CONTACTS || []).find((c) => c.id === id)?.person;
  const senderName = (id) => senders.find((s) => s.id === id)?.label || id || "—";

  const filtered = allJobs.filter((j) => {
    const d = jobDispStatus(j);
    if (failedOnly) return d === "failed";
    if (statusF === "all") return true;
    return d === statusF;
  });

  const OVERVIEW = [
    { key: "queued", label: "Queued", icon: "layers" }, { key: "scheduled", label: "Scheduled", icon: "calendar" },
    { key: "sending", label: "Sending", icon: "send" }, { key: "sent", label: "Sent", icon: "check2" },
    { key: "delivered", label: "Delivered", icon: "checkcircle" }, { key: "read", label: "Read", icon: "eye" },
    { key: "failed", label: "Failed", icon: "alert" }, { key: "cancelled", label: "Cancelled", icon: "x" },
    // A1 — only surfaced when there ARE crash-window sends to verify (keeps the grid clean).
    ...(by.uncertain ? [{ key: "uncertain", label: "Uncertain", icon: "alert" }] : []),
  ];
  const toggleSel = (id) => setSelected((s) => { const n = new Set(s); n.has(id) ? n.delete(id) : n.add(id); return n; });

  return (
    <div className="content__inner content__inner--wide fade-up" style={{ maxWidth: 1320 }}>
      <OpsError msg={actErr || m.error || q.error} />

      {/* overview */}
      <div className="grid" style={{ gridTemplateColumns: "repeat(4,1fr)", gap: 12, marginBottom: 28 }}>
        {OVERVIEW.map((o) => (
          <OverviewCard key={o.key} label={o.label} value={by[o.key] ?? 0} icon={o.icon} c={QUEUE_STATUS[o.key]?.c} active={statusF === o.key} onClick={() => { setStatusF(statusF === o.key ? "all" : o.key); setFailedOnly(false); }} />
        ))}
      </div>

      {/* sender pool */}
      <div className="between" style={{ marginBottom: 14 }}>
        <h5>Sender pool</h5>
        <div className="row" style={{ gap: 10 }}>
          <span className="subtle" style={{ fontSize: 12 }}>{senders.filter((s) => senderDisp(s) === "active").length} active · rotation on</span>
          <button className="btn btn--ghost btn--sm" disabled={!!busy} onClick={() => act("dispatch", () => API.messaging.dispatch({ max: 200 }), "Dispatch run complete")}><Icon name="zap" size={14} />{busy === "dispatch" ? "Dispatching…" : "Dispatch now"}</button>
          <button className="btn btn--ghost btn--sm" onClick={refetch}><Icon name="refresh" size={14} />Refresh</button>
        </div>
      </div>
      <div className="grid" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(240px, 1fr))", gap: 12, marginBottom: 28 }}>
        {senders.length ? senders.map((s) => (
          <SenderRow key={s.id} s={s} busy={!!busy}
            onPause={(id) => act("snd" + id, () => API.messaging.updateSender(id, { status: "paused" }), "Sender paused")}
            onResume={(id) => act("snd" + id, () => API.messaging.updateSender(id, { status: "active" }), "Sender resumed")}
            onReset={(id) => act("snd" + id, () => API.messaging.updateSender(id, { status: "active", sentToday: 0, healthScore: 100 }), "Sender reset")} />
        )) : m.loading ? <div className="skel" style={{ height: 150, borderRadius: 16 }} /> : <Card><EmptyState icon="phoneDevice" title="No senders" body="Add WhatsApp sender lines in Settings to start sending." /></Card>}
      </div>

      {/* queue table */}
      <div className="between" style={{ marginBottom: 14 }}>
        <h5>Queue <span className="subtle" style={{ fontWeight: 600, fontSize: 13 }}>· {metrics.queueSize ?? 0} jobs</span></h5>
        <div className="row" style={{ gap: 8 }}>
          {selected.size > 0 ? <>
            <span className="subtle" style={{ fontSize: 13 }}>{selected.size} selected</span>
            {statusF === "uncertain" ? <>
              {/* A1 — uncertain sends: operator verifies, never auto-resent. */}
              <button className="btn btn--subtle btn--sm" disabled={!!busy} title="Confirmed delivered — mark sent without resending" onClick={() => act("verifySent", () => API.messaging.resolveUncertain([...selected], "sent"), selected.size + " marked sent")}><Icon name="check2" size={14} />Mark sent</button>
              <button className="btn btn--ghost btn--sm" disabled={!!busy} title="Confirmed NOT delivered — queue another send" onClick={() => act("verifyRetry", () => API.messaging.resolveUncertain([...selected], "retry"), selected.size + " queued to retry")}><Icon name="refresh" size={14} />Retry send</button>
              <button className="btn btn--ghost btn--sm" disabled={!!busy} onClick={() => act("cancelSel", () => API.messaging.cancel([...selected]), selected.size + " jobs cancelled")}><Icon name="x" size={14} />Cancel</button>
            </> : <>
              <button className="btn btn--subtle btn--sm" disabled={!!busy} onClick={() => act("retrySel", () => API.messaging.retry([...selected]), selected.size + " jobs queued for retry")}><Icon name="refresh" size={14} />Retry</button>
              <button className="btn btn--ghost btn--sm" disabled={!!busy} onClick={() => act("cancelSel", () => API.messaging.cancel([...selected]), selected.size + " jobs cancelled")}><Icon name="x" size={14} />Cancel</button>
            </>}
          </> : <>
            <FilterPill on={failedOnly} onClick={() => { setFailedOnly(!failedOnly); setStatusF("all"); }}>Failed only</FilterPill>
            <button className="btn btn--ghost btn--sm" disabled={!!busy} onClick={() => act("retryAll", () => API.messaging.retry(), "Failed jobs queued for retry")}><Icon name="refresh" size={14} />{busy === "retryAll" ? "Retrying…" : "Retry all failed"}</button>
          </>}
        </div>
      </div>

      {q.loading ? <Card><div className="skel" style={{ height: 200, borderRadius: 8 }} /></Card>
        : filtered.length === 0 ? (
          <Card><EmptyState icon="inbox" title="Queue is clear" body="No jobs match this filter. New messages appear here as campaigns dispatch." /></Card>
        ) : (
          <Card flush>
            <div style={{ overflowX: "auto", maxHeight: 520, overflowY: "auto" }}>
              <table className="table">
                <thead><tr>
                  <th style={{ width: 40 }}></th><th>Lead</th><th>Campaign</th><th>Sender</th><th>Priority</th><th>Status</th><th>Attempts</th><th>Scheduled</th><th>Last error</th><th>Updated</th>
                </tr></thead>
                <tbody>
                  {filtered.map((j) => {
                    const disp = jobDispStatus(j);
                    const sm = QUEUE_STATUS[disp] || QUEUE_STATUS.queued;
                    return (
                      <tr key={j.id} onClick={() => setDetailId(j.id)}>
                        <td onClick={(e) => { e.stopPropagation(); toggleSel(j.id); }}>
                          <span style={{ width: 18, height: 18, borderRadius: 5, display: "inline-flex", alignItems: "center", justifyContent: "center", border: "1.5px solid " + (selected.has(j.id) ? "var(--color-secondary)" : "var(--border-2)"), background: selected.has(j.id) ? "var(--color-secondary)" : "#fff", color: "#fff" }}>{selected.has(j.id) && <Icon name="check" size={12} />}</span>
                        </td>
                        <td><div><div style={{ fontWeight: 700, fontSize: 13.5 }}>{leadName(j.leadId) || (j.to || "—")}</div><div style={{ fontSize: 11.5, color: "var(--fg-4)", fontFamily: "monospace" }} dir="ltr">{j.to}</div></div></td>
                        <td style={{ fontSize: 12.5, maxWidth: 150, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{campaignName(j.campaignId)}</td>
                        <td style={{ fontSize: 12.5 }}>{senderName(j.senderId).replace("Maxab ", "")}</td>
                        <td><PrioTag p={prioFromNum(j.priority)} /></td>
                        <td><Badge tone={sm.tone} dot={sm.c}>{sm.label}</Badge></td>
                        <td style={{ fontWeight: 600 }}>{j.attempts || 0}</td>
                        <td style={{ fontSize: 12.5, color: "var(--fg-3)" }}>{j.scheduledAt ? fmtClock(j.scheduledAt) : (j.sentAt ? fmtClock(j.sentAt) : "—")}</td>
                        <td style={{ fontSize: 12, color: j.error ? "var(--color-danger)" : "var(--fg-disabled)", maxWidth: 160, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{j.error || "—"}</td>
                        <td style={{ fontSize: 12, color: "var(--fg-4)" }}>{relTime(j.updatedAt)}</td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          </Card>
        )}

      <OpsToast msg={toast} />
      {detailId && <JobDetailDrawer jobId={detailId} leadName={leadName} leadPerson={leadPerson} senderName={senderName} campaignName={campaignName}
        onClose={() => setDetailId(null)}
        onRetry={(id) => act("retryOne", () => API.messaging.retry([id]), "Job queued for retry").then(() => setDetailId(null))} />}
    </div>
  );
}

function JobDetailDrawer({ jobId, onClose, onRetry, leadName, leadPerson, senderName, campaignName }) {
  const { go } = useApp();
  const [st] = useOpsAsync(() => API.messaging.job(jobId), [jobId]);
  const j = st.data;
  const disp = j ? jobDispStatus(j) : "queued";
  const sm = QUEUE_STATUS[disp] || QUEUE_STATUS.queued;
  // delivery receipts derived from real timestamps/status
  const receipts = j ? [
    j.createdAt && `Queued ${fmtClock(j.createdAt)}`,
    j.sentAt && `Sent ${fmtClock(j.sentAt)}`,
    (disp === "delivered" || disp === "read") && `Delivered ${relTime(j.updatedAt)}`,
    disp === "read" && `Read ${relTime(j.updatedAt)}`,
    disp === "failed" && `Failed after ${j.attempts} attempt(s) — ${j.error || "send failed"}`,
  ].filter(Boolean) : [];
  return (
    <Drawer onClose={onClose}>
      <DrawerHead title={j ? (leadName(j.leadId) || j.to || "Queue job") : "Queue job"} sub={j ? `${leadPerson(j.leadId) || ""} ${j.to || ""}`.trim() : jobId} onClose={onClose} right={j ? <Badge tone={sm.tone} dot={sm.c}>{sm.label}</Badge> : null} />
      <div style={{ overflowY: "auto", padding: 24, display: "flex", flexDirection: "column", gap: 16 }}>
        {st.loading ? <div className="skel" style={{ height: 160, borderRadius: 12 }} /> : st.error ? <OpsError msg={st.error} /> : j ? (
          <>
            {disp === "failed" && <div className="row" style={{ gap: 10, background: "var(--color-danger-soft)", borderRadius: "var(--radius-md)", padding: 14 }}>
              <Icon name="alert" size={18} style={{ color: "var(--color-danger)", flexShrink: 0 }} />
              <div style={{ flex: 1 }}><div style={{ fontWeight: 700, fontSize: 13.5, color: "var(--color-danger)" }}>Send failed after {j.attempts} attempts</div><div style={{ fontSize: 12.5, color: "var(--fg-2)" }}>{j.error}</div></div>
              <Button variant="dark" size="sm" icon="refresh" onClick={() => onRetry(j.id)}>Retry</Button>
            </div>}

            <Card title="Message"><p dir="auto" style={{ fontSize: 14, lineHeight: 1.6, color: "var(--fg-1)" }}>{j.text || "—"}</p></Card>

            <Card title="Job">
              <div className="col" style={{ gap: 12 }}>
                <div className="between"><span className="muted" style={{ fontSize: 13 }}>Campaign</span><span style={{ fontSize: 13, fontWeight: 600 }}>{campaignName(j.campaignId)}</span></div>
                <div className="between"><span className="muted" style={{ fontSize: 13 }}>Sender</span><span className="row" style={{ gap: 6, fontSize: 13, fontWeight: 600 }}><Icon name="phoneDevice" size={14} style={{ color: "var(--fg-3)" }} />{senderName(j.senderId)}</span></div>
                <div className="between"><span className="muted" style={{ fontSize: 13 }}>Priority</span><PrioTag p={prioFromNum(j.priority)} /></div>
                <div className="between"><span className="muted" style={{ fontSize: 13 }}>Attempts</span><span style={{ fontSize: 13, fontWeight: 600 }}>{j.attempts || 0}/{j.maxAttempts || 3}</span></div>
                <div className="between"><span className="muted" style={{ fontSize: 13 }}>Scheduled</span><span style={{ fontSize: 13 }}>{j.scheduledAt ? fmtClock(j.scheduledAt) : "—"}</span></div>
              </div>
            </Card>

            <Card title="Provider response">
              <code style={{ fontSize: 12.5, fontFamily: "monospace", color: disp === "failed" ? "var(--color-danger)" : "var(--fg-2)", wordBreak: "break-all" }}>{j.providerMessageId || j.error || "—"}</code>
            </Card>

            <Card title="Delivery receipts">
              {receipts.length ? <div className="col" style={{ gap: 10 }}>
                {receipts.map((r, i) => (
                  <div key={i} className="row" style={{ gap: 10, fontSize: 13 }}>
                    <span className="sdot" style={{ background: r.includes("Failed") ? "var(--color-danger)" : r.includes("Read") ? "var(--color-success)" : "var(--color-blue)" }} />
                    <span style={{ color: "var(--fg-2)" }}>{r}</span>
                  </div>
                ))}
              </div> : <span className="muted" style={{ fontSize: 13 }}>No events yet.</span>}
            </Card>

            <div className="row" style={{ gap: 10 }}>
              {j.conversationId && <Button variant="dark" icon="message" onClick={() => { go("conversations"); onClose(); }}>Open conversation</Button>}
              {(disp === "failed" || disp === "retry") && <Button variant="ghost" icon="refresh" onClick={() => onRetry(j.id)}>Retry now</Button>}
            </div>
          </>
        ) : <EmptyState icon="inbox" title="Job not found" />}
      </div>
    </Drawer>
  );
}

window.MessagingQueueScreen = MessagingQueueScreen;
window.OverviewCard = OverviewCard;
window.FilterPill = FilterPill;
window.PrioTag = PrioTag;
window.useOpsAsync = useOpsAsync;
