// nda-effects.jsx — ScrollVideoBackground · PillNav · HeroFloat · SlidePanel
const { useState, useEffect, useRef } = React;

// Register GSAP plugins at module scope — GSAP loads before Babel scripts
if (window.gsap) {
  if (window.ScrollTrigger)  window.gsap.registerPlugin(window.ScrollTrigger);
  if (window.ScrollToPlugin) window.gsap.registerPlugin(window.ScrollToPlugin);
}

/* ── Aurora canvas ─────────────────────────────────────────────────── */
function ScrollVideoBackground() {
  const canvasRef = useRef(null);
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let prog = 0, needsDraw = true, raf;

    const resize = () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; needsDraw = true; };

    const draw = (t) => {
      const { width: w, height: h } = canvas;
      ctx.fillStyle = '#111018'; ctx.fillRect(0, 0, w, h);

      const blobs = [
        { x: (.64 + Math.sin(t * 6.28) * .17) * w, y: (.28 + Math.cos(t * 3.14) * .09) * h, r: .46 * w, a: .13, c: '214,168,183' },
        { x: (.22 + Math.cos(t * 5.4)  * .12) * w, y: (.62 + Math.sin(t * 6.28) * .13) * h, r: .34 * w, a: .07, c: '190,184,190' },
        { x: (.82 + Math.sin(t * 9.42 + 1) * .06) * w, y: (.74 - t * .12) * h, r: .28 * w, a: .05, c: '217,217,215' },
      ];
      ctx.save(); ctx.globalCompositeOperation = 'screen';
      blobs.forEach(b => {
        const g = ctx.createRadialGradient(b.x, b.y, 0, b.x, b.y, b.r);
        g.addColorStop(0,    `rgba(${b.c},${b.a})`);
        g.addColorStop(.55,  `rgba(${b.c},${(b.a * .3).toFixed(3)})`);
        g.addColorStop(1,    `rgba(${b.c},0)`);
        ctx.fillStyle = g; ctx.fillRect(0, 0, w, h);
      });
      ctx.restore();

      const vg = ctx.createLinearGradient(0, h * .4, 0, h);
      vg.addColorStop(0, 'rgba(17,16,24,0)');
      vg.addColorStop(1, 'rgba(17,16,24,.9)');
      ctx.fillStyle = vg; ctx.fillRect(0, 0, w, h);
    };

    const loop = () => { if (needsDraw) { draw(prog); needsDraw = false; } raf = requestAnimationFrame(loop); };
    const onScroll = () => {
      const max = document.documentElement.scrollHeight - window.innerHeight;
      prog = max > 0 ? Math.min(1, window.scrollY / max) : 0;
      needsDraw = true;
    };

    resize();
    window.addEventListener('resize', resize);
    window.addEventListener('scroll', onScroll, { passive: true });
    raf = requestAnimationFrame(loop);
    return () => { cancelAnimationFrame(raf); window.removeEventListener('resize', resize); window.removeEventListener('scroll', onScroll); };
  }, []);

  return <canvas ref={canvasRef} style={{ position:'fixed', inset:0, zIndex:0, width:'100%', height:'100%', pointerEvents:'none' }} aria-hidden="true" />;
}

/* ── Hero WebGL shader — brand-tinted light-wave beam ──────────────── */
function HeroShader() {
  const canvasRef = useRef(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas || !window.THREE) return;
    const THREE = window.THREE;

    // Read the brand accent (--violet) so the beam follows the tweakable palette
    const readTint = () => {
      const hex = getComputedStyle(document.documentElement).getPropertyValue('--violet').trim() || '#D6A8B7';
      const n = parseInt(hex.replace('#', ''), 16);
      return [((n >> 16) & 255) / 255, ((n >> 8) & 255) / 255, (n & 255) / 255];
    };

    const vertexShader = `
      attribute vec3 position;
      void main() { gl_Position = vec4(position, 1.0); }
    `;
    // Same wave shader as the reference component, but the three chromatic
    // channels are remapped onto the brand accent and output with alpha so
    // the beam blends over the aurora canvas instead of painting black.
    const fragmentShader = `
      precision highp float;
      uniform vec2 resolution;
      uniform float time;
      uniform float xScale;
      uniform float yScale;
      uniform float distortion;
      uniform vec3 tint;

      void main() {
        vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);

        float d = length(p) * distortion;

        float rx = p.x * (1.0 + d);
        float gx = p.x;
        float bx = p.x * (1.0 - d);

        // +0.52 shifts the wave into the lower third so it never
        // washes out the hero headline / subtitle / CTA copy.
        float py = p.y + 0.52;

        float r = 0.05 / abs(py + sin((rx + time) * xScale) * yScale);
        float g = 0.05 / abs(py + sin((gx + time) * xScale) * yScale);
        float b = 0.05 / abs(py + sin((bx + time) * xScale) * yScale);

        // Brand-palette remap: the three chromatic waves become
        // rose accent fringe / warm cream core / deep mauve fringe
        // instead of raw R/G/B (which reads as an off-brand rainbow).
        vec3 rose  = tint;
        vec3 cream = vec3(0.984, 0.973, 0.945);
        vec3 mauve = tint * vec3(0.62, 0.5, 0.78);

        vec3 col = r * rose * 0.85 + g * cream * 0.5 + b * mauve * 0.9;
        float a = clamp(max(r, max(g, b)) * 0.8, 0.0, 1.0);
        gl_FragColor = vec4(col, a);
      }
    `;

    const renderer = new THREE.WebGLRenderer({ canvas, alpha: true });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setClearColor(new THREE.Color(0x000000), 0);

    const scene = new THREE.Scene();
    const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, -1);

    const uniforms = {
      resolution: { value: [window.innerWidth, window.innerHeight] },
      time:       { value: 0.0 },
      xScale:     { value: 1.0 },
      yScale:     { value: 0.38 },
      distortion: { value: 0.05 },
      tint:       { value: readTint() },
    };

    const geometry = new THREE.BufferGeometry();
    geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array([
      -1, -1, 0,   1, -1, 0,   -1, 1, 0,
       1, -1, 0,  -1,  1, 0,    1, 1, 0,
    ]), 3));

    const material = new THREE.RawShaderMaterial({
      vertexShader, fragmentShader, uniforms,
      side: THREE.DoubleSide, transparent: true,
    });
    scene.add(new THREE.Mesh(geometry, material));

    const onResize = () => {
      renderer.setSize(window.innerWidth, window.innerHeight, false);
      uniforms.resolution.value = [window.innerWidth, window.innerHeight];
    };
    onResize();
    window.addEventListener('resize', onResize);

    let raf, frame = 0;
    const animate = () => {
      uniforms.time.value += 0.01;
      if (++frame % 60 === 0) uniforms.tint.value = readTint(); // follow Tweaks accent
      renderer.render(scene, camera);
      raf = requestAnimationFrame(animate);
    };
    animate();

    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener('resize', onResize);
      geometry.dispose();
      material.dispose();
      renderer.dispose();
    };
  }, []);

  return <canvas ref={canvasRef} style={{ position:'fixed', inset:0, zIndex:1, width:'100%', height:'100%', pointerEvents:'none' }} aria-hidden="true" />;
}

/* ── Pill Nav ──────────────────────────────────────────────────────── */
// Smooth-scroll to an in-page section, or fall back to normal navigation.
function navTo(e, href, base) {
  // base set (sub-page) or external link → let the browser navigate normally
  if (base || !href.startsWith('#')) return;
  e.preventDefault();
  const el = document.querySelector(href);
  if (!el) return;
  if (window.gsap && window.ScrollToPlugin) {
    window.gsap.to(window, { scrollTo: { y: el.offsetTop }, duration: 1.2, ease: 'power3.inOut' });
  } else {
    window.scrollTo({ top: el.offsetTop });
  }
}

function PillItem({ href, children, base = '', external = false }) {
  const [hov, setHov] = useState(false);
  const realHref = external ? href : (base ? base + href : href);
  return (
    <a href={realHref} onClick={(e) => { if (!external) navTo(e, href, base); }} className="pill-item"
      onMouseEnter={() => setHov(true)} onMouseLeave={() => setHov(false)}>
      <span className="pill-item-fill" style={{ transform: hov ? 'scale(1)' : 'scale(0)' }} />
      <span>{children}</span>
    </a>
  );
}

function PillNav({ base = '' }) {
  return (
    <nav className="pill-nav" aria-label="Primary">
      <a href={base || '#'} className="pill-nav-logo" aria-label="LIWAN home" onClick={(e) => {
        if (base) return; // sub-page → navigate home
        e.preventDefault();
        if (window.gsap && window.ScrollToPlugin) {
          window.gsap.to(window, { scrollTo: { y: 0 }, duration: 1.2, ease: 'power3.inOut' });
        } else {
          window.scrollTo({ top: 0 });
        }
      }}>
        <img src="assets/logos/Logo_04___Light_Icon_No_Bg.png" alt="LIWAN"
          style={{ height: '32px', width: 'auto', display: 'block' }} />
      </a>
      {[['WORK','#work'],['SERVICES','#services'],['PROCESS','#process'],['ABOUT','#about']].map(([l,h]) =>
        <PillItem key={l} href={h} base={base}>{l}</PillItem>
      )}
      <PillItem href="resources.html" external>RESOURCES</PillItem>
      <a href={base ? base + '#contact' : '#contact'} className="pill-nav-cta"
        onClick={(e) => navTo(e, '#contact', base)}>Book a Project</a>
    </nav>
  );
}

/* ── Hero Float ────────────────────────────────────────────────────── */
function HeroFloat({ subtitle }) {
  const heroRef = useRef(null);
  const { Eyebrow, ShinyBtn } = window;

  useEffect(() => {
    const el = heroRef.current;
    if (!el || !window.gsap || !window.ScrollTrigger) return;

    const chars = el.querySelectorAll('.char');
    const t1 = window.gsap.to(chars, {
      y: 80, opacity: 0, stagger: .011, ease: 'none',
      scrollTrigger: { trigger: el, start: 'top top', end: '+=920', scrub: 1.2 },
    });
    const t2 = window.gsap.to(['.scroll-hero-sub', '.scroll-hero-actions', '.scroll-hero-stats'], {
      y: 44, opacity: 0, ease: 'none',
      scrollTrigger: { trigger: el, start: 'top top', end: '+=560', scrub: 1 },
    });
    return () => { [t1,t2].forEach(t => t.scrollTrigger && t.scrollTrigger.kill()); };
  }, []);

  const lines = [
    { text: 'DESIGN.',   style: {} },
    { text: 'AUTOMATE.', style: { fontFamily:'var(--display-font)', fontStyle:'italic', fontWeight:300, color:'var(--violet)', fontSize:'1.06em' } },
    { text: 'GROW.',     style: {} },
  ];

  return (
    <div ref={heroRef} className="scroll-hero">
      <div className="scroll-hero-inner">
        <h1 className="scroll-float-title" aria-label="DESIGN. AUTOMATE. GROW.">
          {lines.map(({ text, style }, li) => (
            <span key={li} style={{ display:'block', ...style }}>
              {text.split('').map((ch, ci) => (
                <span key={ci} className="char" style={{ display:'inline-block' }}>{ch}</span>
              ))}
            </span>
          ))}
        </h1>
        <p className="scroll-hero-sub">{subtitle}</p>
        <div className="scroll-hero-actions">
          <ShinyBtn href="#contact">Book a Discovery Call &nbsp;→</ShinyBtn>
          <a href="#work" className="btn-secondary">
            <span className="btn-dot" aria-hidden="true" />
            <span>View our work</span>
          </a>
        </div>
        <div className="scroll-hero-stats hero-stats" aria-label="Key metrics">
          <div className="hero-stat">
            <span className="hero-stat-icon" aria-hidden="true">
              <svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor">
                <path d="M12 2.25l2.94 6.16 6.81.99-4.93 4.69 1.16 6.66L12 17.55l-5.98 3.2 1.16-6.66L2.25 9.4l6.81-.99L12 2.25z"/>
              </svg>
            </span>
            <span className="hero-stat-num">5.0</span>
            <span className="hero-stat-label">Average Client Rating</span>
          </div>
          <span className="hero-stat-sep" aria-hidden="true"/>
          <div className="hero-stat">
            <span className="hero-stat-icon" aria-hidden="true">
              <svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor">
                <path d="M13.5 2L4 13.5h7L9.5 22 20 10.5h-7L13.5 2z"/>
              </svg>
            </span>
            <span className="hero-stat-num">100</span>
            <span className="hero-stat-label">PageSpeed Score</span>
          </div>
          <span className="hero-stat-sep" aria-hidden="true"/>
          <div className="hero-stat">
            <span className="hero-stat-icon" aria-hidden="true">
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2z"/>
                <path d="M8 14s1.5 2 4 2 4-2 4-2"/>
                <line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/>
              </svg>
            </span>
            <span className="hero-stat-num">1 Niche</span>
            <span className="hero-stat-label">Wellness only</span>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ── Slide Panel ───────────────────────────────────────────────────── */
function SlidePanel({ eyebrow, title, num, children }) {
  const outerRef = useRef(null);
  const innerRef = useRef(null);

  useEffect(() => {
    const inner = innerRef.current;
    const outer = outerRef.current;
    if (!inner || !outer || !window.gsap || !window.ScrollTrigger) return;

    const slot = outer.closest('.section-slot') || outer;

    const tw = window.gsap.fromTo(inner,
      { y: '100%' },
      { y: '0%', ease: 'none',
        scrollTrigger: { trigger: slot, start: 'top bottom', end: 'top 10%', scrub: 1.2 } }
    );

    const onMove = (e) => {
      const r = inner.getBoundingClientRect();
      const rx = ((e.clientY - (r.top  + r.height / 2)) / r.height) * -7;
      const ry = ((e.clientX - (r.left + r.width  / 2)) / r.width)  *  7;
      window.gsap.to(inner, { rotationX: rx, rotationY: ry, duration: .45, ease: 'power2.out' });
    };
    const onLeave = () => window.gsap.to(inner, { rotationX:0, rotationY:0, duration:.85, ease:'elastic.out(1,.4)' });

    inner.addEventListener('mousemove', onMove);
    inner.addEventListener('mouseleave', onLeave);
    return () => {
      if (tw.scrollTrigger) tw.scrollTrigger.kill();
      inner.removeEventListener('mousemove', onMove);
      inner.removeEventListener('mouseleave', onLeave);
    };
  }, []);

  return (
    <div ref={outerRef} className="slide-panel-outer">
      <div ref={innerRef} className="slide-panel-inner">
        <div className="slide-panel-hd">
          <div>
            <div className="slide-panel-eyebrow">{eyebrow}</div>
            <div className="slide-panel-title">{title}</div>
          </div>
          <div className="slide-panel-num">{num}</div>
        </div>
        {children}
      </div>
    </div>
  );
}

Object.assign(window, { ScrollVideoBackground, HeroShader, PillNav, HeroFloat, SlidePanel });
