/* ============================================================
   ui.jsx — shared UI primitives (window.UI.*)
   Minimal stroke icons (Lucide-style) + small components.
   ============================================================ */
const { useState, useEffect, useRef } = React;

/* ---- Icon: small Lucide-style stroke set ---- */
const PATHS = {
  home: "M3 10.5 12 3l9 7.5M5 9.5V20a1 1 0 0 0 1 1h3v-6h6v6h3a1 1 0 0 0 1-1V9.5",
  layers: "M12 3 3 8l9 5 9-5-9-5ZM3 13l9 5 9-5M3 17l9 5 9-5",
  pen: "M12 20h9M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5Z",
  repeat: "M17 2l4 4-4 4M3 11V9a4 4 0 0 1 4-4h14M7 22l-4-4 4-4M21 13v2a4 4 0 0 1-4 4H3",
  folder: "M3 7a2 2 0 0 1 2-2h4l2 2.5h8a2 2 0 0 1 2 2V18a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7Z",
  plus: "M12 5v14M5 12h14",
  search: "M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16ZM21 21l-4.3-4.3",
  trash: "M3 6h18M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2M19 6l-1 14a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1L5 6",
  x: "M18 6 6 18M6 6l12 12",
  check: "M20 6 9 17l-5-5",
  arrowRight: "M5 12h14M13 6l6 6-6 6",
  sparkles: "M12 3l1.8 4.6L18 9l-4.2 1.4L12 15l-1.8-4.6L6 9l4.2-1.4L12 3ZM19 14l.9 2.3L22 17l-2.1.7L19 20l-.9-2.3L16 17l2.1-.7L19 14Z",
  edit: "M11 4H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-5M18.5 2.5a2.1 2.1 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5Z",
  clock: "M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18ZM12 7v5l3 2",
  flame: "M12 3c1 3-1 4-1 6a3 3 0 0 0 6 0c0-1 0-2-.5-3 2 1.5 3.5 4 3.5 7a8 8 0 1 1-16 0c0-4 3-6 4-9 .8 1 2 1.8 4 -1Z",
  inbox: "M3 12h5l2 3h4l2-3h5M5 5h14a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1Z",
  chevronRight: "M9 6l6 6-6 6",
  book: "M4 5a2 2 0 0 1 2-2h13v16H6a2 2 0 0 0-2 2V5ZM19 17H6a2 2 0 0 0-2 2",
};
function Icon({ name, size = 18, stroke = 2, className, style }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none"
      stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round"
      className={className} style={style} aria-hidden="true">
      <path d={PATHS[name] || ""} />
    </svg>
  );
}

function Button({ variant = "ghost", size, block, busy, icon, iconRight, children, className = "", ...rest }) {
  const cls = ["btn", `btn-${variant}`, size === "lg" ? "btn-lg" : size === "sm" ? "btn-sm" : "", block ? "btn-block" : "", className].filter(Boolean).join(" ");
  return (
    <button className={cls} disabled={busy || rest.disabled} {...rest}>
      {busy ? <span className={"spinner" + (variant === "primary" ? " light" : "")} /> : icon ? <Icon name={icon} size={size === "lg" ? 19 : 17} /> : null}
      {children}
      {iconRight && !busy ? <Icon name={iconRight} size={size === "lg" ? 19 : 17} /> : null}
    </button>
  );
}

function IconButton({ name, size = 18, danger, ...rest }) {
  return <button className={"icon-btn" + (danger ? " danger" : "")} {...rest}><Icon name={name} size={size} /></button>;
}

const FORMAL_LABEL = { formal: "격식", neutral: "중립", casual: "캐주얼" };
function FormalityBadge({ value }) {
  return <span className={"badge " + (value || "neutral")}>{FORMAL_LABEL[value] || "중립"}</span>;
}

function Tag({ children }) { return <span className="tag">{children}</span>; }

function Field({ label, children }) {
  return <div className="field">{label && <label>{label}</label>}{children}</div>;
}

function Spinner({ light }) { return <span className={"spinner" + (light ? " light" : "")} />; }

function AiPill({ children = "AI" }) {
  return <span className="ai-pill"><Icon name="sparkles" size={12} /> {children}</span>;
}

function EmptyState({ icon = "inbox", title, sub, action }) {
  return (
    <div className="empty">
      <div className="empty-ic"><Icon name={icon} size={22} /></div>
      <div className="h-md" style={{ color: "var(--ink-2)" }}>{title}</div>
      {sub && <div className="faint" style={{ maxWidth: 320 }}>{sub}</div>}
      {action && <div style={{ marginTop: 6 }}>{action}</div>}
    </div>
  );
}

function Modal({ title, onClose, children, foot, wide }) {
  useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose]);
  return (
    <div className="overlay" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="modal" style={wide ? { maxWidth: 680 } : undefined} role="dialog" aria-modal="true">
        <div className="modal-head">
          <div className="h-md">{title}</div>
          <IconButton name="x" size={18} onClick={onClose} aria-label="닫기" />
        </div>
        <div className="modal-body">{children}</div>
        {foot && <div className="modal-foot">{foot}</div>}
      </div>
    </div>
  );
}

/* fmt: relative day label in Korean */
function relDay(ts) {
  if (!ts) return "—";
  const Store = window.Store;
  const d = Store.daysUntil(ts);
  if (d <= 0) return "오늘";
  if (d === 1) return "내일";
  if (d < 7) return `${d}일 후`;
  if (d < 30) return `${Math.round(d / 7)}주 후`;
  return `${Math.round(d / 30)}개월 후`;
}
function agoDay(ts) {
  if (!ts) return "—";
  const d = Math.round((window.Store.todayStart() - new Date(ts).setHours(0,0,0,0)) / 86400000);
  if (d <= 0) return "오늘";
  if (d === 1) return "어제";
  if (d < 7) return `${d}일 전`;
  if (d < 30) return `${Math.round(d / 7)}주 전`;
  return `${Math.round(d / 30)}개월 전`;
}

Object.assign(window, {
  UI: { Icon, Button, IconButton, FormalityBadge, Tag, Field, Spinner, AiPill, EmptyState, Modal, relDay, agoDay },
});
