// Shared utilities + small components

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

// Tweaks context for animation intensity + accent hue + hero variant
const TweakCtx = React.createContext({
  animIntensity: 30,
  accentHue: 16,
  heroVariant: 'transformation',
});

// Hue rotation: derive accent oklch from hue tweak. Range tight around burnt orange.
function accentFromHue(h) {
  // h in 0..40 maps to ~5..50 deg of hue around burnt orange family
  const deg = 18 + (h - 16) * 1.2; // tight range
  // Build oklch -> rgb via CSS variables in document
  return `oklch(0.68 0.14 ${deg})`;
}

// IntersectionObserver-based reveal
function useReveal(threshold = 0.15) {
  const ref = useRef(null);
  const [seen, setSeen] = useState(false);
  useEffect(() => {
    if (!ref.current) return;
    const io = new IntersectionObserver(
      ([e]) => { if (e.isIntersecting) { setSeen(true); io.disconnect(); } },
      { threshold }
    );
    io.observe(ref.current);
    return () => io.disconnect();
  }, [threshold]);
  return [ref, seen];
}

// Reveal wrapper
function Reveal({ children, delay = 0, as: As = 'div', style, className, ...rest }) {
  const [ref, seen] = useReveal(0.12);
  return (
    <As
      ref={ref}
      className={(className || '') + ' reveal' + (seen ? ' in' : '')}
      style={{ transitionDelay: `${delay}ms`, ...style }}
      {...rest}
    >
      {children}
    </As>
  );
}

// Section marker: /01 — KICKER
function SectionMark({ num, label, accent = 'var(--accent)' }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 14,
      fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.18em',
      color: 'var(--ink-mute)', textTransform: 'uppercase'
    }}>
      <span style={{ color: accent, fontWeight: 500 }}>/{num}</span>
      <span style={{ width: 28, height: 1, background: 'currentColor', opacity: 0.3 }} />
      <span>{label}</span>
    </div>
  );
}

// Pulse dot
function PulseDot({ size = 6, color = 'var(--accent)' }) {
  return (
    <span style={{
      display: 'inline-block', width: size, height: size, borderRadius: '50%',
      background: color, animation: 'pulse-dot 2s ease-in-out infinite',
      boxShadow: `0 0 12px ${color}`,
    }} />
  );
}

// Hairline rule
function Rule({ color = 'var(--hair-dk)', vertical = false, length, style }) {
  return (
    <div style={{
      background: color,
      width: vertical ? 1 : (length || '100%'),
      height: vertical ? (length || '100%') : 1,
      ...style
    }} />
  );
}

// Ambient grid — quiet breathing dot field. Animation amplitude scaled by intensity.
function AmbientGrid({ density = 28, dark = true }) {
  const canvasRef = useRef(null);
  const { animIntensity } = useContext(TweakCtx);
  const t0 = useRef(performance.now());
  const mouse = useRef({ x: -9999, y: -9999 });
  const smooth = useRef({ x: -9999, y: -9999 });
  const raf = useRef(0);

  useEffect(() => {
    const c = canvasRef.current;
    if (!c) return;
    const ctx = c.getContext('2d');

    const resize = () => {
      const dpr = window.devicePixelRatio || 1;
      const r = c.getBoundingClientRect();
      c.width = r.width * dpr;
      c.height = r.height * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    };

    const onMove = (e) => {
      const r = c.getBoundingClientRect();
      mouse.current = { x: e.clientX - r.left, y: e.clientY - r.top };
    };
    const onLeave = () => { mouse.current = { x: -9999, y: -9999 }; };

    const draw = () => {
      const r = c.getBoundingClientRect();
      const w = r.width, h = r.height;
      ctx.clearRect(0, 0, w, h);

      smooth.current.x += (mouse.current.x - smooth.current.x) * 0.08;
      smooth.current.y += (mouse.current.y - smooth.current.y) * 0.08;

      const t = (performance.now() - t0.current) / 1000;
      const ampGlobal = (animIntensity / 100); // 0..1
      const breathe = 0.5 + 0.5 * Math.sin(t * 0.4) * ampGlobal;

      const baseA = dark ? 0.05 : 0.06;
      const hiA = 0.35;
      const baseRGB = dark ? [238, 240, 248] : [26, 23, 20];
      const hiRGB = [232, 112, 90];
      const infl = 110;

      for (let x = density / 2; x < w; x += density) {
        for (let y = density / 2; y < h; y += density) {
          const dx = x - smooth.current.x;
          const dy = y - smooth.current.y;
          const d = Math.hypot(dx, dy);
          let i = 0;
          if (d < infl) {
            const tt = 1 - d / infl;
            i = tt * tt * (3 - 2 * tt);
          }
          // gentle wave for ambient breathe
          const wave = Math.sin((x + y) * 0.012 + t * 0.6) * 0.5 + 0.5;
          const ambientI = wave * breathe * 0.18 * ampGlobal;
          const totalI = Math.min(1, i + ambientI * 0.4);

          const rr = Math.round(baseRGB[0] + (hiRGB[0] - baseRGB[0]) * totalI);
          const gg = Math.round(baseRGB[1] + (hiRGB[1] - baseRGB[1]) * totalI);
          const bb = Math.round(baseRGB[2] + (hiRGB[2] - baseRGB[2]) * totalI);
          const aa = baseA + (hiA - baseA) * totalI;
          const rad = 0.7 + totalI * 1.6;

          ctx.beginPath();
          ctx.arc(x, y, rad, 0, Math.PI * 2);
          ctx.fillStyle = `rgba(${rr},${gg},${bb},${aa})`;
          ctx.fill();
        }
      }
      raf.current = requestAnimationFrame(draw);
    };

    resize();
    window.addEventListener('resize', resize);
    window.addEventListener('mousemove', onMove);
    c.addEventListener('mouseleave', onLeave);
    raf.current = requestAnimationFrame(draw);
    return () => {
      window.removeEventListener('resize', resize);
      window.removeEventListener('mousemove', onMove);
      c.removeEventListener('mouseleave', onLeave);
      cancelAnimationFrame(raf.current);
    };
  }, [animIntensity, density, dark]);

  return (
    <canvas
      ref={canvasRef}
      style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', pointerEvents: 'none' }}
    />
  );
}

// Counter that animates up
function Counter({ value, duration = 1200, prefix = '', suffix = '' }) {
  const [v, setV] = useState(0);
  const [ref, seen] = useReveal(0.4);
  useEffect(() => {
    if (!seen) return;
    const start = performance.now();
    let raf;
    const step = (now) => {
      const t = Math.min(1, (now - start) / duration);
      const eased = 1 - Math.pow(1 - t, 3);
      setV(Math.round(value * eased));
      if (t < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [seen, value, duration]);
  return <span ref={ref}>{prefix}{v.toLocaleString('en-IN')}{suffix}</span>;
}

// Small button
function PrimaryBtn({ children, onClick, style, ...rest }) {
  return (
    <button
      onClick={onClick}
      style={{
        padding: '14px 24px',
        background: 'var(--accent)',
        color: 'white',
        borderRadius: 10,
        fontWeight: 500,
        fontSize: 15,
        letterSpacing: '0.005em',
        boxShadow: '0 8px 32px rgba(232, 112, 90, 0.32), inset 0 1px 0 rgba(255,255,255,0.18)',
        transition: 'all 0.3s cubic-bezier(.2,.7,.2,1)',
        ...style
      }}
      onMouseEnter={(e) => { e.currentTarget.style.transform = 'translateY(-2px)'; e.currentTarget.style.boxShadow = '0 12px 40px rgba(232, 112, 90, 0.5), inset 0 1px 0 rgba(255,255,255,0.18)'; }}
      onMouseLeave={(e) => { e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.boxShadow = '0 8px 32px rgba(232, 112, 90, 0.32), inset 0 1px 0 rgba(255,255,255,0.18)'; }}
      {...rest}
    >
      {children}
    </button>
  );
}

function GhostBtn({ children, onClick, style, ...rest }) {
  return (
    <button
      onClick={onClick}
      style={{
        padding: '14px 24px',
        background: 'transparent',
        color: 'var(--ink)',
        border: '1px solid var(--hair-dk-strong)',
        borderRadius: 10,
        fontWeight: 400,
        fontSize: 15,
        transition: 'all 0.3s',
        ...style
      }}
      onMouseEnter={(e) => { e.currentTarget.style.borderColor = 'var(--accent)'; e.currentTarget.style.color = 'var(--accent)'; }}
      onMouseLeave={(e) => { e.currentTarget.style.borderColor = 'var(--hair-dk-strong)'; e.currentTarget.style.color = 'var(--ink)'; }}
      {...rest}
    >
      {children}
    </button>
  );
}

Object.assign(window, {
  TweakCtx, accentFromHue, useReveal, Reveal,
  SectionMark, PulseDot, Rule, AmbientGrid,
  Counter, PrimaryBtn, GhostBtn
});
