// Shared atoms: Placeholder image, icons, Reveal wrapper, nav link factory.
// Each component is lightweight — no external deps beyond React.

const Ph = ({ label, variant = "", className = "", style, src, alt, position = "center" }) => (
  <div className={`ph ${variant} ${src ? "ph-has-img" : ""} ${className}`} style={style}>
    {src && <img className="ph-img" src={src} alt={alt || label} loading="lazy" style={{ objectPosition: position }} />}
    {label && !src && <div className="ph-label">{label}</div>}
  </div>
);

const Icon = ({ name, size = 16 }) => {
  const s = { width: size, height: size, display: "inline-block", verticalAlign: "middle" };
  const p = { fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round" };
  switch (name) {
    case "phone":
      return <svg style={s} viewBox="0 0 24 24"><path {...p} d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>;
    case "arrow":
      return <svg style={s} viewBox="0 0 24 24"><path {...p} d="M5 12h14M13 5l7 7-7 7"/></svg>;
    case "clock":
      return <svg style={s} viewBox="0 0 24 24"><circle {...p} cx="12" cy="12" r="10"/><path {...p} d="M12 6v6l4 2"/></svg>;
    case "pin":
      return <svg style={s} viewBox="0 0 24 24"><path {...p} d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle {...p} cx="12" cy="10" r="3"/></svg>;
    case "mail":
      return <svg style={s} viewBox="0 0 24 24"><path {...p} d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><path {...p} d="M22 6l-10 7L2 6"/></svg>;
    case "star":
      return <svg style={{ ...s, fill: "currentColor" }} viewBox="0 0 24 24"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>;
    case "leaf":
      return <svg style={s} viewBox="0 0 24 24"><path {...p} d="M11 20A7 7 0 0 1 4 13V6h7a7 7 0 0 1 7 7v7zM4 6l16 16"/></svg>;
    case "x":
      return <svg style={s} viewBox="0 0 24 24"><path {...p} d="M18 6L6 18M6 6l12 12"/></svg>;
    case "award":
      return <svg style={s} viewBox="0 0 24 24"><circle {...p} cx="12" cy="8" r="6"/><path {...p} d="M15.477 12.89L17 22l-5-3-5 3 1.523-9.11"/></svg>;
    case "utensils":
      return <svg style={s} viewBox="0 0 24 24"><path {...p} d="M3 2v7c0 1.1.9 2 2 2h1v11M7 2v6M11 2v6M18 2c-1.5 2-2 4-2 6.5 0 2 .8 3 2 3.5v10"/></svg>;
    case "wine":
      return <svg style={s} viewBox="0 0 24 24"><path {...p} d="M8 22h8M12 15v7M7 3h10l-.7 6.2A4.4 4.4 0 0 1 12 13a4.4 4.4 0 0 1-4.3-3.8z"/></svg>;
    case "chat":
      return <svg style={s} viewBox="0 0 24 24"><path {...p} d="M21 11.5a8.4 8.4 0 0 1-9 8.4 9 9 0 0 1-3.8-.8L3 21l1.9-4.6A8.3 8.3 0 0 1 4 11.5 8.4 8.4 0 0 1 12.5 3 8.4 8.4 0 0 1 21 11.5z"/></svg>;
    default: return null;
  }
};

// Apparition au défilement — IntersectionObserver ajoute la classe 'in'.
// Les blocs démarrent à opacity:0 : si l'observateur ne se déclenche jamais, le
// contenu resterait invisible. Deux filets de sécurité ci-dessous.
const Reveal = ({ children, delay = 0, as: Tag = "div", className = "", ...rest }) => {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    const show = () => el.classList.add("in");

    // 1. Navigateur sans IntersectionObserver → on affiche tout de suite.
    if (typeof IntersectionObserver === "undefined") { show(); return; }

    const io = new IntersectionObserver(
      (entries) => entries.forEach(e => e.isIntersecting && show()),
      { threshold: 0.15, rootMargin: "0px 0px -60px 0px" }
    );
    io.observe(el);

    // 2. Déjà visible au chargement (haut de page, grand écran) → on n'attend pas
    //    le premier callback, qui peut tarder d'une frame ou deux.
    const r = el.getBoundingClientRect();
    if (r.top < (window.innerHeight || 0) && r.bottom > 0) show();

    return () => io.disconnect();
  }, []);
  const delayClass = delay ? ` reveal-delay-${delay}` : "";
  return <Tag ref={ref} className={`reveal${delayClass} ${className}`} {...rest}>{children}</Tag>;
};

// Parallax — translateY based on scroll relative to element top
const Parallax = ({ children, speed = 0.15, className = "" }) => {
  const ref = React.useRef(null);
  const innerRef = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current, inner = innerRef.current; if (!el || !inner) return;
    let raf = 0;
    const onScroll = () => {
      if (raf) return;
      raf = requestAnimationFrame(() => {
        raf = 0;
        const r = el.getBoundingClientRect();
        const vh = window.innerHeight;
        const progress = (r.top + r.height/2 - vh/2) / vh; // -1..1 ish
        inner.style.transform = `translate3d(0, ${progress * speed * 100}px, 0)`;
      });
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    return () => { window.removeEventListener("scroll", onScroll); window.removeEventListener("resize", onScroll); };
  }, [speed]);
  return (
    <div ref={ref} className={className} style={{ overflow: "hidden" }}>
      <div ref={innerRef} className="parallax-inner" style={{ width: "100%", height: "100%", willChange: "transform" }}>
        {children}
      </div>
    </div>
  );
};

Object.assign(window, { Ph, Icon, Reveal, Parallax });
