// extras.jsx — bonus animations for the portfolio
const { useState: useStateX, useEffect: useEffectX, useRef: useRefX, useMemo: useMemoX } = React;

/* =============== 3D WIREFRAME GLOBE WITH ORBITING NODES =============== */
function Globe() {
  const ref = useRefX(null);
  useEffectX(() => {
    const canvas = ref.current;
    const ctx = canvas.getContext('2d');
    let w, h, dpr, raf;
    let mouseX = 0, mouseY = 0;
    let rotX = -0.3, rotY = 0;
    let targetRotX = -0.3, targetRotY = 0;

    function resize() {
      dpr = Math.min(window.devicePixelRatio || 1, 2);
      const rect = canvas.getBoundingClientRect();
      w = canvas.width = rect.width * dpr;
      h = canvas.height = rect.height * dpr;
    }
    resize();
    window.addEventListener('resize', resize);

    function onMove(e) {
      const rect = canvas.getBoundingClientRect();
      mouseX = (e.clientX - rect.left - rect.width/2) / rect.width;
      mouseY = (e.clientY - rect.top - rect.height/2) / rect.height;
      targetRotY = mouseX * 0.8;
      targetRotX = -0.3 + mouseY * 0.5;
    }
    window.addEventListener('mousemove', onMove);

    // Build sphere lattice
    const R = () => Math.min(w, h) * 0.32;
    const latitudes = 14;
    const longitudes = 22;
    const points = [];
    for (let i = 0; i <= latitudes; i++) {
      const lat = (i / latitudes) * Math.PI - Math.PI/2;
      for (let j = 0; j < longitudes; j++) {
        const lon = (j / longitudes) * Math.PI * 2;
        points.push({ lat, lon });
      }
    }

    // Orbiting product nodes — fixed positions on the sphere
    const nodes = [
      { lat: 0.6, lon: 0.5, label: 'BoekhoudBuddies' },
      { lat: -0.4, lon: 1.8, label: 'Aether Drift' },
      { lat: 0.3, lon: 3.0, label: 'Xcelerate' },
      { lat: -0.7, lon: 4.2, label: 'Praatbox' },
      { lat: 0.1, lon: 5.4, label: 'Kayamint' },
      { lat: 0.8, lon: 2.5, label: 'Kaya Core' },
    ];

    let t = 0;
    function project(lat, lon) {
      const r = R();
      // auto-rotate + mouse rotate
      const ry = rotY + t * 0.15;
      const rx = rotX;
      let x = Math.cos(lat) * Math.cos(lon);
      let y = Math.sin(lat);
      let z = Math.cos(lat) * Math.sin(lon);
      // rotate Y
      const cy = Math.cos(ry), sy = Math.sin(ry);
      let x2 = x * cy + z * sy;
      let z2 = -x * sy + z * cy;
      x = x2; z = z2;
      // rotate X
      const cx = Math.cos(rx), sx = Math.sin(rx);
      let y3 = y * cx - z * sx;
      let z3 = y * sx + z * cx;
      y = y3; z = z3;
      const cx2 = w/2, cy2 = h/2;
      return { x: cx2 + x * r, y: cy2 + y * r, z };
    }

    function tick() {
      t += 0.005;
      rotX += (targetRotX - rotX) * 0.06;
      rotY += (targetRotY - rotY) * 0.06;

      ctx.clearRect(0, 0, w, h);

      // glow center
      const grad = ctx.createRadialGradient(w/2, h/2, 0, w/2, h/2, R()*1.4);
      grad.addColorStop(0, 'rgba(255,106,43,0.05)');
      grad.addColorStop(1, 'rgba(255,106,43,0)');
      ctx.fillStyle = grad;
      ctx.fillRect(0, 0, w, h);

      // longitude lines
      for (let j = 0; j < longitudes; j++) {
        ctx.beginPath();
        for (let i = 0; i <= latitudes; i++) {
          const p = project(points[i*longitudes + j].lat, points[i*longitudes + j].lon);
          const a = (p.z + 1) * 0.5;
          ctx.strokeStyle = `rgba(244, 237, 228, ${a * 0.18})`;
          ctx.lineWidth = 1 * dpr;
          if (i === 0) ctx.moveTo(p.x, p.y);
          else ctx.lineTo(p.x, p.y);
        }
        ctx.stroke();
      }
      // latitude lines
      for (let i = 0; i <= latitudes; i++) {
        ctx.beginPath();
        for (let j = 0; j <= longitudes; j++) {
          const p = project(points[i*longitudes + (j%longitudes)].lat, points[i*longitudes + (j%longitudes)].lon);
          const a = (p.z + 1) * 0.5;
          ctx.strokeStyle = `rgba(244, 237, 228, ${a * 0.12})`;
          ctx.lineWidth = 1 * dpr;
          if (j === 0) ctx.moveTo(p.x, p.y);
          else ctx.lineTo(p.x, p.y);
        }
        ctx.stroke();
      }

      // nodes
      for (const n of nodes) {
        const p = project(n.lat, n.lon);
        const front = p.z > -0.1;
        const a = front ? Math.min(1, (p.z + 1) * 0.7) : 0.15;
        const r = front ? 4 * dpr : 2 * dpr;
        ctx.fillStyle = `rgba(255, 106, 43, ${a})`;
        ctx.beginPath();
        ctx.arc(p.x, p.y, r, 0, Math.PI * 2);
        ctx.fill();
        // glow
        if (front) {
          const g2 = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, 18*dpr);
          g2.addColorStop(0, `rgba(255, 106, 43, ${a*0.6})`);
          g2.addColorStop(1, 'rgba(255, 106, 43, 0)');
          ctx.fillStyle = g2;
          ctx.beginPath();
          ctx.arc(p.x, p.y, 18*dpr, 0, Math.PI*2);
          ctx.fill();
          // label
          ctx.fillStyle = `rgba(244, 237, 228, ${a})`;
          ctx.font = `${10*dpr}px JetBrains Mono, monospace`;
          ctx.fillText(n.label, p.x + 10*dpr, p.y - 8*dpr);
        }
      }

      raf = requestAnimationFrame(tick);
    }
    tick();
    return () => { cancelAnimationFrame(raf); window.removeEventListener('resize', resize); window.removeEventListener('mousemove', onMove); };
  }, []);
  return <canvas ref={ref} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%' }} />;
}

/* =============== MAGNETIC BUTTON WRAPPER =============== */
function Magnetic({ children, strength = 0.4 }) {
  const ref = useRefX(null);
  useEffectX(() => {
    const el = ref.current;
    if (!el) return;
    function move(e) {
      const r = el.getBoundingClientRect();
      const dx = e.clientX - (r.left + r.width/2);
      const dy = e.clientY - (r.top + r.height/2);
      el.style.transform = `translate(${dx*strength}px, ${dy*strength}px)`;
    }
    function leave() {
      el.style.transform = '';
    }
    el.addEventListener('mousemove', move);
    el.addEventListener('mouseleave', leave);
    return () => { el.removeEventListener('mousemove', move); el.removeEventListener('mouseleave', leave); };
  }, [strength]);
  return <span ref={ref} style={{ display: 'inline-block', transition: 'transform 0.5s cubic-bezier(0.22,1,0.36,1)' }}>{children}</span>;
}

/* =============== SPLIT-LETTER REVEAL =============== */
function SplitText({ text, className = '', delay = 0 }) {
  const ref = useRefX(null);
  const [visible, setVisible] = useStateX(false);
  useEffectX(() => {
    const obs = new IntersectionObserver((es) => {
      if (es[0].isIntersecting) { setVisible(true); obs.disconnect(); }
    }, { threshold: 0.3 });
    if (ref.current) obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  return (
    <span ref={ref} className={className} style={{ display: 'inline-block' }}>
      {text.split('').map((ch, i) => (
        <span key={i} style={{
          display: 'inline-block',
          opacity: visible ? 1 : 0,
          transform: visible ? 'translateY(0) rotate(0)' : 'translateY(40px) rotate(8deg)',
          transition: `opacity 0.6s, transform 0.8s cubic-bezier(0.22,1,0.36,1)`,
          transitionDelay: `${delay + i*0.025}s`,
          whiteSpace: ch === ' ' ? 'pre' : 'normal'
        }}>{ch}</span>
      ))}
    </span>
  );
}

/* =============== TILT WRAPPER (3D mouse parallax) =============== */
function Tilt({ children, max = 8 }) {
  const ref = useRefX(null);
  useEffectX(() => {
    const el = ref.current;
    if (!el) return;
    function move(e) {
      const r = el.getBoundingClientRect();
      const px = (e.clientX - r.left) / r.width - 0.5;
      const py = (e.clientY - r.top) / r.height - 0.5;
      el.style.transform = `perspective(1200px) rotateX(${-py*max}deg) rotateY(${px*max}deg)`;
    }
    function leave() { el.style.transform = ''; }
    el.addEventListener('mousemove', move);
    el.addEventListener('mouseleave', leave);
    return () => { el.removeEventListener('mousemove', move); el.removeEventListener('mouseleave', leave); };
  }, [max]);
  return <div ref={ref} style={{ transition: 'transform 0.4s cubic-bezier(0.22,1,0.36,1)', transformStyle: 'preserve-3d' }}>{children}</div>;
}

/* =============== ANIMATED INITIALS C K =============== */
function Signature() {
  const ref = useRefX(null);
  const [draw, setDraw] = useStateX(false);
  useEffectX(() => {
    const obs = new IntersectionObserver((es) => {
      if (es[0].isIntersecting) { setDraw(true); obs.disconnect(); }
    }, { threshold: 0.4 });
    if (ref.current) obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  const lineStyle = (delay, dash) => ({
    strokeDasharray: dash,
    strokeDashoffset: draw ? 0 : dash,
    transition: `stroke-dashoffset 1.6s cubic-bezier(0.6, 0.05, 0.3, 1) ${delay}s`,
  });
  return (
    <div ref={ref} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', padding: '60px 0 0', gap: 18 }}>
      <svg viewBox="0 0 320 200" width="220" height="140" style={{ overflow: 'visible' }}>
        {/* C */}
        <path
          d="M 130 40 A 60 60 0 1 0 130 160"
          stroke="var(--accent)" strokeWidth="3" fill="none" strokeLinecap="round"
          style={lineStyle(0, 380)}
        />
        {/* K - vertical bar */}
        <line x1="180" y1="40" x2="180" y2="160"
          stroke="var(--accent)" strokeWidth="3" strokeLinecap="round"
          style={lineStyle(0.8, 130)}
        />
        {/* K - upper diagonal */}
        <line x1="180" y1="100" x2="240" y2="40"
          stroke="var(--accent)" strokeWidth="3" strokeLinecap="round"
          style={lineStyle(1.4, 90)}
        />
        {/* K - lower diagonal */}
        <line x1="180" y1="100" x2="240" y2="160"
          stroke="var(--accent)" strokeWidth="3" strokeLinecap="round"
          style={lineStyle(1.7, 90)}
        />
        {/* underline */}
        <line x1="80" y1="180" x2="260" y2="180"
          stroke="var(--ink-dim)" strokeWidth="1" strokeLinecap="round"
          style={lineStyle(2.2, 200)}
        />
      </svg>
      <div style={{
        fontFamily: 'JetBrains Mono, monospace',
        fontSize: 10,
        letterSpacing: '0.35em',
        color: 'var(--ink-dim)',
        opacity: draw ? 1 : 0,
        transition: 'opacity 0.8s ease 2.6s'
      }}>CIHAT&nbsp;&nbsp;KAYA&nbsp;&nbsp;·&nbsp;&nbsp;2026</div>
    </div>
  );
}

/* =============== NOISE GRADIENT BLOB (cursor follower) =============== */
function Blob() {
  const ref = useRefX(null);
  useEffectX(() => {
    let x = window.innerWidth / 2, y = window.innerHeight / 2;
    let tx = x, ty = y;
    function move(e) { tx = e.clientX; ty = e.clientY; }
    function loop() {
      x += (tx - x) * 0.04;
      y += (ty - y) * 0.04;
      if (ref.current) ref.current.style.transform = `translate(${x - 300}px, ${y - 300}px)`;
      requestAnimationFrame(loop);
    }
    window.addEventListener('mousemove', move);
    loop();
    return () => window.removeEventListener('mousemove', move);
  }, []);
  return (
    <div ref={ref} style={{
      position: 'fixed', top: 0, left: 0,
      width: 600, height: 600,
      background: 'radial-gradient(circle, var(--accent) 0%, transparent 60%)',
      filter: 'blur(80px)',
      opacity: 0.18,
      pointerEvents: 'none',
      zIndex: 0,
      mixBlendMode: 'screen',
    }} />
  );
}

/* =============== MARQUEE WITH SCROLL VELOCITY =============== */
function VelocityMarquee({ items }) {
  const ref = useRefX(null);
  useEffectX(() => {
    let lastY = window.scrollY;
    let velocity = 0;
    let pos = 0;
    let raf;
    function tick() {
      const y = window.scrollY;
      const dv = (y - lastY) * 0.5;
      lastY = y;
      velocity = velocity * 0.9 + dv;
      pos -= 0.5 + Math.abs(velocity) * 0.4;
      if (ref.current) {
        const w = ref.current.scrollWidth / 3;
        if (pos < -w) pos += w;
        ref.current.style.transform = `translateX(${pos}px)`;
      }
      raf = requestAnimationFrame(tick);
    }
    tick();
    return () => cancelAnimationFrame(raf);
  }, []);
  return (
    <div className="marquee">
      <div className="marquee-track" ref={ref} style={{ animation: 'none' }}>
        {[...items, ...items, ...items].map((it, i) => (
          <span key={i}>{it} <span className="star">✱</span></span>
        ))}
      </div>
    </div>
  );
}

/* =============== EXPOSE TO WINDOW =============== */
window.Globe = Globe;
window.Magnetic = Magnetic;
window.SplitText = SplitText;
window.Tilt = Tilt;
window.Signature = Signature;
window.Blob = Blob;
window.VelocityMarquee = VelocityMarquee;
