// Jennati shared components
const { motion, AnimatePresence, useScroll, useTransform, useMotionValue, useVelocity, useSpring, animate } = window.Motion || window.framerMotion || {};
const M = window.Motion || window.framerMotion;

// Icons via inline SVG so we don't depend on lucide loading
const Icon = ({ name, size = 20, stroke = 1.5, className = "" }) => {
  const paths = {
    search: <><circle cx="11" cy="11" r="7" /><path d="m20 20-3.5-3.5" /></>,
    user: <><circle cx="12" cy="8" r="4" /><path d="M4 21c0-4.4 3.6-8 8-8s8 3.6 8 8" /></>,
    bag: <><path d="M5 7h14l-1.2 12.2A2 2 0 0 1 15.8 21H8.2a2 2 0 0 1-2-1.8L5 7Z" /><path d="M9 7V5a3 3 0 0 1 6 0v2" /></>,
    menu: <><path d="M3 6h18" /><path d="M3 12h18" /><path d="M3 18h18" /></>,
    x: <><path d="m6 6 12 12" /><path d="M6 18 18 6" /></>,
    arrowRight: <><path d="M5 12h14" /><path d="m13 5 7 7-7 7" /></>,
    arrowLeft: <><path d="M19 12H5" /><path d="m12 19-7-7 7-7" /></>,
    arrowDown: <><path d="M12 5v14" /><path d="m19 12-7 7-7-7" /></>,
    chevronLeft: <><path d="m15 18-6-6 6-6" /></>,
    chevronRight: <><path d="m9 18 6-6-6-6" /></>,
    chevronDown: <><path d="m6 9 6 6 6-6" /></>,
    instagram: <><rect x="3" y="3" width="18" height="18" rx="5" /><circle cx="12" cy="12" r="4" /><circle cx="17.5" cy="6.5" r="0.5" fill="currentColor" /></>,
    facebook: <><path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z" /></>,
    tiktok: <><path d="M9 12a4 4 0 1 0 4 4V4c.5 2.5 2.5 4.5 5 5" /></>,
    whatsapp: <><path d="M3 21l1.65-3.8a9 9 0 1 1 3.4 3.45L3 21" /><path d="M9 10a5 5 0 0 0 5 5l1.5-1.5-2.5-1L12 13.5a3 3 0 0 1-1.5-1.5l1-1L10.5 8.5 9 10z" fill="currentColor" /></>,
    star: <path d="m12 3 2.5 5.5 6 .5-4.5 4 1.5 6L12 16l-5.5 3 1.5-6L3.5 9l6-.5L12 3z" fill="currentColor" />,
    heart: <path d="M12 21s-7-4.5-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 11c0 5.5-7 10-7 10z" />,
    plus: <><path d="M12 5v14" /><path d="M5 12h14" /></>,
    minus: <path d="M5 12h14" />,
    play: <path d="M8 5v14l11-7L8 5z" fill="currentColor" />,
    sparkle: <path d="M12 3v6m0 6v6M3 12h6m6 0h6M5.5 5.5l4 4m5 5 4 4m0-13-4 4m-5 5-4 4" />,
  };
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
      {paths[name]}
    </svg>
  );
};

// Magnetic button wrapper
const Magnetic = ({ children, strength = 0.35, className = "" }) => {
  const ref = React.useRef(null);
  const onMove = (e) => {
    const el = ref.current;
    if (!el) return;
    const r = el.getBoundingClientRect();
    const x = e.clientX - (r.left + r.width / 2);
    const y = e.clientY - (r.top + r.height / 2);
    el.style.transform = `translate3d(${x * strength}px, ${y * strength}px, 0)`;
  };
  const onLeave = () => {
    const el = ref.current;
    if (el) el.style.transform = "translate3d(0,0,0)";
  };
  return (
    <span ref={ref} className={`magnetic inline-block ${className}`} onMouseMove={onMove} onMouseLeave={onLeave}>
      {children}
    </span>
  );
};

// Char-by-char H2 reveal
const RevealText = ({ children, className = "", italic = "" }) => {
  const ref = React.useRef(null);
  const [vis, setVis] = React.useState(false);
  React.useEffect(() => {
    const obs = new IntersectionObserver(
      ([e]) => { if (e.isIntersecting) { setVis(true); obs.disconnect(); } },
      { threshold: 0.2 }
    );
    if (ref.current) obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  const text = typeof children === "string" ? children : "";
  const parts = text.split(/(\*[^*]+\*)/g).filter(Boolean);
  let charIdx = 0;
  return (
    <span ref={ref} className={className} aria-label={text.replace(/\*/g, "")}>
      {parts.map((part, i) => {
        const isItalic = part.startsWith("*") && part.endsWith("*");
        const clean = isItalic ? part.slice(1, -1) : part;
        return (
          <span key={i} className={isItalic ? "italic" : ""} style={{ display: "inline" }}>
            {clean.split("").map((ch, j) => {
              const idx = charIdx++;
              return (
                <span
                  key={j}
                  style={{
                    display: "inline-block",
                    opacity: vis ? 1 : 0,
                    transform: vis ? "translateY(0)" : "translateY(22px)",
                    transition: `opacity 600ms cubic-bezier(0.4,0,0.2,1) ${idx * 28}ms, transform 600ms cubic-bezier(0.4,0,0.2,1) ${idx * 28}ms`,
                    whiteSpace: ch === " " ? "pre" : "normal",
                  }}
                >{ch}</span>
              );
            })}
          </span>
        );
      })}
    </span>
  );
};

// Generic in-view fade-up
const FadeUp = ({ children, delay = 0, y = 30, className = "", as: Tag = "div" }) => {
  const ref = React.useRef(null);
  const [vis, setVis] = React.useState(false);
  React.useEffect(() => {
    const obs = new IntersectionObserver(([e]) => { if (e.isIntersecting) { setVis(true); obs.disconnect(); } }, { threshold: 0.15 });
    if (ref.current) obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  return (
    <Tag ref={ref} className={className} style={{
      opacity: vis ? 1 : 0,
      transform: vis ? "translateY(0)" : `translateY(${y}px)`,
      transition: `opacity 800ms cubic-bezier(0.4,0,0.2,1) ${delay}ms, transform 800ms cubic-bezier(0.4,0,0.2,1) ${delay}ms`,
    }}>{children}</Tag>
  );
};

// Image wipe reveal (mosaic)
const WipeImage = ({ src, alt, delay = 0, className = "" }) => {
  const ref = React.useRef(null);
  const [vis, setVis] = React.useState(false);
  React.useEffect(() => {
    const obs = new IntersectionObserver(([e]) => { if (e.isIntersecting) { setVis(true); obs.disconnect(); } }, { threshold: 0.2 });
    if (ref.current) obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  return (
    <div ref={ref} className={`wipe-img ${vis ? "is-in" : ""} ${className}`} style={{ transitionDelay: `${delay}ms` }}>
      <img src={src} alt={alt} className="w-full h-full object-cover" loading="lazy" style={{
        transform: vis ? "scale(1)" : "scale(1.06)",
        transition: `transform 1.4s cubic-bezier(0.4,0,0.2,1) ${delay}ms`
      }} />
    </div>
  );
};

// Animated number counter
const Counter = ({ target, suffix = "", duration = 2000 }) => {
  const ref = React.useRef(null);
  const [val, setVal] = React.useState(0);
  React.useEffect(() => {
    const obs = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) {
        const start = performance.now();
        const tick = (t) => {
          const p = Math.min(1, (t - start) / duration);
          const eased = 1 - Math.pow(1 - p, 3);
          setVal(Math.round(target * eased));
          if (p < 1) requestAnimationFrame(tick);
        };
        requestAnimationFrame(tick);
        obs.disconnect();
      }
    }, { threshold: 0.4 });
    if (ref.current) obs.observe(ref.current);
    return () => obs.disconnect();
  }, [target]);
  return <span ref={ref}>{val}{suffix}</span>;
};

// Custom cursor
const CustomCursor = () => {
  const dotRef = React.useRef(null);
  const ringRef = React.useRef(null);
  React.useEffect(() => {
    if (window.innerWidth < 1024) return;
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    document.body.classList.add("has-custom-cursor");
    let mx = window.innerWidth / 2, my = window.innerHeight / 2;
    let rx = mx, ry = my;
    const onMove = (e) => { mx = e.clientX; my = e.clientY; if (dotRef.current) { dotRef.current.style.left = mx + "px"; dotRef.current.style.top = my + "px"; } };
    let rafId;
    const loop = () => {
      rx += (mx - rx) * 0.18;
      ry += (my - ry) * 0.18;
      if (ringRef.current) { ringRef.current.style.left = rx + "px"; ringRef.current.style.top = ry + "px"; }
      rafId = requestAnimationFrame(loop);
    };
    loop();
    const onOver = (e) => {
      const t = e.target;
      if (!ringRef.current) return;
      ringRef.current.classList.remove("is-link", "is-product");
      ringRef.current.textContent = "";
      if (t.closest("[data-cursor='product']")) {
        ringRef.current.classList.add("is-product");
        ringRef.current.textContent = "VOIR";
      } else if (t.closest("a, button, [role='button'], [data-cursor='link']")) {
        ringRef.current.classList.add("is-link");
      }
    };
    window.addEventListener("mousemove", onMove);
    window.addEventListener("mouseover", onOver);
    return () => {
      cancelAnimationFrame(rafId);
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mouseover", onOver);
      document.body.classList.remove("has-custom-cursor");
    };
  }, []);
  return (
    <>
      <div ref={dotRef} className="cursor-dot hidden lg:block" />
      <div ref={ringRef} className="cursor-ring hidden lg:block" />
    </>
  );
};

// Smooth scroll (Lenis-like) — DESKTOP ONLY (touch devices use native scroll)
const useSmoothScroll = () => {
  React.useEffect(() => {
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    // Skip entirely on touch devices — wheel hijacking breaks iOS scroll
    const isTouch = ("ontouchstart" in window) || (navigator.maxTouchPoints > 0);
    const isNarrow = window.matchMedia("(max-width: 1024px)").matches;
    if (isTouch || isNarrow) return;
    let target = window.scrollY;
    let current = window.scrollY;
    let rafId;
    let active = true;
    const onWheel = (e) => {
      // only intercept if no modifier and not inside a scrollable child
      const t = e.target;
      const scrollable = t && t.closest("[data-no-smooth]");
      if (scrollable) return;
      e.preventDefault();
      target = Math.max(0, Math.min(document.documentElement.scrollHeight - window.innerHeight, target + e.deltaY));
    };
    const loop = () => {
      current += (target - current) * 0.085;
      if (Math.abs(target - current) < 0.5) current = target;
      window.scrollTo(0, current);
      if (active) rafId = requestAnimationFrame(loop);
    };
    target = current = window.scrollY;
    window.addEventListener("wheel", onWheel, { passive: false });
    rafId = requestAnimationFrame(loop);
    return () => {
      active = false;
      cancelAnimationFrame(rafId);
      window.removeEventListener("wheel", onWheel);
    };
  }, []);
};

// Brand wordmark separator
const Bullet = () => (
  <span className="inline-block mx-6 align-middle" aria-hidden="true">
    <svg width="10" height="10" viewBox="0 0 10 10"><path d="M5 0 L6 4 L10 5 L6 6 L5 10 L4 6 L0 5 L4 4 Z" fill="#D4AF7A" /></svg>
  </span>
);

window.JC = { Icon, Magnetic, RevealText, FadeUp, WipeImage, Counter, CustomCursor, useSmoothScroll, Bullet };
