// ==========================================
// Shared UI components
// ==========================================

const { useState, useEffect, useMemo, useRef } = React;

// ---------- Modal ----------
function Modal({ open, onClose, title, children, width = 560 }) {
  if (!open) return null;
  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" style={{ width }} onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <div className="modal-title">{title}</div>
          <button className="icon-btn" onClick={onClose} aria-label="close">✕</button>
        </div>
        <div className="modal-body">{children}</div>
      </div>
    </div>
  );
}

// ---------- Toast ----------
const ToastCtx = React.createContext(null);
function ToastProvider({ children }) {
  const [items, setItems] = useState([]);
  const push = (msg, kind = "ok") => {
    const id = Math.random().toString(36).slice(2);
    setItems((it) => [...it, { id, msg, kind }]);
    setTimeout(() => setItems((it) => it.filter((x) => x.id !== id)), 3200);
  };
  return (
    <ToastCtx.Provider value={push}>
      {children}
      <div className="toast-wrap">
        {items.map((t) => (
          <div key={t.id} className={`toast toast-${t.kind}`}>
            <span className="toast-dot" />
            {t.msg}
          </div>
        ))}
      </div>
    </ToastCtx.Provider>
  );
}
function useToast() {
  return React.useContext(ToastCtx);
}

// ---------- Badge ----------
function CatBadge({ cat }) {
  if (!cat) return null;
  return (
    <span className="cat-badge" style={{ background: cat.color + "1f", color: cat.color, borderColor: cat.color + "55" }}>
      <span className="cat-dot" style={{ background: cat.color }} />
      {cat.name}
    </span>
  );
}

// ---------- Stat card ----------
function StatCard({ label, value, sub, accent, icon }) {
  return (
    <div className="stat-card">
      <div className="stat-head">
        <div className="stat-label">{label}</div>
        {icon && <div className="stat-icon" style={{ background: (accent || "#222") + "1a", color: accent || "#222" }}>{icon}</div>}
      </div>
      <div className="stat-value" style={{ color: accent || "#111" }}>{value}</div>
      {sub && <div className="stat-sub">{sub}</div>}
    </div>
  );
}

// ---------- Empty ----------
function Empty({ text = "ไม่มีข้อมูล" }) {
  return <div className="empty">{text}</div>;
}

// ---------- Confirm ----------
function ConfirmBtn({ children, onConfirm, className = "btn-danger" }) {
  const [armed, setArmed] = useState(false);
  useEffect(() => {
    if (!armed) return;
    const t = setTimeout(() => setArmed(false), 3000);
    return () => clearTimeout(t);
  }, [armed]);
  return (
    <button
      className={className}
      onClick={() => {
        if (armed) { onConfirm(); setArmed(false); }
        else setArmed(true);
      }}
    >
      {armed ? "ยืนยัน?" : children}
    </button>
  );
}

// ---------- Tiny chart (SVG bars) ----------
function MiniBars({ data, color = "#2E86C1", height = 64 }) {
  const max = Math.max(1, ...data.map((d) => d.v));
  const w = 220;
  const bw = w / data.length;
  return (
    <svg viewBox={`0 0 ${w} ${height}`} className="mini-chart">
      {data.map((d, i) => {
        const h = (d.v / max) * (height - 14);
        return (
          <g key={i}>
            <rect x={i * bw + 2} y={height - h - 12} width={bw - 4} height={h} fill={color} rx="2" opacity={0.85} />
            <text x={i * bw + bw / 2} y={height - 2} textAnchor="middle" fontSize="8" fill="#888">{d.l}</text>
          </g>
        );
      })}
    </svg>
  );
}

// ---------- Donut ----------
function Donut({ slices, size = 160, thickness = 22 }) {
  const total = slices.reduce((a, b) => a + b.v, 0) || 1;
  let acc = 0;
  const r = (size - thickness) / 2;
  const c = 2 * Math.PI * r;
  return (
    <svg viewBox={`0 0 ${size} ${size}`} className="donut">
      <g transform={`translate(${size / 2} ${size / 2}) rotate(-90)`}>
        <circle r={r} fill="none" stroke="#eee" strokeWidth={thickness} />
        {slices.map((s, i) => {
          const len = (s.v / total) * c;
          const dash = `${len} ${c - len}`;
          const offset = -acc;
          acc += len;
          return <circle key={i} r={r} fill="none" stroke={s.color} strokeWidth={thickness} strokeDasharray={dash} strokeDashoffset={offset} />;
        })}
      </g>
      <text x={size / 2} y={size / 2 - 2} textAnchor="middle" fontSize="22" fontWeight="700" fill="#111">{fmtNum(total)}</text>
      <text x={size / 2} y={size / 2 + 16} textAnchor="middle" fontSize="10" fill="#888">รายการทั้งหมด</text>
    </svg>
  );
}

// ---------- Input ----------
function Field({ label, children, hint }) {
  return (
    <label className="field">
      <span className="field-label">{label}</span>
      {children}
      {hint && <span className="field-hint">{hint}</span>}
    </label>
  );
}

Object.assign(window, {
  Modal, ToastProvider, useToast, CatBadge, StatCard, Empty, ConfirmBtn, MiniBars, Donut, Field,
});
