/* ============================================================
   PRESTIGE BIMMER — Shared lib (helpers, hooks, icons)
   ============================================================ */
const { useState, useEffect, useRef, useCallback } = React;

/* ---------- formatters ---------- */
const fmtPrice = (n) => "$" + Number(n || 0).toLocaleString("en-US");
const fmtMiles = (n) => Number(n || 0).toLocaleString("en-US");

/* ---------- icons (stroke, 24 viewbox) ---------- */
const ICON = {
  arrow:  "M5 12h14M13 6l6 6-6 6",
  arrowUR:"M7 17 17 7M7 7h10v10",
  chevR:  "M9 6l6 6-6 6",
  chevL:  "M15 6l-6 6 6 6",
  chevD:  "M6 9l6 6 6-6",
  gauge:  "M12 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4ZM12 14l4-4M3.5 18a9 9 0 1 1 17 0",
  bolt:   "M13 2 4 14h7l-1 8 9-12h-7l1-8Z",
  road:   "M4 21 8 3M20 21 16 3M12 6v2M12 12v2M12 18v2",
  cog:    "M12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6ZM19.4 13a1.7 1.7 0 0 0 .3 1.9l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.9-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.9.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.9 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1.1 1.7 1.7 0 0 0-.3-1.9l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.9.3H10a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.9-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.9V10a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1Z",
  fuel:   "M3 22V5a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v17M3 11h10M16 7l3 3v8a2 2 0 0 1-4 0V5",
  seat:   "M5 20v-2a4 4 0 0 1 4-4h2M19 20v-6M9 4h6a2 2 0 0 1 2 2v6H7V6a2 2 0 0 1 2-2Z",
  shield: "M12 3 4 6v6c0 5 3.5 8 8 9 4.5-1 8-4 8-9V6l-8-3Z",
  check:  "M20 6 9 17l-5-5",
  star:   "M12 3l2.7 5.5 6 .9-4.3 4.2 1 6-5.4-2.8L6.6 19.6l1-6L3.3 9.4l6-.9L12 3Z",
  lock:   "M5 11h14v9H5zM8 11V8a4 4 0 0 1 8 0v3",
  phone:  "M5 4h4l2 5-3 2a12 12 0 0 0 5 5l2-3 5 2v4a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2Z",
  pin:    "M12 21s7-5.5 7-11a7 7 0 1 0-14 0c0 5.5 7 11 7 11ZM12 12a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Z",
  mail:   "M3 6h18v12H3zM3 7l9 6 9-6",
  clock:  "M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18ZM12 8v4l3 2",
  plus:   "M12 5v14M5 12h14",
  edit:   "M4 20h4L18 10l-4-4L4 16v4ZM14 6l4 4",
  trash:  "M4 7h16M9 7V5a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2M6 7l1 13h10l1-13",
  search: "M11 18a7 7 0 1 0 0-14 7 7 0 0 0 0 14ZM21 21l-4.3-4.3",
  filter: "M3 5h18M7 12h10M11 19h2",
  logout: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9",
  user:   "M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8ZM5 21a7 7 0 0 1 14 0",
  heart:  "M12 21s-7-4.5-9.5-9A5 5 0 0 1 12 6a5 5 0 0 1 9.5 6c-2.5 4.5-9.5 9-9.5 9Z",
  spark:  "M12 3v4M12 17v4M3 12h4M17 12h4M6 6l2.5 2.5M15.5 15.5 18 18M18 6l-2.5 2.5M8.5 15.5 6 18",
  x:      "M6 6l12 12M18 6 6 18",
  menu:   "M3 6h18M3 12h18M3 18h18",
  cal:    "M3 5h18v16H3zM3 9h18M8 3v4M16 3v4",
};

function Icon({ name, size = 20, stroke = 1.7, fill = false, style }) {
  const d = ICON[name];
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={fill ? "currentColor" : "none"}
      stroke={fill ? "none" : "currentColor"} strokeWidth={stroke}
      strokeLinecap="round" strokeLinejoin="round" style={style} aria-hidden="true">
      <path d={d} />
    </svg>
  );
}

/* ---------- image placeholder (or real image once provided) ---------- */
function Photo({ label, src, className = "", style, ratio }) {
  const cls = "ph " + (src ? "has-img " : "") + className;
  const st = ratio ? { aspectRatio: ratio, ...style } : style;
  return (
    <div className={cls} data-label={label} style={st}>
      {src ? <img src={src} alt={label} /> : null}
    </div>
  );
}

/* ---------- scroll reveal observer (auto-attaches to [data-reveal]) ---------- */
function useRevealObserver(dep) {
  useEffect(() => {
    const els = document.querySelectorAll("[data-reveal]:not(.in)");
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); }
      });
    }, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" });
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, [dep]);
}

/* ---------- animated number counter ---------- */
function useCountUp(target, run, dur = 1600) {
  const [val, setVal] = useState(0);
  const started = useRef(false);
  useEffect(() => {
    if (!run || started.current) return;
    started.current = true;
    const t0 = performance.now();
    const tick = (t) => {
      const p = Math.min(1, (t - t0) / dur);
      const e = 1 - Math.pow(1 - p, 3);
      setVal(target * e);
      if (p < 1) requestAnimationFrame(tick);
      else setVal(target);
    };
    requestAnimationFrame(tick);
  }, [run, target, dur]);
  return val;
}

/* ---------- live inventory hook (Firestore-backed via PB.Store cache) ---------- */
function useInventory() {
  const [list, setList] = useState(() => PB.Store.all());
  useEffect(() => {
    const h = () => setList(PB.Store.all());
    window.addEventListener("pb:inventory", h);
    h(); // sync immediately in case the first snapshot already arrived
    return () => window.removeEventListener("pb:inventory", h);
  }, []);
  return list;
}

/* ---------- hash router ---------- */
function useRoute() {
  const parse = () => {
    const h = (location.hash || "#/").replace(/^#/, "");
    const parts = h.split("/").filter(Boolean);
    return { name: parts[0] || "home", id: parts[1] || null, raw: h };
  };
  const [route, setRoute] = useState(parse);
  useEffect(() => {
    const h = () => { setRoute(parse()); window.scrollTo({ top: 0, behavior: "instant" }); };
    window.addEventListener("hashchange", h);
    return () => window.removeEventListener("hashchange", h);
  }, []);
  return route;
}
const go = (path) => { location.hash = path; };

Object.assign(window, {
  fmtPrice, fmtMiles, Icon, ICON, Photo,
  useRevealObserver, useCountUp, useInventory, useRoute, go,
});
