// mailroom-ux.jsx — interaction layer: global toasts, centered modal, dropdown
// menu, confirm dialog. Exports: ToastHost, mrToast (window), Modal, Menu, Confirm.

/* ---------------- Toasts (global event bus) ---------------- */
// Any component can call window.mrToast("message", { tone, icon }). ToastHost
// (mounted once in Root) renders the stack. Avoids threading context everywhere.
window.mrToast = function (msg, opts = {}) {
  window.dispatchEvent(new CustomEvent("mr-toast", { detail: { msg, ...opts, id: Date.now() + Math.random() } }));
};

function ToastHost() {
  const t = useT();
  const [items, setItems] = React.useState([]);
  React.useEffect(() => {
    const on = (e) => {
      const toast = e.detail;
      setItems((cur) => [...cur, toast]);
      setTimeout(() => setItems((cur) => cur.filter((x) => x.id !== toast.id)), toast.duration || 2800);
    };
    window.addEventListener("mr-toast", on);
    return () => window.removeEventListener("mr-toast", on);
  }, []);
  const toneColor = (tone) => tone === "good" ? t.good : tone === "warn" ? t.warn : tone === "bad" ? t.bad : t.accent;
  return (
    <div style={{ position: "fixed", left: "50%", bottom: 24, transform: "translateX(-50%) scale(var(--dc-inv-zoom,1))",
      zIndex: 2147483600, display: "flex", flexDirection: "column", gap: 8, alignItems: "center", pointerEvents: "none" }}>
      {items.map((it) => (
        <div key={it.id} style={{ display: "flex", alignItems: "center", gap: 10, padding: "11px 16px 11px 13px",
          background: t.console, color: t.consoleText, border: `1px solid ${hexA("#fff", 0.14)}`, borderRadius: t.radiusSm,
          boxShadow: t.shadowLg, fontFamily: t.font, fontSize: 13.5, fontWeight: 500, maxWidth: 460,
          animation: "mrToastIn .26s cubic-bezier(.32,.72,.3,1)" }}>
          <span style={{ width: 22, height: 22, borderRadius: 5, flex: "0 0 auto", background: hexA(toneColor(it.tone), 0.22),
            display: "flex", alignItems: "center", justifyContent: "center" }}>
            <Icon name={it.icon || "check"} size={14} color={toneColor(it.tone)} />
          </span>
          <span>{it.msg}</span>
        </div>
      ))}
    </div>
  );
}

/* ---------------- Centered modal (pop-out) ---------------- */
function Modal({ open, onClose, title, sub, icon, iconTone, width = 460, children, footer, loud }) {
  const t = useT();
  if (!open) return null;
  const tc = iconTone === "warn" ? t.warn : iconTone === "bad" ? t.bad : iconTone === "marker" ? t.markerInk : t.accent;
  const tcb = iconTone === "warn" ? t.warnTint : iconTone === "bad" ? t.badTint : iconTone === "marker" ? t.markerTint : t.accentTint;
  return (
    <div onClick={onClose} style={{ position: "absolute", inset: 0, zIndex: 60, display: "flex", alignItems: "center",
      justifyContent: "center", padding: 24, background: hexA("#1c1814", t.dark ? 0.6 : 0.38), animation: "mrFade .16s ease" }}>
      <div onClick={(e) => e.stopPropagation()} style={{ width, maxWidth: "94%", maxHeight: "90%", overflow: "auto",
        background: t.bg, border: `1px solid ${loud ? t.markerBorder : t.border}`, borderRadius: t.radiusLg,
        boxShadow: t.shadowLg, animation: "mrPop .22s cubic-bezier(.32,.72,.3,1)" }}>
        <div style={{ display: "flex", alignItems: "flex-start", gap: 13, padding: "18px 18px 14px",
          borderBottom: `1px solid ${t.border}` }}>
          {icon && (
            <div style={{ width: 36, height: 36, borderRadius: t.radiusSm, background: tcb, border: `1px solid ${hexA(tc, 0.3)}`,
              display: "flex", alignItems: "center", justifyContent: "center", flex: "0 0 auto" }}>
              <Icon name={icon} size={18} color={tc} />
            </div>
          )}
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontFamily: t.head, fontSize: 16.5, fontWeight: 700, color: t.text, letterSpacing: "-.01em" }}>{title}</div>
            {sub && <div style={{ fontSize: 12.5, color: t.textMuted, marginTop: 3, lineHeight: 1.5 }}>{sub}</div>}
          </div>
          <IconBtn icon="x" onClick={onClose} />
        </div>
        <div style={{ padding: 18 }}>{children}</div>
        {footer && (
          <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "13px 18px", borderTop: `1px solid ${t.border}`,
            background: t.card }}>{footer}</div>
        )}
      </div>
    </div>
  );
}

/* ---------------- Dropdown menu ---------------- */
function Menu({ trigger, items, align = "right", width = 184 }) {
  const t = useT();
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const on = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    window.addEventListener("mousedown", on);
    return () => window.removeEventListener("mousedown", on);
  }, [open]);
  return (
    <span ref={ref} style={{ position: "relative", display: "inline-flex" }}>
      <span onClick={(e) => { e.stopPropagation(); setOpen(!open); }}>
        {trigger || <IconBtn icon="more" size={16} active={open} />}
      </span>
      {open && (
        <div style={{ position: "absolute", top: "calc(100% + 4px)", [align]: 0, width, zIndex: 70,
          background: t.card, border: `1px solid ${t.borderStrong}`, borderRadius: t.radiusSm, boxShadow: t.shadowMd,
          padding: 5, animation: "mrPop .16s cubic-bezier(.32,.72,.3,1)" }}>
          {items.map((it, i) => it.divider ? (
            <div key={i} style={{ height: 1, background: t.border, margin: "5px 0" }} />
          ) : (
            <button key={i} onClick={(e) => { e.stopPropagation(); setOpen(false); it.onClick && it.onClick(); }}
              style={{ display: "flex", alignItems: "center", gap: 9, width: "100%", textAlign: "left", border: "none",
                background: "transparent", cursor: "pointer", padding: "7px 9px", borderRadius: 4, fontFamily: t.font,
                fontSize: 13, fontWeight: 500, color: it.danger ? t.bad : t.text }}
              onMouseEnter={(e) => e.currentTarget.style.background = it.danger ? t.badTint : (t.dark ? t.sunken : t.bg)}
              onMouseLeave={(e) => e.currentTarget.style.background = "transparent"}>
              {it.icon && <Icon name={it.icon} size={15} color={it.danger ? t.bad : t.textMuted} />}
              {it.label}
            </button>
          ))}
        </div>
      )}
    </span>
  );
}

Object.assign(window, { ToastHost, Modal, Menu, Skeleton });

/* ---------------- Skeleton loader ---------------- */
function Skeleton({ t, w = "100%", h = 14, r, style }) {
  const tt = t || useT();
  return (
    <div style={{ width: w, height: h, borderRadius: r != null ? r : tt.radiusSm,
      background: `linear-gradient(90deg, ${tt.sunken} 25%, ${tt.dark ? tt.card2 : "#efe9db"} 50%, ${tt.sunken} 75%)`,
      backgroundSize: "200% 100%", animation: "mrShimmer 1.3s linear infinite", ...style }} />
  );
}
