/* ZestPlus — shared primitives
   Reveal, Counter, Pill, Icon, Avatar, AvatarStack, Logo, Container, Section, GradBorder, OrbField
*/

const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* ------------------------------ Reveal -------------------------------- */
/* Lightweight identity wrapper. We avoid CSS transitions on entry because
   they're unreliable in hidden iframes (verifier/screenshots).
   The "motion budget" lives in the floating orbs, parallax, pulse-glow,
   and counters — all of which run unconditionally. */
function Reveal({ children, delay = 0, y = 24, className = "", as: As = "div", once = true }) {
  return <As className={className}>{children}</As>;
}

/* ------------------------------ Counter ------------------------------- */
function Counter({ to, duration = 1800, format, suffix = "", prefix = "", className = "" }) {
  const ref = useRef(null);
  const [val, setVal] = useState(0);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const animate = () => {
      const hidden = document.hidden;
      const start = (typeof performance !== "undefined" ? performance.now() : Date.now());
      // If page is hidden, rAF is throttled — just jump to final value
      if (hidden) { setVal(to); return; }
      const tick = (now) => {
        const t = Math.min(1, (now - start) / duration);
        const eased = 1 - Math.pow(1 - t, 3);
        setVal(to * eased);
        if (t < 1) requestAnimationFrame(tick);
      };
      requestAnimationFrame(tick);
    };
    // sync check
    const r = el.getBoundingClientRect();
    if (r.top < window.innerHeight + 80 && r.bottom > -80) { animate(); return; }
    if (typeof IntersectionObserver === "undefined") { setVal(to); return; }
    const io = new IntersectionObserver(([e]) => {
      if (!e.isIntersecting) return;
      io.disconnect();
      animate();
    }, { threshold: 0.2 });
    io.observe(el);
    const safety = setTimeout(() => { io.disconnect(); animate(); }, 1500);
    return () => { io.disconnect(); clearTimeout(safety); };
  }, [to, duration]);
  const display = format ? format(val) : Math.round(val).toLocaleString();
  return <span ref={ref} className={className}>{prefix}{display}{suffix}</span>;
}

/* ------------------------------ Pill / Chip --------------------------- */
function Pill({ children, accent = false, className = "" }) {
  return <span className={`chip ${accent ? "chip-accent" : ""} ${className}`}>{children}</span>;
}

function Eyebrow({ children, className = "" }) {
  return <div className={`eyebrow ${className}`}>{children}</div>;
}

/* ------------------------------ Icon ---------------------------------- */
/* Minimal hand-tuned SVG set so we don't bring a 200KB icon lib */
const ICONS = {
  arrowRight: "M5 12h14M13 6l6 6-6 6",
  arrowDown:  "M12 5v14M6 13l6 6 6-6",
  arrowUpRight: "M7 17 17 7M9 7h8v8",
  check:      "M5 12l5 5 9-11",
  bolt:       "M13 2 4 14h7l-1 8 9-12h-7l1-8z",
  flame:      "M12 3s4 4 4 9a4 4 0 1 1-8 0c0-2 2-3 2-5 0 0 2 0 2-4zM10 14a2 2 0 1 0 4 0",
  trophy:     "M8 4h8v3a4 4 0 1 1-8 0V4zM5 5h3v2H6a2 2 0 0 1-1-2zM16 7V5h3a2 2 0 0 1-1 2h-2zM9 13h6v3H9zM7 20h10",
  users:      "M16 19a4 4 0 0 0-8 0M12 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM20 19a3 3 0 0 0-5-2.236M18 11.5a2.5 2.5 0 1 0 0-5",
  heart:      "M12 20s-7-4.5-7-10a4 4 0 0 1 7-2.5A4 4 0 0 1 19 10c0 5.5-7 10-7 10z",
  play:       "M6 4l14 8-14 8z",
  pause:      "M7 5h3v14H7zM14 5h3v14h-3z",
  shield:     "M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6l8-3z",
  sparkle:    "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3zM19 14l.7 2.1L22 17l-2.3.9L19 20l-.7-2.1L16 17l2.3-.9L19 14z",
  target:     "M12 21a9 9 0 1 1 0-18 9 9 0 0 1 0 18zM12 16a4 4 0 1 1 0-8 4 4 0 0 1 0 8zM12 13a1 1 0 1 1 0-2 1 1 0 0 1 0 2z",
  badminton:  "M5 19l6-6M12 12l3-3M14 8l-3 3M16 6l4-2-2 4M11 13a3 3 0 1 0 0 6 3 3 0 0 0 0-6z",
  apple:      "M16.5 12.5c0-2 1.5-3 1.5-3-.8-1.3-2-2-3.5-2-1.4 0-2 .8-3 .8s-1.6-.8-3-.8c-2.2 0-4 1.8-4 4.7 0 3.4 2.5 7.3 4.5 7.3 1 0 1.5-.7 2.5-.7s1.5.7 2.5.7c1.7 0 3.5-3 3.5-3-.5-.3-1.5-1.3-1-3zM13 4c.7-.8.8-2 .7-2.5-.6 0-1.5.4-2 1-.5.5-.8 1.4-.7 2 .6 0 1.4-.3 2-.5z",
  play2:      "M5 3l16 9-16 9z",
  globe:      "M12 21a9 9 0 1 1 0-18 9 9 0 0 1 0 18zM3 12h18M12 3c2.5 3 4 6 4 9s-1.5 6-4 9c-2.5-3-4-6-4-9s1.5-6 4-9z",
  ring:       "M12 21a9 9 0 1 1 0-18 9 9 0 0 1 0 18z",
  ring2:      "M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12z",
  chevR:      "M9 6l6 6-6 6",
  chevL:      "M15 6l-6 6 6 6",
  plus:       "M12 5v14M5 12h14",
  minus:      "M5 12h14",
  star:       "M12 3l2.6 5.6 6.1.6-4.6 4.2 1.3 6L12 16.8 6.6 19.4l1.3-6L3.3 9.2l6.1-.6L12 3z",
  calendar:   "M3 7h18M3 7v12h18V7M8 3v4M16 3v4",
  bell:       "M6 16V11a6 6 0 1 1 12 0v5l2 2H4l2-2zM10 21a2 2 0 0 0 4 0",
  search:     "M11 19a8 8 0 1 1 0-16 8 8 0 0 1 0 16zM21 21l-4.3-4.3",
  download:   "M12 4v12M6 12l6 6 6-6M4 20h16",
  mail:       "M3 6h18v12H3zM3 6l9 7 9-7",
  phone:      "M5 4h4l2 5-3 2c1 3 3 5 6 6l2-3 5 2v4a2 2 0 0 1-2 2A17 17 0 0 1 3 6a2 2 0 0 1 2-2z",
  pin:        "M12 21s-7-7-7-12a7 7 0 1 1 14 0c0 5-7 12-7 12zM12 11a2 2 0 1 1 0-4 2 2 0 0 1 0 4z",
  insta:      "M4 4h16v16H4zM12 8a4 4 0 1 1 0 8 4 4 0 0 1 0-8zM17 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z",
  tiktok:     "M14 4v9.5a3.5 3.5 0 1 1-3.5-3.5M14 4c0 2 2 4 5 4",
  x:          "M5 5l14 14M19 5L5 19",
  sun:        "M12 5V3M12 21v-2M5 12H3M21 12h-2M6 6l-1.5-1.5M19.5 19.5 18 18M6 18l-1.5 1.5M19.5 4.5 18 6M12 17a5 5 0 1 0 0-10 5 5 0 0 0 0 10z",
  moon:       "M21 13A9 9 0 1 1 11 3a7 7 0 0 0 10 10z",
  menu:       "M4 7h16M4 12h16M4 17h16",
  close:      "M6 6l12 12M18 6L6 18",
};
function Icon({ name, size = 16, stroke = 1.7, className = "", fill = "none", color = "currentColor" }) {
  const d = ICONS[name]; if (!d) return null;
  return (
    <svg
      width={size} height={size} viewBox="0 0 24 24"
      fill={fill} stroke={color} strokeWidth={stroke}
      strokeLinecap="round" strokeLinejoin="round"
      className={className} aria-hidden="true"
    >
      <path d={d} />
    </svg>
  );
}

/* ------------------------------ Logo ---------------------------------- */
function Logo({ size = 28, withWord = true, className = "" }) {
  return (
    <div className={`inline-flex items-center gap-2 ${className}`}>
      <img src="images/ic_launcher.png" width={size} height={size} alt="" aria-hidden="true"
        style={{ borderRadius: Math.round(size * 0.26), display: "block" }} />
      {withWord && <span className="font-display font-semibold tracking-tight text-[18px] leading-none">Zest<span className="text-gradient-lime">+</span></span>}
    </div>
  );
}

/* ------------------------------ Container/Section --------------------- */
function Container({ children, className = "" }) {
  return <div className={`mx-auto w-full max-w-[1280px] px-6 md:px-10 ${className}`}>{children}</div>;
}
function Section({ id, children, className = "", padded = true }) {
  return (
    <section id={id} className={`relative overflow-x-clip ${padded ? "py-24 md:py-32" : ""} ${className}`}>
      {children}
    </section>
  );
}

/* ------------------------------ Avatar -------------------------------- */
const AVATAR_PALETTE = [
  ["#c7ff3d","#7fb800"], // lime
  ["#34d399","#0d9488"], // emerald
  ["#f59e0b","#b45309"], // amber
  ["#ef4444","#9f1239"], // rose
  ["#60a5fa","#1d4ed8"], // blue
  ["#a78bfa","#6d28d9"], // violet
  ["#f472b6","#9d174d"], // pink
  ["#fbbf24","#92400e"], // gold
];
function avatarColors(seed){
  let h=0; for(let i=0;i<seed.length;i++) h=(h*31+seed.charCodeAt(i))|0;
  return AVATAR_PALETTE[Math.abs(h)%AVATAR_PALETTE.length];
}
function Avatar({ name = "?", size = 36, ring = false, className = "" }) {
  const [c1,c2] = avatarColors(name);
  const initials = name.split(" ").map(s=>s[0]).slice(0,2).join("").toUpperCase();
  return (
    <div
      className={`inline-flex items-center justify-center rounded-full font-display font-semibold text-[#0a0a0b] ${ring?"ring-2 ring-[var(--bg)]":""} ${className}`}
      style={{
        width:size, height:size,
        fontSize: Math.round(size*0.42),
        background:`linear-gradient(135deg, ${c1}, ${c2})`,
        boxShadow:`inset 0 1px 0 rgba(255,255,255,0.25), 0 1px 2px rgba(0,0,0,0.25)`
      }}
      aria-label={name}
    >
      {initials}
    </div>
  );
}
function AvatarStack({ names = [], size = 32, max = 4, overlap = 10, extra = null }) {
  const shown = names.slice(0, max);
  const remainder = (extra ?? (names.length - max));
  return (
    <div className="flex items-center">
      {shown.map((n,i)=>(
        <div key={n+i} style={{marginLeft: i===0?0:-overlap, zIndex:max-i}}>
          <Avatar name={n} size={size} ring />
        </div>
      ))}
      {remainder>0 && (
        <div style={{marginLeft:-overlap, zIndex:0}}
          className="inline-flex items-center justify-center rounded-full text-[11px] font-semibold ring-2 ring-[var(--bg)]"
          style={{width:size, height:size, background:"var(--bg-card-2)", color:"var(--fg-2)", marginLeft:-overlap}}>
          +{remainder}
        </div>
      )}
    </div>
  );
}

/* ---------------------------- Live dot --------------------------------- */
function LiveDot({ size = 8, label = "LIVE" }) {
  return (
    <span className="inline-flex items-center gap-1.5 text-[10px] font-medium tracking-[0.18em] uppercase" style={{color:"var(--fg-3)"}}>
      <span className="relative inline-flex" style={{width:size,height:size}}>
        <span className="absolute inset-0 rounded-full animate-pulse-glow" style={{background:"#ef4444",opacity:.7}}></span>
        <span className="absolute inset-[2px] rounded-full" style={{background:"#ef4444"}}></span>
      </span>
      {label}
    </span>
  );
}

/* ---------------------------- Floating orbs --------------------------- */
function OrbField({ orbs = [], className = "" }) {
  return (
    <div className={`absolute inset-0 pointer-events-none overflow-hidden ${className}`} aria-hidden="true">
      {orbs.map((o,i)=>(
        <div key={i}
          className={`absolute rounded-full ${o.anim || "animate-float-slow"}`}
          style={{
            left:o.left, top:o.top, right:o.right, bottom:o.bottom,
            width:o.size, height:o.size,
            background:o.bg || "radial-gradient(closest-side, var(--accent-glow), transparent 70%)",
            filter:`blur(${o.blur||40}px)`,
            opacity:o.opacity ?? .6,
            animationDelay:`${o.delay||0}s`,
          }}
        />
      ))}
    </div>
  );
}

/* ---------------------------- Tiny utils ------------------------------ */
function Divider({ className = "" }) {
  return <div className={`h-px w-full ${className}`} style={{background:"var(--line)"}}/>;
}
function Dot({ size = 4, className = "" }) {
  return <span className={`inline-block rounded-full ${className}`} style={{width:size,height:size,background:"var(--fg-3)"}}/>;
}

/* ---------------------------- Mini activity bar chart ----------------- */
function MiniBars({ values = [3,5,4,7,6,9,8], height = 36, color = "var(--accent)", track = "var(--line-strong)" }) {
  const max = Math.max(...values);
  return (
    <div className="flex items-end gap-1" style={{height}}>
      {values.map((v,i)=>{
        const h = (v/max)*height;
        return <div key={i} style={{height:h, width:6, background:i===values.length-1?color:track, borderRadius:2, opacity:i===values.length-1?1:.55}}/>;
      })}
    </div>
  );
}

/* ---------------------------- Theme helper ---------------------------- */
function useTheme() {
  const [theme, setTheme] = useState(document.documentElement.getAttribute("data-theme") || "dark");
  const set = useCallback((t) => {
    document.documentElement.setAttribute("data-theme", t);
    setTheme(t);
  }, []);
  return [theme, set];
}

/* ---------------------------- Mouse parallax -------------------------- */
/* hook returning { x, y } from -1..1 based on pointer position in element */
function useMouseParallax(ref, strength = 12) {
  const [xy, setXY] = useState({x:0,y:0});
  useEffect(()=>{
    const el = ref.current; if (!el) return;
    let raf=0;
    const onMove = (e)=>{
      const r = el.getBoundingClientRect();
      const x = ((e.clientX - r.left)/r.width - 0.5)*2;
      const y = ((e.clientY - r.top )/r.height - 0.5)*2;
      cancelAnimationFrame(raf);
      raf = requestAnimationFrame(()=>setXY({x:x*strength, y:y*strength}));
    };
    const onLeave = ()=>setXY({x:0,y:0});
    el.addEventListener("mousemove", onMove);
    el.addEventListener("mouseleave", onLeave);
    return ()=>{ el.removeEventListener("mousemove", onMove); el.removeEventListener("mouseleave", onLeave); cancelAnimationFrame(raf); };
  },[ref, strength]);
  return xy;
}

/* ---------------------------- Export to globals ----------------------- */
Object.assign(window, {
  Reveal, Counter, Pill, Eyebrow, Icon, Logo,
  Container, Section, Avatar, AvatarStack, LiveDot,
  OrbField, Divider, Dot, MiniBars,
  useTheme, useMouseParallax, avatarColors, ICONS
});
