/* ============================================================
   UI compartilhada — botões, inputs, modal, badges, tabela,
   gráficos (SVG) e toasts. Exporta tudo para window.
   ============================================================ */
const { useState, useEffect, useRef } = React;

/* ---------- Ícones (stroke simples, sem ilustração) ---------- */
function Icon({ name, size = 20 }) {
  const s = { width: size, height: size, fill: "none", stroke: "currentColor", strokeWidth: 1.8, strokeLinecap: "round", strokeLinejoin: "round" };
  const P = {
    dashboard: <><rect x="3" y="3" width="7" height="9" /><rect x="14" y="3" width="7" height="5" /><rect x="14" y="12" width="7" height="9" /><rect x="3" y="16" width="7" height="5" /></>,
    users: <><circle cx="9" cy="8" r="3.2" /><path d="M3.5 20c.6-3.2 3-5 5.5-5s4.9 1.8 5.5 5" /><path d="M16 4.2a3 3 0 0 1 0 7.6" /><path d="M18 20c-.3-2.2-1.3-3.8-2.7-4.6" /></>,
    cart: <><circle cx="9" cy="20" r="1.4" /><circle cx="17" cy="20" r="1.4" /><path d="M2.5 3h2.2l2 12.5h11l1.8-9H6.2" /></>,
    gift: <><rect x="3.5" y="9" width="17" height="11" rx="1" /><path d="M3.5 13h17M12 9v11" /><path d="M12 9S10.5 4 8 5c-2 .8-1 4 4 4 5 0 6-3.2 4-4-2.5-1-4 4-4 4Z" /></>,
    swap: <><path d="M4 8h13l-3-3M20 16H7l3 3" /></>,
    gear: <><circle cx="12" cy="12" r="3.2" /><path d="M12 2.5v3M12 18.5v3M21.5 12h-3M5.5 12h-3M18.4 5.6l-2.1 2.1M7.7 16.3l-2.1 2.1M18.4 18.4l-2.1-2.1M7.7 7.7 5.6 5.6" /></>,
    user: <><circle cx="12" cy="8" r="3.6" /><path d="M5 20c.8-4 3.8-6 7-6s6.2 2 7 6" /></>,
    plus: <><path d="M12 5v14M5 12h14" /></>,
    search: <><circle cx="11" cy="11" r="6.5" /><path d="m20 20-3.5-3.5" /></>,
    edit: <><path d="M14 5l5 5M4 20l1-4L17 4l3 3L8 19l-4 1Z" /></>,
    trash: <><path d="M4 7h16M9 7V5h6v2M6 7l1 13h10l1-13" /></>,
    close: <><path d="M6 6l12 12M18 6 6 18" /></>,
    check: <><path d="m5 12 4.5 4.5L19 7" /></>,
    print: <><path d="M7 9V3h10v6M7 18H5a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-2M7 14h10v7H7z" /></>,
    chevron: <><path d="m9 6 6 6-6 6" /></>,
    back: <><path d="m15 6-6 6 6 6" /></>,
    coins: <><ellipse cx="9" cy="7" rx="6" ry="3" /><path d="M3 7v5c0 1.7 2.7 3 6 3s6-1.3 6-3V7" /><path d="M9 12v5c0 1.7 2.7 3 6 3s6-1.3 6-3v-5" /><ellipse cx="15" cy="12" rx="6" ry="3" /></>,
    clock: <><circle cx="12" cy="12" r="8.5" /><path d="M12 7.5V12l3 2" /></>,
    alert: <><path d="M12 3 2 20h20L12 3Z" /><path d="M12 10v5M12 17.5v.5" /></>
  };
  return <svg viewBox="0 0 24 24" style={s}>{P[name] || null}</svg>;
}

/* ---------- Botão ---------- */
function Button({ children, variant = "primary", size = "md", icon, onClick, type = "button", disabled, full, title }) {
  const cls = ["btn", "btn-" + variant, "btn-" + size];
  if (full) cls.push("btn-full");
  return (
    <button type={type} className={cls.join(" ")} onClick={onClick} disabled={disabled} title={title}>
      {icon && <Icon name={icon} size={size === "sm" ? 16 : 18} />}
      {children && <span>{children}</span>}
    </button>
  );
}

/* ---------- Campos de formulário ---------- */
function Field({ label, children, hint, required }) {
  return (
    <label className="field">
      <span className="field-label">{label}{required && <em className="req">*</em>}</span>
      {children}
      {hint && <span className="field-hint">{hint}</span>}
    </label>
  );
}
function Input(props) { return <input className="input" {...props} />; }
function Textarea(props) { return <textarea className="input textarea" {...props} />; }
function Select({ children, ...props }) {
  return (
    <div className="select-wrap">
      <select className="input select" {...props}>{children}</select>
      <span className="select-arrow"><Icon name="chevron" size={16} /></span>
    </div>
  );
}

/* ---------- Badges ---------- */
function TierBadge({ tier, size = "md" }) {
  return (
    <span className={"tier tier-" + size} style={{ background: tier.soft, color: tier.color, boxShadow: "inset 0 0 0 1px " + tier.ring }}>
      <span className="tier-dot" style={{ background: tier.color }} />
      {tier.label}
    </span>
  );
}
function StatusPill({ active }) {
  return <span className={"pill " + (active ? "pill-on" : "pill-off")}>{active ? "Ativo" : "Inativo"}</span>;
}

/* ---------- Modal ---------- */
function Modal({ title, subtitle, onClose, children, footer, wide }) {
  useEffect(() => {
    const h = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", h);
    document.body.style.overflow = "hidden";
    return () => { document.removeEventListener("keydown", h); document.body.style.overflow = ""; };
  }, []);
  return (
    <div className="modal-overlay" onMouseDown={onClose}>
      <div className={"modal" + (wide ? " modal-wide" : "")} onMouseDown={(e) => e.stopPropagation()}>
        <header className="modal-head">
          <div>
            <h3>{title}</h3>
            {subtitle && <p>{subtitle}</p>}
          </div>
          <button className="icon-btn" onClick={onClose} aria-label="Fechar"><Icon name="close" /></button>
        </header>
        <div className="modal-body">{children}</div>
        {footer && <footer className="modal-foot">{footer}</footer>}
      </div>
    </div>
  );
}

/* ---------- Toast ---------- */
let toastFn = null;
function ToastHost() {
  const [items, setItems] = useState([]);
  useEffect(() => {
    toastFn = (msg, kind) => {
      const id = Math.random().toString(36).slice(2);
      setItems((x) => [...x, { id, msg, kind: kind || "ok" }]);
      setTimeout(() => setItems((x) => x.filter((i) => i.id !== id)), 3200);
    };
  }, []);
  return (
    <div className="toast-host">
      {items.map((i) => (
        <div key={i.id} className={"toast toast-" + i.kind}>
          <Icon name={i.kind === "err" ? "alert" : "check"} size={18} />
          <span>{i.msg}</span>
        </div>
      ))}
    </div>
  );
}
function toast(msg, kind) { if (toastFn) toastFn(msg, kind); }

/* ---------- Empty state ---------- */
function Empty({ icon, title, hint, action }) {
  return (
    <div className="empty">
      <div className="empty-ic"><Icon name={icon || "search"} size={26} /></div>
      <h4>{title}</h4>
      {hint && <p>{hint}</p>}
      {action}
    </div>
  );
}

/* ---------- Busca ---------- */
function SearchBox({ value, onChange, placeholder }) {
  return (
    <div className="searchbox">
      <Icon name="search" size={18} />
      <input value={value} onChange={(e) => onChange(e.target.value)} placeholder={placeholder || "Buscar..."} />
    </div>
  );
}

/* ---------- Avatar (iniciais) ---------- */
function Avatar({ name, color, size = 38 }) {
  const initials = (name || "?").split(" ").filter(Boolean).slice(0, 2).map((w) => w[0]).join("").toUpperCase();
  return (
    <span className="avatar" style={{ width: size, height: size, background: (color || "#2563eb") + "18", color: color || "#2563eb", fontSize: size * 0.36 }}>
      {initials}
    </span>
  );
}

/* ============================================================
   Gráficos SVG (somente formas básicas a partir de dados)
   ============================================================ */

/* Donut — clientes por categoria */
function DonutChart({ data, size = 168, thickness = 26 }) {
  const total = data.reduce((s, d) => s + d.value, 0) || 1;
  const r = (size - thickness) / 2;
  const c = size / 2;
  const circ = 2 * Math.PI * r;
  let acc = 0;
  return (
    <div className="donut-wrap">
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
        <circle cx={c} cy={c} r={r} fill="none" stroke="#eef1f5" strokeWidth={thickness} />
        {data.map((d, i) => {
          const frac = d.value / total;
          const dash = frac * circ;
          const el = (
            <circle key={i} cx={c} cy={c} r={r} fill="none" stroke={d.color} strokeWidth={thickness}
              strokeDasharray={`${dash} ${circ - dash}`} strokeDashoffset={-acc * circ}
              transform={`rotate(-90 ${c} ${c})`} strokeLinecap="butt" />
          );
          acc += frac;
          return el;
        })}
        <text x={c} y={c - 4} textAnchor="middle" className="donut-num">{DB.formatNum(total)}</text>
        <text x={c} y={c + 15} textAnchor="middle" className="donut-lbl">clientes</text>
      </svg>
      <div className="donut-legend">
        {data.map((d, i) => (
          <div key={i} className="legend-row">
            <span className="legend-dot" style={{ background: d.color }} />
            <span className="legend-lbl">{d.label}</span>
            <span className="legend-val">{DB.formatNum(d.value)}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

/* Barras — pontos gerados por mês */
function BarChart({ data, height = 200, accent = "#2563eb" }) {
  const max = Math.max.apply(null, data.map((d) => d.value).concat([1]));
  const pad = 28;
  const innerH = height - pad;
  const barW = 64 / data.length;
  const gap = (100 - barW * data.length) / (data.length + 1);
  return (
    <svg className="barchart" viewBox={`0 0 100 ${height / 2}`} preserveAspectRatio="none" style={{ width: "100%", height: height }}>
      {[0.25, 0.5, 0.75, 1].map((g, i) => (
        <line key={i} x1="0" x2="100" y1={(innerH / 2) * (1 - g) + 2} y2={(innerH / 2) * (1 - g) + 2} stroke="#eef1f5" strokeWidth="0.4" />
      ))}
      {data.map((d, i) => {
        const h = (d.value / max) * (innerH / 2 - 4);
        const x = gap + i * (barW + gap);
        const y = innerH / 2 - h + 2;
        return (
          <g key={i}>
            <rect x={x} y={y} width={barW} height={Math.max(h, 0.6)} rx="1.2" fill={accent}>
              <title>{d.label}: {DB.formatNum(d.value)} pts</title>
            </rect>
          </g>
        );
      })}
    </svg>
  );
}
function BarLabels({ data }) {
  return (
    <div className="bar-labels">
      {data.map((d, i) => <span key={i}>{d.label}</span>)}
    </div>
  );
}

/* ---------- Progresso de tier ---------- */
function TierProgress({ pontos }) {
  const tiers = DB.TIERS;
  const cat = DB.categoriaFor(pontos);
  let pct = 100, prox = null, falta = 0;
  if (cat.key !== "ouro") {
    const next = tiers[tiers.findIndex((t) => t.key === cat.key) + 1];
    prox = next;
    const span = next.min - cat.min;
    pct = Math.min(100, Math.round(((pontos - cat.min) / span) * 100));
    falta = next.min - pontos;
  }
  return (
    <div className="tierprog">
      <div className="tierprog-bar">
        <div className="tierprog-fill" style={{ width: pct + "%", background: cat.color }} />
      </div>
      <div className="tierprog-meta">
        {prox
          ? <span>Faltam <strong>{DB.formatNum(falta)} pts</strong> para <strong style={{ color: prox.color }}>{prox.label}</strong></span>
          : <span>Categoria máxima atingida 🏆</span>}
      </div>
    </div>
  );
}

Object.assign(window, {
  Icon, Button, Field, Input, Textarea, Select, TierBadge, StatusPill,
  Modal, ToastHost, toast, Empty, SearchBox, Avatar,
  DonutChart, BarChart, BarLabels, TierProgress
});
