/* Robindex v2 — NotificationBell2: bell + unread badge + dropdown.
   Mount inside PrivyProvider (uses usePrivy for 401 → logout).
   - On mount / every 60s / on rx2:refresh → RXAPI.notifications({limit:30})
   - Response: {items:[{id,ts,type,title,body,kol_id,read_at}], unread}
   - Dropdown: bilingual empty/loading/error/list (sorted by ts desc)
   - "Mark all read" → RXAPI.markRead(unreadIds); on success local read_at + unread=0
   - Click outside closes; unmount clears interval + listener.
   - No mock fallback. 401/unauthorized → privy.logout() (clear key). */
const { useState: nbS, useEffect: nbE, useRef: nbR } = React;
const nbL = (en, zh) => (window.RXI && window.RXI.lang === "zh" ? zh : en);

function NotificationBell2() {
  const { Icon } = window.RXC;
  const E = window.RXE;
  // ClaimModal pattern: Privy bridge for 401 → clear key (sign out).
  const privy = window.PrivySDK && window.PrivySDK.usePrivy ? window.PrivySDK.usePrivy() : null;

  const [items, setItems] = nbS([]);
  const [unread, setUnread] = nbS(0);
  const [loading, setLoading] = nbS(true);
  const [err, setErr] = nbS(null);
  const [open, setOpen] = nbS(false);
  const [marking, setMarking] = nbS(false);
  const wrapRef = nbR(null);
  const bellRef = nbR(null);

  function handleAuthError() {
    if (privy && typeof privy.logout === "function") {
      try { privy.logout(); } catch (e) { console.warn("[NotificationBell2] privy.logout failed:", e); }
    }
    setErr(nbL("Session expired — please sign in again.", "登录已过期，请重新登录。"));
  }

  // Never throws. network/throw → err="network_error". 401 → logout. No mock fallback.
  async function load() {
    try {
      const r = await window.RXAPI.notifications({ limit: 30 });
      if (!r) { setErr("network_error"); return; }
      if (r.status === 401 || r.error === "unauthorized") { handleAuthError(); return; }
      if (r.error) { setErr(r.error); return; }
      setErr(null);
      setItems(Array.isArray(r.items) ? r.items : []);
      setUnread(typeof r.unread === "number" ? r.unread : 0);
    } catch (_) {
      setErr("network_error");
    }
  }

  // mount: load immediately + interval 60s + rx2:refresh listener; cleanup on unmount.
  nbE(() => {
    let cancelled = false;
    setLoading(true);
    load().finally(() => { if (!cancelled) setLoading(false); });
    const iv = setInterval(load, 60 * 1000);
    const onRefresh = () => load();
    window.addEventListener("rx2:refresh", onRefresh);
    return () => {
      cancelled = true;
      clearInterval(iv);
      window.removeEventListener("rx2:refresh", onRefresh);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // click outside → close; Escape → close + focus bell
  nbE(() => {
    if (!open) return;
    const onDoc = (e) => {
      if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
    };
    const onKey = (e) => {
      if (e.key === "Escape") {
        setOpen(false);
        if (bellRef.current) bellRef.current.focus();
      }
    };
    document.addEventListener("mousedown", onDoc);
    document.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("mousedown", onDoc);
      document.removeEventListener("keydown", onKey);
    };
  }, [open]);

  const sorted = items.slice().sort((a, b) => (b.ts || 0) - (a.ts || 0));
  const unreadIds = items.filter((i) => !i.read_at).map((i) => i.id);

  const markAll = async () => {
    if (marking || unreadIds.length === 0) return;
    setMarking(true);
    try {
      const r = await window.RXAPI.markRead(unreadIds);
      if (!r) return;
      if (r.status === 401 || r.error === "unauthorized") { handleAuthError(); return; }
      if (r.error) return;
      // success: local read_at on all unread + unread=0
      const now = Date.now();
      setItems((arr) => arr.map((i) => (i.read_at ? i : { ...i, read_at: now })));
      setUnread(0);
    } catch (_) {
      // silent — no mock fallback
    } finally {
      setMarking(false);
    }
  };

  const zh = !!(window.RXI && window.RXI.lang === "zh");
  const last = sorted.length - 1;

  return (
    <div ref={wrapRef} style={{ position: "relative", display: "inline-flex" }}>
      <button
        type="button"
        ref={bellRef}
        className="topbal"
        aria-label={unread > 0 ? nbL(`Notifications, ${unread} unread`, `通知，${unread} 条未读`) : nbL("Notifications", "通知")}
        aria-expanded={open ? "true" : "false"}
        onClick={() => setOpen((o) => !o)}
        style={{ position: "relative" }}
      >
        <Icon name="lightbulb" size={14} color="var(--accent)" />
        {unread > 0 && (
          <span aria-hidden="true" style={{
            position: "absolute", top: -5, right: -5,
            minWidth: 16, height: 16, padding: "0 4px",
            borderRadius: 999, background: "var(--down)", color: "#fff",
            font: "600 10px var(--mono)", lineHeight: "14px",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
            border: "2px solid var(--panel)", boxSizing: "border-box",
          }}>{unread > 99 ? "99+" : unread}</span>
        )}
      </button>
      {open && (
        <div role="region" aria-label={nbL("Notifications", "通知")} style={{
          position: "absolute", top: "calc(100% + 8px)", right: 0,
          width: 340, maxWidth: "calc(100vw - 24px)",
          background: "var(--panel)", border: "1px solid var(--border)",
          borderRadius: "var(--r-lg)", boxShadow: "var(--sh-lg)",
          zIndex: 50, overflow: "hidden",
        }}>
          <div style={{
            display: "flex", alignItems: "center", gap: 8,
            padding: "11px 14px", borderBottom: "1px solid var(--border-soft)",
          }}>
            <Icon name="lightbulb" size={14} color="var(--accent)" />
            <span style={{ font: "600 13px var(--sans)", color: "var(--text)" }}>{nbL("Notifications", "通知")}</span>
            {unread > 0 && (
              <button
                type="button"
                className="btn-ghost"
                onClick={markAll}
                disabled={marking}
                style={{ marginLeft: "auto", padding: "5px 9px", font: "600 11px var(--sans)" }}
              >
                {marking ? (zh ? "处理中…" : "Marking…") : (zh ? "全部标为已读" : "Mark all read")}
              </button>
            )}
          </div>
          <div style={{ maxHeight: 360, overflowY: "auto" }}>
            {loading ? (
              <div role="status" style={{ padding: "22px 14px", textAlign: "center", color: "var(--dim)", font: "400 12.5px var(--sans)" }}>
                {zh ? "加载中…" : "Loading…"}
              </div>
            ) : err ? (
              <div style={{ padding: 14 }}>
                <div className="x2-note x2-danger" role="alert">
                  <Icon name="shield" size={13} style={{ flex: "none", marginTop: 1 }} />
                  {err === "network_error"
                    ? (zh ? "网络错误，请重试" : "Network error, please retry")
                    : (zh ? "加载失败，请重试" : "Failed to load, please retry")}
                </div>
                <button className="btn-ghost" style={{ marginTop: 10 }} onClick={load}>
                  <Icon name="refresh" size={12} />{zh ? "重试" : "Retry"}
                </button>
              </div>
            ) : sorted.length === 0 ? (
              <div role="status" style={{ padding: "22px 14px", textAlign: "center", color: "var(--faint)", font: "400 12.5px var(--sans)" }}>
                {zh ? "暂无通知" : "No notifications"}
              </div>
            ) : (
              sorted.map((n, i) => (
                <div key={n.id} className="lg-row" style={{ padding: "11px 14px", borderBottom: i === last ? "none" : "1px solid var(--border-soft)" }}>
                  <div className="lg-ic" style={{ background: n.read_at ? "var(--panel-2)" : "var(--accent-ghost)" }}>
                    <Icon name={n.read_at ? "check" : "lightbulb"} size={13} color={n.read_at ? "var(--faint)" : "var(--accent)"} />
                  </div>
                  <div className="lg-main">
                    <div className="lg-t">{n.title || ""}</div>
                    {n.body && <div className="lg-s">{n.body}</div>}
                    {n.ts && <div className="lg-ts" style={{ marginTop: 2 }}>{E.fmtDT(n.ts)}</div>}
                  </div>
                </div>
              ))
            )}
          </div>
        </div>
      )}
    </div>
  );
}

window.NotificationBell2 = NotificationBell2;
