/* ============================================================
   Componentes compartidos + set de íconos (monoline)
   Expone a window: Icon, Badge, StockBadge, Modal, Field,
   Money, MiniBar, Toasts helpers.
   ============================================================ */
const { useState, useEffect, useRef, useCallback } = React;

/* ---------------- Íconos (stroke, estilo monoline) --------------- */
const ICON_PATHS = {
  dashboard: <><rect x="3" y="3" width="7" height="9" rx="1.5"/><rect x="14" y="3" width="7" height="5" rx="1.5"/><rect x="14" y="12" width="7" height="9" rx="1.5"/><rect x="3" y="16" width="7" height="5" rx="1.5"/></>,
  box: <><path d="M21 8l-9-5-9 5v8l9 5 9-5V8z"/><path d="M3.3 7L12 12l8.7-5M12 22V12"/></>,
  stock: <><path d="M3 7h18M3 12h18M3 17h18"/><circle cx="7" cy="7" r="0.5" fill="currentColor"/></>,
  truck: <><path d="M3 6h11v9H3zM14 9h4l3 3v3h-7z"/><circle cx="7" cy="18" r="2"/><circle cx="17" cy="18" r="2"/></>,
  cart: <><circle cx="9" cy="20" r="1.4"/><circle cx="18" cy="20" r="1.4"/><path d="M2 3h3l2.4 12.4a1.5 1.5 0 001.5 1.2h8.6a1.5 1.5 0 001.5-1.2L21 7H6"/></>,
  trending: <><path d="M3 17l6-6 4 4 7-7"/><path d="M17 7h4v4"/></>,
  search: <><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.3-4.3"/></>,
  plus: <><path d="M12 5v14M5 12h14"/></>,
  edit: <><path d="M12 20h9"/><path d="M16.5 3.5a2.1 2.1 0 013 3L7 19l-4 1 1-4z"/></>,
  trash: <><path d="M3 6h18M8 6V4a1 1 0 011-1h6a1 1 0 011 1v2M19 6l-1 14a1 1 0 01-1 1H7a1 1 0 01-1-1L5 6"/></>,
  x: <><path d="M18 6L6 18M6 6l12 12"/></>,
  check: <><path d="M20 6L9 17l-5-5"/></>,
  alert: <><path d="M10.3 3.9L1.8 18a2 2 0 001.7 3h17a2 2 0 001.7-3L14.7 3.9a2 2 0 00-3.4 0z"/><path d="M12 9v4M12 17h.01"/></>,
  arrowUp: <><path d="M12 19V5M5 12l7-7 7 7"/></>,
  arrowDown: <><path d="M12 5v14M5 12l7 7 7-7"/></>,
  package: <><path d="M16.5 9.4 7.5 4.2M21 16V8a2 2 0 00-1-1.7l-7-4a2 2 0 00-2 0l-7 4A2 2 0 003 8v8a2 2 0 001 1.7l7 4a2 2 0 002 0l7-4A2 2 0 0021 16z"/><path d="M3.3 7L12 12l8.7-5M12 22V12"/></>,
  coins: <><ellipse cx="12" cy="6" rx="8" ry="3"/><path d="M4 6v6c0 1.7 3.6 3 8 3s8-1.3 8-3V6M4 12v6c0 1.7 3.6 3 8 3s8-1.3 8-3v-6"/></>,
  wallet: <><path d="M19 7H5a2 2 0 00-2 2v8a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2z"/><path d="M16 13h.01M3 9V7a2 2 0 012-2h11"/></>,
  leaf: <><path d="M11 20A7 7 0 019.8 6.1C15.5 5 17 4.5 19 2c1 2 2 4.2 2 8a7 7 0 01-7 7c-3 0-4-1-4-1"/><path d="M2 21c0-3 2-7 8-9"/></>,
  whatsapp: <><path d="M3 21l1.6-4.5A8 8 0 1112 20a8 8 0 01-4.1-1.1L3 21z"/><path d="M8.5 8.5c0 4 3 7 7 7 .8 0 1.3-.6 1-1.3l-.6-1.2-1.7.5-1.7-1.7.5-1.7-1.2-.6c-.7-.3-1.3.2-1.6 1z" fill="currentColor" stroke="none"/></>,
  phone: <><path d="M22 16.9v3a2 2 0 01-2.2 2 19.8 19.8 0 01-8.6-3 19.5 19.5 0 01-6-6 19.8 19.8 0 01-3-8.6A2 2 0 014.1 2h3a2 2 0 012 1.7c.1 1 .4 1.9.7 2.8a2 2 0 01-.5 2.1L8.1 9.9a16 16 0 006 6l1.3-1.2a2 2 0 012.1-.5c.9.3 1.8.6 2.8.7a2 2 0 011.7 2z"/></>,
  mail: <><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M2 6l10 7 10-7"/></>,
  pin: <><path d="M21 10c0 6-9 12-9 12s-9-6-9-12a9 9 0 1118 0z"/><circle cx="12" cy="10" r="2.5"/></>,
  sliders: <><path d="M4 21v-7M4 10V3M12 21v-9M12 8V3M20 21v-5M20 12V3M1 14h6M9 8h6M17 16h6"/></>,
  bell: <><path d="M18 8a6 6 0 10-12 0c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.7 21a2 2 0 01-3.4 0"/></>,
  refresh: <><path d="M3 12a9 9 0 0115-6.7L21 8M21 3v5h-5M21 12a9 9 0 01-15 6.7L3 16M3 21v-5h5"/></>,
  download: <><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3"/></>,
  filter: <><path d="M22 3H2l8 9.5V19l4 2v-8.5z"/></>,
  paw: <><circle cx="6" cy="11" r="2"/><circle cx="10.5" cy="6.5" r="2"/><circle cx="15.5" cy="6.5" r="2"/><circle cx="18" cy="11" r="2"/><path d="M8 16c0-2.5 1.8-4 4-4s4 1.5 4 4c0 2-1.5 3-4 3s-4-1-4-3z"/></>,
  tag: <><path d="M20.6 13.4L13.4 20.6a2 2 0 01-2.8 0l-7.2-7.2A2 2 0 013 12V4a1 1 0 011-1h8a2 2 0 011.4.6l7.2 7.2a2 2 0 010 2.6z"/><circle cx="7.5" cy="7.5" r="1.2" fill="currentColor"/></>,
  history: <><path d="M3 3v5h5"/><path d="M3.05 13A9 9 0 1012 3a9 9 0 00-8 5"/><path d="M12 7v5l3 2"/></>,
  menu: <><path d="M3 6h18M3 12h18M3 18h18"/></>,
  chevron: <><path d="M9 6l6 6-6 6"/></>,
};

function Icon({ name, size, style, className }) {
  const p = ICON_PATHS[name];
  if (!p) return null;
  return (
    <svg viewBox="0 0 24 24" width={size || 20} height={size || 20} fill="none"
      stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"
      style={style} className={className} aria-hidden="true">{p}</svg>
  );
}

/* ---------------- Badges de estado de stock --------------- */
function StockBadge({ product }) {
  const st = RB.stockState(product);
  return (
    <span className={"badge badge-" + st}>
      <span className="dot"></span>{RB.STATE_LABEL[st]}
    </span>
  );
}

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

/* ---------------- Field --------------- */
function Field({ label, hint, full, children }) {
  return (
    <div className={"field" + (full ? " full" : "")}>
      {label && <label>{label} {hint && <span className="hint">· {hint}</span>}</label>}
      {children}
    </div>
  );
}

/* ---------------- InfoTip: botón "?" que explica un dato al tocarlo --------------- */
function InfoTip({ title, text }) {
  const [open, setOpen] = useState(false);
  return (
    <>
      <button type="button" className="infotip-btn" aria-label="¿Qué significa?"
        title="¿Qué significa?"
        onClick={(e) => { e.stopPropagation(); setOpen(true); }}>?</button>
      {open && (
        <Modal narrow title={title || "¿Qué significa?"} onClose={() => setOpen(false)}
          footer={<button className="btn btn-primary" onClick={() => setOpen(false)}>Entendido</button>}>
          <p style={{ margin: 0, fontSize: 14.5, color: "var(--ink-2)", lineHeight: 1.55 }}>{text}</p>
        </Modal>
      )}
    </>
  );
}

/* ---------------- DetailModal: explicación + desglose de un dato --------------- */
function DetailModal({ title, intro, rows, empty, foot, onClose }) {
  return (
    <Modal title={title} onClose={onClose}
      footer={<button className="btn btn-primary" onClick={onClose}>Cerrar</button>}>
      {intro && <p className="detail-intro">{intro}</p>}
      {(!rows || rows.length === 0)
        ? <div className="detail-empty">{empty || "Todavía no hay datos para mostrar."}</div>
        : <div className="detail-list">
            {rows.map((r, i) => (
              <div className="detail-row" key={i}>
                <span className="dl-name">{r.name}{r.sub && <small className="dl-sub">{r.sub}</small>}</span>
                <span className="dl-val" style={r.color ? { color: r.color } : null}>{r.value}</span>
              </div>
            ))}
          </div>}
      {foot && <div className="detail-foot"><span>{foot.label}</span><span>{foot.value}</span></div>}
    </Modal>
  );
}

/* ---------------- Tarjeta de indicador clickeable (abre su desglose) --------------- */
function StatBox({ tint, icon, label, value, sub, onClick, children }) {
  return (
    <div className={"stat" + (onClick ? " clickable" : "")} onClick={onClick}
      role={onClick ? "button" : undefined} tabIndex={onClick ? 0 : undefined}
      onKeyDown={onClick ? (e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onClick(); } } : undefined}>
      {onClick && <Icon name="chevron" className="stat-more" size={16} />}
      {icon && <div className="stat-ico" style={{ background: tint.bg, color: tint.fg }}><Icon name={icon} /></div>}
      <div className="stat-label">{label}</div>
      {value !== undefined && <div className="stat-value">{value}</div>}
      {sub && <div className="muted" style={{ fontSize: 12.5, marginTop: 4 }}>{sub}</div>}
      {children}
    </div>
  );
}

/* ---------------- Thumb de producto (placeholder ilustrado) --------------- */
const CAT_ICON = {
  Bebederos: "coins", Comederos: "package", Camas: "leaf", Juguetes: "paw",
  Rascadores: "stock", Transportadoras: "box", Accesorios: "tag",
  Higiene: "refresh", Premium: "trending",
};
function ProdThumb({ product }) {
  if (product && product.img) {
    return <div className="prod-thumb has-img"><img src={product.img} alt={product.name} /></div>;
  }
  return (
    <div className="prod-thumb">
      <Icon name={CAT_ICON[product.cat] || "paw"} />
    </div>
  );
}

/* ---------------- Selector de imagen (sube a la nube) --------------- */
function ImagePicker({ value, onChange, shape, label, hint }) {
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");
  const inputRef = useRef(null);

  const pick = async (e) => {
    const file = e.target.files && e.target.files[0];
    e.target.value = "";
    if (!file) return;
    if (!/^image\//.test(file.type)) { setErr("Elegí un archivo de imagen (JPG o PNG)."); return; }
    setErr(""); setBusy(true);
    try {
      const url = await RBCloud.uploadImage(file);
      onChange(url);
    } catch (e2) {
      setErr(e2 && e2.message ? e2.message : "No se pudo subir la imagen.");
    } finally {
      setBusy(false);
    }
  };

  return (
    <div className="field full">
      {label && <label>{label} {hint && <span className="hint">· {hint}</span>}</label>}
      <div className="img-picker">
        <div className={"img-preview " + (shape || "rect") + (value ? " filled" : "")}>
          {busy
            ? <div className="img-spin"></div>
            : value
              ? <img src={value} alt="" />
              : <Icon name="box" size={26} />}
        </div>
        <div className="img-actions">
          <button type="button" className="btn btn-ghost btn-sm" disabled={busy} onClick={() => inputRef.current.click()}>
            <Icon name="download" size={15} />{value ? "Cambiar imagen" : "Subir imagen"}
          </button>
          {value && !busy && (
            <button type="button" className="btn btn-ghost btn-sm danger" onClick={() => onChange("")}>
              <Icon name="trash" size={15} />Quitar
            </button>
          )}
          <div className="img-hint">{busy ? "Subiendo…" : (err || "JPG o PNG · se ajusta sola")}</div>
        </div>
        <input ref={inputRef} type="file" accept="image/*" hidden onChange={pick} />
      </div>
    </div>
  );
}

/* ---------------- Toasts --------------- */
function useToasts() {
  const [toasts, setToasts] = useState([]);
  const push = useCallback((msg) => {
    const id = Math.random().toString(36).slice(2);
    setToasts((t) => [...t, { id, msg }]);
    setTimeout(() => setToasts((t) => t.filter((x) => x.id !== id)), 2600);
  }, []);
  return { toasts, push };
}
function ToastHost({ toasts }) {
  return (
    <div className="toast-wrap">
      {toasts.map((t) => (
        <div className="toast" key={t.id}><Icon name="check" />{t.msg}</div>
      ))}
    </div>
  );
}

Object.assign(window, { Icon, StockBadge, Modal, Field, InfoTip, DetailModal, StatBox, ProdThumb, ImagePicker, useToasts, ToastHost, CAT_ICON });
