/* ============================================================
   ATOMS — helpers, iconos, placeholder de foto, stepper de cantidad
   ============================================================ */
const { useState, useEffect, useRef, useMemo } = React;

/* ---- formato de precio ---- */
function fmt(n) {
  try { return "$\u2009" + Number(n).toLocaleString("es-CO"); }
  catch (e) { return "$ " + n; }
}
// etiqueta de precio para un item (maneja rangos "desde / hasta")
function priceLabel(it) {
  if (it.to && it.to !== it.from) return fmt(it.from) + " – " + fmt(it.to);
  return fmt(it.from);
}

/* ---- iconos (line) ---- */
function Icon({ d, size = 20, fill = "none", stroke = "currentColor", sw = 1.7, style }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={fill} stroke={stroke}
      strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round" style={style}>
      {Array.isArray(d) ? d.map((p, i) => <path key={i} d={p} />) : <path d={d} />}
    </svg>
  );
}
const I = {
  cart: "M6 6h15l-1.5 9h-12zM6 6 5 3H2M9 20a1 1 0 1 0 0-2 1 1 0 0 0 0 2M18 20a1 1 0 1 0 0-2 1 1 0 0 0 0 2",
  plus: "M12 5v14M5 12h14",
  minus: "M5 12h14",
  close: "M6 6l12 12M18 6 6 18",
  clock: ["M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18", "M12 7v5l3 2"],
  pin: ["M12 21s-7-5.6-7-11a7 7 0 0 1 14 0c0 5.4-7 11-7 11", "M12 11a2 2 0 1 0 0-4 2 2 0 0 0 0 4"],
  arrow: "M5 12h14M13 6l6 6-6 6",
  back: "M19 12H5M11 18l-6-6 6-6",
  check: "M5 12.5 10 17l9-10",
  cal: ["M4 7a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2z", "M4 10h16M8 3v4M16 3v4"],
  users: ["M16 19a4 4 0 0 0-8 0", "M12 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6", "M20 19a3.5 3.5 0 0 0-5-3.2", "M18 11.5a2.5 2.5 0 1 0 0-5"],
  qr: ["M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4z", "M14 14h2v2h-2zM18 14h2v2h-2zM14 18h2v2h-2zM18 18h2v2h-2z"],
  spark: "M12 3l1.8 5.2L19 10l-5.2 1.8L12 17l-1.8-5.2L5 10l5.2-1.8z",
  wave: "M2 12c2.5-3 5-3 7 0s4.5 3 7 0",
  card: ["M3 7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z", "M3 10h18"],
  anchor: ["M12 8a2 2 0 1 0 0-4 2 2 0 0 0 0 4", "M12 8v12", "M5 12a7 7 0 0 0 14 0", "M3 12h3M18 12h3"],
  pdf: ["M7 3h7l5 5v13a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z", "M14 3v5h5"],
  ig: ["M7 2.5h10A4.5 4.5 0 0 1 21.5 7v10a4.5 4.5 0 0 1-4.5 4.5H7A4.5 4.5 0 0 1 2.5 17V7A4.5 4.5 0 0 1 7 2.5z", "M12 8.4a3.6 3.6 0 1 0 0 7.2 3.6 3.6 0 0 0 0-7.2z", "M17.4 6.4h.01"],
  fb: "M15.5 8.5H18V5.5h-2.5A3.5 3.5 0 0 0 12 9v2.5H9.5v3H12v6h3v-6h2.4l.6-3H15V9a.5.5 0 0 1 .5-.5z",
  tt: "M15 3c.4 2 1.7 3.5 3.6 3.9v3.1a7.2 7.2 0 0 1-3.6-1v5.9a5.6 5.6 0 1 1-5.6-5.6c.3 0 .6 0 .9.1v3.1a2.5 2.5 0 1 0 1.7 2.4V3H15z",
};
function Wa({ size = 18 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor">
      <path d="M12 2a10 10 0 0 0-8.6 15l-1.3 4.7 4.8-1.3A10 10 0 1 0 12 2zm0 18a8 8 0 0 1-4.1-1.1l-.3-.2-2.8.8.8-2.7-.2-.3A8 8 0 1 1 12 20zm4.4-6c-.2-.1-1.4-.7-1.6-.8-.2-.1-.4-.1-.5.1l-.7.9c-.1.2-.3.2-.5.1a6.5 6.5 0 0 1-3.2-2.8c-.2-.4.2-.4.6-1.2.1-.2 0-.3 0-.5l-.7-1.7c-.2-.4-.4-.4-.5-.4h-.5a1 1 0 0 0-.7.3c-.3.3-1 1-1 2.4s1 2.8 1.2 3 2 3.1 4.9 4.3c1.8.8 2.5.8 3.4.7.5 0 1.4-.6 1.6-1.1.2-.6.2-1 .1-1.1 0-.1-.2-.2-.4-.3z" />
    </svg>
  );
}

/* ---- placeholder de foto (rayas suaves + etiqueta mono) ---- */
function Placeholder({ label, kind = "foto", className = "", style, img, fit = "contain" }) {
  if (img) {
    if (fit === "cover") return <div className={"ph ph-img " + className} style={style}><img className="ph-img-fg ph-img-cover" src={img} alt={label} /></div>;
    if (fit === "fill") return <div className={"ph ph-img " + className} style={style}><img className="ph-img-bg" src={img} alt="" aria-hidden="true" /><img className="ph-img-rice" src={img} alt={label} /></div>;
    return <div className={"ph ph-img " + className} style={style}><img className="ph-img-bg" src={img} alt="" aria-hidden="true" /><img className="ph-img-fg" src={img} alt={label} /></div>;
  }
  return (
    <div className={"ph " + className} style={style}>
      <span className="ph-tag">{kind} · {label}</span>
      <Icon d={I.wave} size={26} stroke="rgba(255,255,255,.6)" sw={1.4} style={{ position: "absolute", bottom: 12, right: 12 }} />
    </div>
  );
}

/* ---- stepper de cantidad ---- */
function Stepper({ value, onChange, min = 1, max = 20, size = "md" }) {
  return (
    <div className={"stepper " + size}>
      <button type="button" aria-label="Menos" disabled={value <= min}
        onClick={() => onChange(Math.max(min, value - 1))}><Icon d={I.minus} size={16} /></button>
      <span>{value}</span>
      <button type="button" aria-label="Más" disabled={value >= max}
        onClick={() => onChange(Math.min(max, value + 1))}><Icon d={I.plus} size={16} /></button>
    </div>
  );
}

/* ---- saneamiento y validación de campos (seguridad / ciberseguridad) ----
   - Quita caracteres de control y los signos < > (evita inyección de HTML/scripts).
   - Limita la longitud para evitar entradas abusivas.
   - Filtra por tipo: nombre = solo letras; teléfono = solo dígitos y signos. */
function sanitizeBase(str, max = 200) {
  return String(str == null ? "" : str)
    .replace(/[<>]/g, "")                    // evita etiquetas/inyección HTML
    .replace(/[\u0000-\u001F\u007F]/g, "")   // quita caracteres de control
    .slice(0, max);
}
function filterName(str) {
  // solo letras (con tildes y ñ), espacios y los signos . ' - ; sin números ni símbolos
  return sanitizeBase(str, 50)
    .replace(/[^\p{L}\s.'\-]/gu, "")
    .replace(/\s{2,}/g, " ");
}
function filterPhone(str) {
  // solo dígitos y los signos + ( ) - y espacios; sin letras
  return sanitizeBase(str, 20).replace(/[^\d+()\-\s]/g, "");
}
function filterAddress(str) { return sanitizeBase(str, 120); }
function filterNotes(str) { return sanitizeBase(str, 120); }
function digitsOf(str) { return String(str == null ? "" : str).replace(/\D/g, ""); }
function isValidName(str) { const v = filterName(str).trim(); return v.length >= 2 && /\p{L}/u.test(v); }
function isValidPhone(str) { const d = digitsOf(str); return d.length >= 7 && d.length <= 15; }
function haversineKm(lat1, lon1, lat2, lon2) {
  const R = 6371;
  const dLat = (lat2 - lat1) * Math.PI / 180;
  const dLon = (lon2 - lon1) * Math.PI / 180;
  const a = Math.sin(dLat / 2) ** 2 + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLon / 2) ** 2;
  return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}

Object.assign(window, { fmt, priceLabel, Icon, I, Wa, Placeholder, Stepper,
  sanitizeBase, filterName, filterPhone, filterAddress, filterNotes, digitsOf, isValidName, isValidPhone, haversineKm });
