/* Shared design primitives: section shells, eyebrows, motion config */

const { motion, useScroll, useTransform, useInView, useSpring, useMotionValue, AnimatePresence } = window.Motion || window.framerMotion || {};

// Expose motion utilities globally so section files can use them too
Object.assign(window, { useScroll, useTransform, useInView, useSpring, useMotionValue });

// Motion intensity comes from window.__tweaks set in app.jsx; default to 60
const motionScale = () => {
  const m = (window.__tweaks?.motion ?? 60) / 100;
  return Math.max(0.05, m);
};

const fadeUp = (delay = 0) => ({
  initial: { opacity: 0, y: 20 * motionScale() },
  whileInView: { opacity: 1, y: 0 },
  viewport: { once: true, margin: '-10% 0px' },
  transition: { duration: 0.7 + 0.1 * motionScale(), delay, ease: [0.2, 0.7, 0.2, 1] },
});

const fadeIn = (delay = 0) => ({
  initial: { opacity: 0 },
  whileInView: { opacity: 1 },
  viewport: { once: true, margin: '-10% 0px' },
  transition: { duration: 0.8, delay, ease: [0.2, 0.7, 0.2, 1] },
});

// Section wrapper — gives consistent padding + max width
const Section = ({ id, label, children, className = '', noPad = false }) => (
  <section id={id} className={`relative ${noPad ? '' : 'py-24 md:py-32'} ${className}`}>
    <div className="mx-auto max-w-[1280px] px-6 md:px-10">{children}</div>
  </section>
);

// Eyebrow label with monospaced index
const Eyebrow = ({ index, children }) => (
  <div className="flex items-center gap-3 font-mono text-[11px] uppercase tracking-[0.18em]" style={{ color: 'var(--fg-dim)' }}>
    {index && (
      <span className="inline-flex items-center justify-center px-1.5 py-0.5 rounded-sm" style={{ background: 'var(--accent-soft)', color: 'var(--accent)' }}>
        {index}
      </span>
    )}
    <span>{children}</span>
  </div>
);

// Section heading
const SectionTitle = ({ children, className = '' }) => (
  <h2 className={`font-display display-tight text-4xl md:text-6xl font-medium tracking-tight ${className}`}>
    {children}
  </h2>
);

// Generic button — three variants
const Btn = ({ as: As = 'a', variant = 'primary', children, className = '', icon, ...props }) => {
  const base = 'inline-flex items-center gap-2 px-5 h-11 rounded-full text-sm font-medium transition-all duration-200 will-change-transform';
  const styles = {
    primary: { background: 'var(--accent)', color: '#fff' },
    secondary: { background: 'transparent', color: 'var(--fg)', border: '1px solid var(--line-strong)' },
    ghost: { background: 'transparent', color: 'var(--fg-muted)' },
  };
  return (
    <As
      className={`${base} hover:-translate-y-0.5 hover:shadow-lg ${className}`}
      style={styles[variant]}
      {...props}
    >
      {children}
      {icon}
    </As>
  );
};

// AnimatedTitle — splits children into per-word reveal spans
const AnimatedTitle = ({ children, className = '', delay = 0 }) => {
  // children can be string, or array of strings/elements; flatten only top-level strings
  const renderNode = (node, i) => {
    if (typeof node === 'string') {
      return node.split(' ').map((word, wi) => (
        <span key={`${i}-${wi}`} className="inline-block overflow-hidden align-baseline" style={{ paddingBottom: '0.08em' }}>
          <motion.span
            className="inline-block"
            initial={{ y: '110%' }}
            whileInView={{ y: 0 }}
            viewport={{ once: true, margin: '-10% 0px' }}
            transition={{ duration: 0.8, delay: delay + wi * 0.06, ease: [0.2, 0.7, 0.2, 1] }}
          >
            {word}{wi < node.split(' ').length - 1 ? '\u00A0' : ''}
          </motion.span>
        </span>
      ));
    }
    return node;
  };
  const arr = React.Children.toArray(children);
  return (
    <h2 className={`font-display display-tight text-4xl md:text-6xl font-medium tracking-tight ${className}`}>
      {arr.map(renderNode)}
    </h2>
  );
};

// Reveal — generic in-view fade/slide for any node
const Reveal = ({ children, delay = 0, y = 24, className = '', as: As = 'div' }) => {
  const M = motion[As] || motion.div;
  return (
    <M
      initial={{ opacity: 0, y: y * motionScale() }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ once: true, margin: '-8% 0px' }}
      transition={{ duration: 0.8, delay, ease: [0.2, 0.7, 0.2, 1] }}
      className={className}
    >
      {children}
    </M>
  );
};

// Parallax — translates Y as element passes through viewport
const Parallax = ({ children, speed = 0.3, className = '' }) => {
  const ref = React.useRef(null);
  const { scrollYProgress } = useScroll({ target: ref, offset: ['start end', 'end start'] });
  const intensity = (window.__tweaks?.motion ?? 60) / 100;
  const y = useTransform(scrollYProgress, [0, 1], [60 * speed * intensity, -60 * speed * intensity]);
  return <motion.div ref={ref} style={{ y }} className={className}>{children}</motion.div>;
};

// MagneticHover — element drifts toward cursor
const Magnetic = ({ children, strength = 0.25, className = '' }) => {
  const ref = React.useRef(null);
  const x = useMotionValue(0);
  const y = useMotionValue(0);
  const sx = useSpring(x, { stiffness: 200, damping: 18 });
  const sy = useSpring(y, { stiffness: 200, damping: 18 });
  const onMove = (e) => {
    if (!ref.current) return;
    const r = ref.current.getBoundingClientRect();
    x.set((e.clientX - r.left - r.width / 2) * strength);
    y.set((e.clientY - r.top - r.height / 2) * strength);
  };
  const onLeave = () => { x.set(0); y.set(0); };
  return (
    <motion.span
      ref={ref}
      onMouseMove={onMove}
      onMouseLeave={onLeave}
      style={{ x: sx, y: sy, display: 'inline-flex' }}
      className={className}
    >
      {children}
    </motion.span>
  );
};

// CountUp — animates a number when it enters view
const CountUp = ({ to = 100, duration = 1.6, suffix = '', prefix = '', className = '' }) => {
  const ref = React.useRef(null);
  const inView = useInView(ref, { once: true, margin: '-10% 0px' });
  const [val, setVal] = React.useState(0);
  React.useEffect(() => {
    if (!inView) return;
    const start = performance.now();
    let raf;
    const tick = (now) => {
      const t = Math.min(1, (now - start) / (duration * 1000));
      const eased = 1 - Math.pow(1 - t, 3);
      setVal(Math.round(to * eased));
      if (t < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [inView, to, duration]);
  return <span ref={ref} className={className}>{prefix}{val.toLocaleString()}{suffix}</span>;
};

// Hairline divider with optional label
const Rule = ({ label, className = '' }) => (
  <div className={`flex items-center gap-4 ${className}`}>
    <div className="h-px flex-1" style={{ background: 'var(--line)' }} />
    {label && (
      <span className="font-mono text-[10px] uppercase tracking-[0.2em]" style={{ color: 'var(--fg-dim)' }}>
        {label}
      </span>
    )}
    {label && <div className="h-px flex-1" style={{ background: 'var(--line)' }} />}
  </div>
);

Object.assign(window, { Section, Eyebrow, SectionTitle, AnimatedTitle, Reveal, Parallax, Magnetic, CountUp, Btn, Rule, fadeUp, fadeIn, motionScale });
