// === Shared UI helpers ===
const { useState, useEffect, useMemo, useRef, useCallback } = React;

const formatKRW = (n) => "₩" + Math.round(n).toLocaleString("ko-KR");
const formatNum = (n) => Math.round(n).toLocaleString("ko-KR");
const formatDate = (s) => s.split(" ")[0].replace(/-/g, ".");

// Toast manager
let toastSetter;
function ToastHost() {
  const [toasts, setToasts] = useState([]);
  toastSetter = setToasts;
  useEffect(() => {
    if (toasts.length === 0) return;
    const t = setTimeout(() => setToasts(arr => arr.slice(1)), 2800);
    return () => clearTimeout(t);
  }, [toasts]);
  return (
    <div className="toast-stack">
      {toasts.map((t, i) => (
        <div className="toast" key={i}>
          <window.I.Check size={14} stroke="#03c75a" />
          {t}
        </div>
      ))}
    </div>
  );
}
function toast(msg) { toastSetter && toastSetter(arr => [...arr, msg]); }
window.toast = toast;

// 실제 이미지 또는 그라데이션 placeholder (imageUrl 없을 때)
function ProductThumb({ tone = 0, name = "", size = 36, radius = 6, imageUrl = "" }) {
  const [errored, setErrored] = useState(false);
  if (imageUrl && !errored) {
    return (
      <img src={imageUrl} alt={name}
           onError={() => setErrored(true)}
           style={{
             width: size, height: size, borderRadius: radius,
             objectFit: "cover", background: "var(--bg-elev)",
             flexShrink: 0,
             boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.06)",
           }} />
    );
  }
  const [a, b] = window.MOCK.TONES[tone % window.MOCK.TONES.length];
  const initial = name.replace(/[^가-힣A-Za-z]/g, "").slice(0, 2);
  return (
    <div style={{
      width: size, height: size, borderRadius: radius,
      background: `linear-gradient(135deg, ${a}, ${b})`,
      display: "flex", alignItems: "center", justifyContent: "center",
      color: "rgba(255,255,255,0.9)", fontWeight: 700,
      fontSize: Math.max(10, size * 0.32),
      flexShrink: 0,
      boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.04)",
    }}>
      {initial}
    </div>
  );
}
window.ProductThumb = ProductThumb;

// Modal
function Modal({ open, onClose, title, children, footer, size = "" }) {
  if (!open) return null;
  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className={"modal " + (size === "lg" ? "modal-lg" : size === "xl" ? "modal-xl" : "")} onClick={e => e.stopPropagation()}>
        <div className="modal-header">
          <div className="modal-title">{title}</div>
          <button className="btn btn-icon btn-ghost btn-sm" onClick={onClose}><window.I.X size={14} /></button>
        </div>
        <div className="modal-body">{children}</div>
        {footer && <div className="modal-footer">{footer}</div>}
      </div>
    </div>
  );
}
window.Modal = Modal;

// Status badge for products
function StatusBadge({ status }) {
  const map = {
    active: { label: "판매중", cls: "badge-success" },
    outofstock: { label: "품절", cls: "badge-warn" },
    paused: { label: "판매중지", cls: "" },
    pending: { label: "결제대기", cls: "" },
    paid: { label: "결제완료", cls: "badge-info" },
    shipped: { label: "배송중", cls: "badge-warn" },
    delivered: { label: "배송완료", cls: "badge-success" },
    canceled: { label: "취소", cls: "badge-danger" },
    returned: { label: "반품", cls: "badge-danger" },
    exchanged: { label: "교환", cls: "badge-warn" },
  };
  const c = map[status] || { label: status, cls: "" };
  return <span className={"badge badge-dot " + c.cls}>{c.label}</span>;
}
window.StatusBadge = StatusBadge;

// MiniSpark — sparkline chart
function MiniSpark({ data, height = 40, color = "var(--accent)" }) {
  const max = Math.max(...data);
  const min = Math.min(...data);
  const w = 100;
  const pts = data.map((v, i) => {
    const x = (i / (data.length - 1)) * w;
    const y = height - ((v - min) / (max - min || 1)) * (height - 4) - 2;
    return `${x},${y}`;
  }).join(" ");
  const areaPts = `0,${height} ${pts} ${w},${height}`;
  return (
    <svg viewBox={`0 0 ${w} ${height}`} preserveAspectRatio="none" style={{ width: "100%", height, display: "block" }}>
      <polygon points={areaPts} fill={color} opacity="0.1" />
      <polyline points={pts} fill="none" stroke={color} strokeWidth="1.5" />
    </svg>
  );
}
window.MiniSpark = MiniSpark;
