/* SEAL — shared UI primitives. Exported to window. */
const { useState, useEffect, useRef, useCallback } = React;
const F = window.SEAL_FMT;

/* ---- Badge ---- */
function Badge({ tone = "gray", dot = false, children }) {
  return (
    <span className={`badge badge-${tone}`}>
      {dot && <span className="dot" />}
      {children}
    </span>
  );
}

/* verdict → badge tone */
function VerdictBadge({ verdict }) {
  const map = {
    "집행가능": "green", "적정": "green", "완료": "green",
    "결재대기": "orange", "검수대기": "orange",
    "불인정": "red", "주의": "orange",
  };
  return <Badge tone={map[verdict] || "gray"} dot>{verdict}</Badge>;
}

/* ---- Button ---- */
function Btn({ variant = "primary", size = "md", icon, iconRight, block, disabled, onClick, children }) {
  const I = icon ? Icons[icon] : null;
  const IR = iconRight ? Icons[iconRight] : null;
  return (
    <button
      className={`btn btn-${size} btn-${variant} ${block ? "btn-block" : ""}`}
      disabled={disabled} onClick={onClick}>
      {I && <I size={size === "sm" ? 15 : 17} />}
      {children && <span>{children}</span>}
      {IR && <IR size={size === "sm" ? 15 : 17} />}
    </button>
  );
}

/* ---- KPI ---- */
function Kpi({ label, value, foot, accent, icon }) {
  const I = icon ? Icons[icon] : null;
  return (
    <div className={`kpi ${accent ? "accent" : ""}`}>
      <div className="kpi-label">{I && <I size={15} />}{label}</div>
      <div className="kpi-value tnum">{value}</div>
      {foot && <div className="kpi-foot">{foot}</div>}
    </div>
  );
}

/* ---- Budget bar row ---- */
function BudgetBar({ item, onClick }) {
  const pct = F.pct(item.spent, item.budget);
  const cls = pct >= 100 ? "over" : pct >= 80 ? "near" : "";
  const [w, setW] = useState(0);
  useEffect(() => { const t = setTimeout(() => setW(pct), 60); return () => clearTimeout(t); }, [pct]);
  return (
    <div className={`barrow ${item.active ? "" : "muted"}`} onClick={onClick} style={onClick ? { cursor: "pointer" } : null}>
      <div className="barrow-top">
        <div className="barrow-name">
          {item.name}
          <span className="barrow-group">{item.group}</span>
          {!item.active && <Badge tone="gray">곧 지원</Badge>}
        </div>
        <div className="barrow-figs tnum">
          <b>{F.manwon(item.budget)}</b> 중 {F.manwon(item.spent)}
        </div>
      </div>
      <div className="bartrack">
        <div className={`barfill ${cls}`} style={{ width: `${item.active ? w : 0}%` }} />
      </div>
      <div className="barrow-foot tnum">
        {item.active
          ? <>잔액 <b>{F.manwon(item.remain)}</b> 남음 · {pct}% 집행</>
          : <>집행 준비 중 · 계획 {F.manwon(item.budget)}</>}
      </div>
    </div>
  );
}

/* ---- Accordion ---- */
function Accordion({ title, meta, defaultOpen = false, children }) {
  const [open, setOpen] = useState(defaultOpen);
  return (
    <div className={`acc-item ${open ? "open" : ""}`}>
      <div className="acc-head" onClick={() => setOpen(!open)}>
        <span className="acc-t">{title}</span>
        {meta && <span className="badge badge-gray">{meta}</span>}
        <Icons.chevDown className="acc-chev" size={18} />
      </div>
      {open && <div className="acc-body fade-in">{children}</div>}
    </div>
  );
}

/* ---- Page header ---- */
function PageHead({ eyebrow, title, sub, action }) {
  return (
    <div className="page-head">
      {eyebrow && <div className="page-eyebrow">{eyebrow}</div>}
      <div className="row" style={{ justifyContent: "space-between", alignItems: "flex-start", gap: 16 }}>
        <div style={{ flex: 1, minWidth: 0 }}>
          <h1 className="page-title">{title}</h1>
          {sub && <p className="page-sub">{sub}</p>}
        </div>
        {action}
      </div>
    </div>
  );
}

/* ---- Section header ---- */
function SecHead({ title, link, onLink }) {
  return (
    <div className="sec-head">
      <div className="sec-title">{title}</div>
      {link && <div className="sec-link" onClick={onLink}>{link}<Icons.chevRight size={14} /></div>}
    </div>
  );
}

/* ---- Empty state ---- */
function Empty({ icon = "inbox", title, children }) {
  const I = Icons[icon];
  return (
    <div className="empty">
      <div className="empty-ico"><I size={26} /></div>
      <h3>{title}</h3>
      <p>{children}</p>
    </div>
  );
}

/* ---- Skeleton block ---- */
function Skel({ h = 16, w = "100%", r = 8, style }) {
  return <div className="skel" style={{ height: h, width: w, borderRadius: r, ...style }} />;
}

/* ---- Toast host (global via window event) ---- */
function ToastHost() {
  const [toasts, setToasts] = useState([]);
  useEffect(() => {
    const h = (e) => {
      const id = Math.random();
      setToasts((t) => [...t, { id, ...e.detail }]);
      setTimeout(() => setToasts((t) => t.filter((x) => x.id !== id)), 2600);
    };
    window.addEventListener("seal-toast", h);
    return () => window.removeEventListener("seal-toast", h);
  }, []);
  return (
    <div className="toast-wrap">
      {toasts.map((t) => (
        <div key={t.id} className={`toast ${t.ok ? "ok" : ""}`}>
          <span className="tc">{t.ok ? <Icons.checkCircle size={18} /> : <Icons.alert size={18} />}</span>
          {t.msg}
        </div>
      ))}
    </div>
  );
}
function toast(msg, ok = true) {
  window.dispatchEvent(new CustomEvent("seal-toast", { detail: { msg, ok } }));
}

/* ---- Layer chip (법/시행령/기관/과제 근거) ---- */
function LayerChip({ layer, ref: refText }) {
  const tone = "gray";
  return (
    <div className="row" style={{ gap: 8, padding: "8px 0", alignItems: "flex-start" }}>
      <Badge tone={tone}>{layer}</Badge>
      <span style={{ fontSize: 13.5, color: "var(--semantic-label-neutral)", lineHeight: 1.5, fontWeight: 500 }}>{refText}</span>
    </div>
  );
}

Object.assign(window, {
  Badge, VerdictBadge, Btn, Kpi, BudgetBar, Accordion,
  PageHead, SecHead, Empty, Skel, ToastHost, toast, LayerChip,
});
