// VaultUI — app-wide in-Vault dialogs. Replaces native alert()/confirm().
//   await window.VaultUI.confirm({ title, message, confirmLabel, danger })  -> Promise<boolean>
//   window.VaultUI.toast(kind, msg)   kind: "success" | "error" | "info"
//   window.VaultUI.alert(msg)         -> info toast
// A single <window.VaultUIHost/> mounted at the app root renders the modal + toast.
(function () {
  const BLUE = "#196EA7", INK = "#1A2733", INK2 = "#5A6B7B", LINE = "#E4E9F0";
  let _emit = null; // host registers its dispatcher here

  window.VaultUI = {
    _register(fn) { _emit = fn; },
    confirm(opts) {
      return new Promise(resolve => {
        if (_emit) _emit({ type: "confirm", opts: opts || {}, resolve });
        else resolve(window.confirm((opts && opts.message) || "Are you sure?")); // pre-mount fallback
      });
    },
    toast(kind, msg) {
      if (_emit) _emit({ type: "toast", kind: kind || "info", msg: msg });
      else console.log("[toast]", kind, msg);
    },
    alert(msg) { this.toast("info", msg); },
  };

  function VaultUIHost() {
    const { useState, useEffect, useRef } = React;
    const [confirmReq, setConfirmReq] = useState(null);
    const [toast, setToast] = useState(null);
    const toastTimer = useRef(null);

    useEffect(() => {
      window.VaultUI._register(req => {
        if (req.type === "confirm") {
          setConfirmReq(req);
        } else if (req.type === "toast") {
          if (toastTimer.current) clearTimeout(toastTimer.current);
          setToast({ kind: req.kind, msg: req.msg });
          toastTimer.current = setTimeout(() => setToast(null), req.kind === "error" ? 8000 : 5000);
        }
      });
      return () => { window.VaultUI._register(null); };
    }, []);

    const close = (val) => { if (confirmReq) confirmReq.resolve(val); setConfirmReq(null); };
    const o = confirmReq ? confirmReq.opts : null;
    const toastColors = toast && (toast.kind === "error"
      ? { bg: "#FDECEC", bd: "#F5C2C2", fg: "#9B2C2C" }
      : toast.kind === "success"
        ? { bg: "#E8F5EC", bd: "#BFE3CC", fg: "#216A3A" }
        : { bg: "#EAF2F8", bd: "#C5DBEC", fg: "#1B4C70" });

    return (
      <React.Fragment>
        {toast && (
          <div onClick={() => setToast(null)}
            style={{ position: "fixed", top: 18, left: "50%", transform: "translateX(-50%)", zIndex: 4001, cursor: "pointer",
              background: toastColors.bg, border: "1px solid " + toastColors.bd, color: toastColors.fg,
              padding: "11px 16px", borderRadius: 10, fontSize: 13.5, fontWeight: 600, boxShadow: "0 6px 20px rgba(0,0,0,.12)", maxWidth: 560 }}>
            {toast.msg}
          </div>
        )}
        {confirmReq && (
          <div onClick={() => close(false)}
            style={{ position: "fixed", inset: 0, background: "rgba(20,30,45,.35)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 4000 }}>
            <div onClick={e => e.stopPropagation()}
              style={{ background: "#fff", borderRadius: 14, border: "1px solid " + LINE, padding: 22, maxWidth: 440, margin: 16, boxShadow: "0 12px 44px rgba(0,0,0,.20)" }}>
              <div style={{ fontSize: 16, fontWeight: 600, color: INK, marginBottom: 8 }}>{o.title || "Confirm"}</div>
              <div style={{ fontSize: 13.5, color: INK2, lineHeight: 1.55, marginBottom: 18, whiteSpace: "pre-line" }}>{o.message}</div>
              <div style={{ display: "flex", justifyContent: "flex-end", gap: 8 }}>
                <button onClick={() => close(false)}
                  style={{ padding: "8px 16px", borderRadius: 9, border: "1px solid " + LINE, background: "#fff", color: INK2, fontSize: 13, fontWeight: 600, cursor: "pointer" }}>
                  {o.cancelLabel || "Cancel"}
                </button>
                <button onClick={() => close(true)}
                  style={{ padding: "8px 16px", borderRadius: 9, border: "none", background: o.danger ? "#C2410C" : BLUE, color: "#fff", fontSize: 13, fontWeight: 600, cursor: "pointer" }}>
                  {o.confirmLabel || "Confirm"}
                </button>
              </div>
            </div>
          </div>
        )}
      </React.Fragment>
    );
  }

  // ---- Harvey deep-link helpers ----
  window.VaultHarvey = {
    companyUrl: function (id) { return (id != null && id !== "") ? "https://db.harveyllc.com/company/" + id + "/target" : null; },
    projectUrl: function (id) { return (id != null && id !== "") ? "https://db.harveyllc.com/project/" + id : null; },
  };
  // <window.HarveyLink companyId={..} | projectId={..}>{name}</window.HarveyLink>
  // Renders a link to the Harvey record when an id is present; plain text otherwise.
  window.HarveyLink = function HarveyLink(props) {
    const cid = props.companyId, pid = props.projectId;
    const href = (cid != null && cid !== "") ? window.VaultHarvey.companyUrl(cid)
      : (pid != null && pid !== "") ? window.VaultHarvey.projectUrl(pid) : null;
    if (!href) return props.children;
    const style = Object.assign({ color: "var(--accent, #196EA7)", textDecoration: "none" }, props.style || {});
    const onClick = (e) => {
      e.stopPropagation();
      // Plain left-click on a company opens the in-app Company drawer; ctrl/cmd/shift-click still deep-links to Harvey.
      if (cid != null && cid !== "" && window.openCompany && !e.metaKey && !e.ctrlKey && !e.shiftKey && !e.altKey && e.button === 0) {
        e.preventDefault();
        const nm = props.companyName || (typeof props.children === "string" ? props.children : null);
        window.openCompany({ name: nm, harveyId: cid, pipeline: props.ctx || null });
      }
    };
    return <a href={href} target="_blank" rel="noopener noreferrer" style={style} onClick={onClick}>{props.children}</a>;
  };

  // ---- Batch 4 UI system primitives ----
  // PageToolbar: one consistent in-page header. Left: title + optional subtitle.
  // Right: any controls (scope pickers, period toggles, primary action button).
  // <window.PageToolbar title="Deal Pipeline" subtitle="Active targets · Scott module">
  //   {controls}
  // </window.PageToolbar>
  window.PageToolbar = function PageToolbar({ title, subtitle, children, style }) {
    return (
      <div className="page-toolbar" style={Object.assign({
        display: "flex", alignItems: "center", justifyContent: "space-between",
        gap: 12, flexWrap: "wrap", marginBottom: 16,
      }, style || {})}>
        <div style={{ minWidth: 0 }}>
          <h2 className="display" style={{ margin: 0, fontSize: 20, fontWeight: 650, color: "var(--ink)", lineHeight: 1.2 }}>{title}</h2>
          {subtitle ? <div className="muted" style={{ fontSize: 12.5, marginTop: 3 }}>{subtitle}</div> : null}
        </div>
        {children ? <div className="row" style={{ gap: 8, alignItems: "center", flexWrap: "wrap" }}>{children}</div> : null}
      </div>
    );
  };

  // Skeleton: shimmering placeholder bars while data loads.
  // <window.Skeleton rows={5}/> or <window.Skeleton width={220} height={14}/>
  window.Skeleton = function Skeleton({ rows = 1, width = "100%", height = 13, gap = 10, style }) {
    const bar = (i) => (
      <div key={i} className="vault-skeleton" style={Object.assign({
        width: typeof width === "number" ? width + "px" : width,
        height: height, borderRadius: 6,
        background: "linear-gradient(90deg, var(--line-2, #eceef1) 25%, var(--surface-2, #f4f6f8) 50%, var(--line-2, #eceef1) 75%)",
        backgroundSize: "200% 100%", animation: "vaultShimmer 1.2s ease-in-out infinite",
        marginBottom: i < rows - 1 ? gap : 0,
      }, style || {})}/>
    );
    return <div aria-busy="true">{Array.from({ length: rows }, (_, i) => bar(i))}</div>;
  };

  // EmptyState: friendly zero-data panel with optional action.
  // <window.EmptyState title="No closed deals" hint="Nothing in this scope/period." actionLabel="+ Add" onAction={fn}/>
  window.EmptyState = function EmptyState({ title, hint, actionLabel, onAction, style }) {
    return (
      <div style={Object.assign({
        padding: "28px 16px", textAlign: "center",
        border: "1px dashed var(--line)", borderRadius: 10, background: "var(--surface)",
      }, style || {})}>
        <div style={{ fontSize: 14, fontWeight: 600, color: "var(--ink-2)" }}>{title}</div>
        {hint ? <div className="muted" style={{ fontSize: 12.5, marginTop: 5 }}>{hint}</div> : null}
        {actionLabel && onAction ? (
          <button onClick={onAction} style={{ marginTop: 12, padding: "7px 14px", border: 0, borderRadius: 8,
            background: "var(--accent)", color: "var(--accent-ink, #fff)", fontSize: 13, fontWeight: 600, cursor: "pointer" }}>
            {actionLabel}
          </button>
        ) : null}
      </div>
    );
  };

  // ---- Acronym tooltips (Batch 4) --------------------------------------
  // <window.Acro k="CR"/> renders the acronym with a dotted underline and a
  // hover/tap tooltip carrying the expansion. Single source of truth below;
  // use at header/label level only (not in data cells).
  window.VAULT_GLOSSARY = {
    CR:   "Custom Re-approach",
    CRs:  "Custom Re-approaches",
    CC:   "Conference Call",
    CCs:  "Conference Calls",
    EBITDA: "Earnings Before Interest, Taxes, Depreciation & Amortization",
    LOI:  "Letter of Intent",
    LOIs: "Letters of Intent",
    IOI:  "Indication of Interest",
    IOIs: "Indications of Interest",
    EV:   "Enterprise Value",
    BHAG: "Big Hairy Audacious Goal",
    RPM:  "Research Progression Map",
    DM:   "Dealmaker",
    AA:   "Analyst/Associate",
    NDA:  "Non-Disclosure Agreement",
    NTP:  "New Target Profile \u2014 a newly researched company added to Harvey",
    NDAs: "Non-Disclosure Agreements",
  };
  window.Acro = function Acro({ k, children, style }) {
    const label = window.VAULT_GLOSSARY[k] || null;
    if (!label) return <span style={style}>{children || k}</span>;
    return (
      <span className="acro" tabIndex={0} style={style} title={label}>
        {children || k}
        <span className="acro-tip" role="tooltip">{label}</span>
      </span>
    );
  };

  // <window.AcroLabel text="Signed LOIs"/> — wraps any glossary tokens found in
  // a label string with <Acro/>; non-acronym text passes through untouched.
  window.AcroLabel = function AcroLabel({ text, style }) {
    const s = String(text == null ? "" : text);
    const parts = s.split(/([A-Za-z]+)/);
    return (
      <span style={style}>
        {parts.map((p, i) => window.VAULT_GLOSSARY[p]
          ? <window.Acro key={i} k={p}/>
          : <React.Fragment key={i}>{p}</React.Fragment>)}
      </span>
    );
  };

  window.VaultUIHost = VaultUIHost;
})();