// Animated background components

const GradientMesh = ({ intensity = 1 }) => {
  const canvasRef = React.useRef(null);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let raf;
    let t = 0;

    const resize = () => {
      const dpr = window.devicePixelRatio || 1;
      canvas.width = canvas.offsetWidth * dpr;
      canvas.height = canvas.offsetHeight * dpr;
      ctx.scale(dpr, dpr);
    };
    resize();
    window.addEventListener('resize', resize);

    const blobs = [
      { x: 0.2, y: 0.3, r: 0.5, color: 'rgba(217, 205, 240, 0.6)', sx: 0.0003, sy: 0.0002 },
      { x: 0.8, y: 0.2, r: 0.4, color: 'rgba(167, 139, 217, 0.4)', sx: -0.0002, sy: 0.0003 },
      { x: 0.5, y: 0.8, r: 0.6, color: 'rgba(232, 222, 245, 0.7)', sx: 0.0002, sy: -0.0002 },
      { x: 0.9, y: 0.7, r: 0.35, color: 'rgba(201, 184, 232, 0.5)', sx: -0.0003, sy: -0.0001 },
    ];

    const draw = () => {
      const w = canvas.offsetWidth;
      const h = canvas.offsetHeight;
      ctx.clearRect(0, 0, w, h);
      blobs.forEach((b, i) => {
        const x = (b.x + Math.sin(t * b.sx * 120 + i) * 0.04) * w;
        const y = (b.y + Math.cos(t * b.sy * 120 + i) * 0.04) * h;
        const r = b.r * Math.min(w, h);
        const grad = ctx.createRadialGradient(x, y, 0, x, y, r);
        grad.addColorStop(0, b.color);
        grad.addColorStop(1, 'rgba(255,255,255,0)');
        ctx.fillStyle = grad;
        ctx.fillRect(0, 0, w, h);
      });
      t += intensity;
      raf = requestAnimationFrame(draw);
    };
    draw();

    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener('resize', resize);
    };
  }, [intensity]);

  return <canvas ref={canvasRef} className="hero-canvas" />;
};

const ParticleField = ({ density = 60, color = 'rgba(167, 139, 217, 0.5)', linkColor = 'rgba(167, 139, 217, 0.15)' }) => {
  const canvasRef = React.useRef(null);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let raf;
    let particles = [];
    let mouse = { x: -1000, y: -1000 };

    const resize = () => {
      const dpr = window.devicePixelRatio || 1;
      canvas.width = canvas.offsetWidth * dpr;
      canvas.height = canvas.offsetHeight * dpr;
      ctx.setTransform(1, 0, 0, 1, 0, 0);
      ctx.scale(dpr, dpr);
      const count = Math.min(density, Math.floor((canvas.offsetWidth * canvas.offsetHeight) / 18000));
      particles = Array.from({ length: count }, () => ({
        x: Math.random() * canvas.offsetWidth,
        y: Math.random() * canvas.offsetHeight,
        vx: (Math.random() - 0.5) * 0.3,
        vy: (Math.random() - 0.5) * 0.3,
        r: Math.random() * 1.6 + 0.6,
      }));
    };
    resize();
    window.addEventListener('resize', resize);

    const onMove = (e) => {
      const rect = canvas.getBoundingClientRect();
      mouse.x = e.clientX - rect.left;
      mouse.y = e.clientY - rect.top;
    };
    const onLeave = () => { mouse.x = -1000; mouse.y = -1000; };
    window.addEventListener('mousemove', onMove);
    canvas.addEventListener('mouseleave', onLeave);

    const draw = () => {
      const w = canvas.offsetWidth;
      const h = canvas.offsetHeight;
      ctx.clearRect(0, 0, w, h);

      particles.forEach((p) => {
        // mouse attraction
        const dx = mouse.x - p.x;
        const dy = mouse.y - p.y;
        const dist = Math.sqrt(dx * dx + dy * dy);
        if (dist < 140) {
          p.vx += (dx / dist) * 0.02;
          p.vy += (dy / dist) * 0.02;
        }
        p.vx *= 0.98;
        p.vy *= 0.98;
        p.x += p.vx;
        p.y += p.vy;
        if (p.x < 0) p.x = w; if (p.x > w) p.x = 0;
        if (p.y < 0) p.y = h; if (p.y > h) p.y = 0;

        ctx.fillStyle = color;
        ctx.beginPath();
        ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2);
        ctx.fill();
      });

      // links
      for (let i = 0; i < particles.length; i++) {
        for (let j = i + 1; j < particles.length; j++) {
          const a = particles[i], b = particles[j];
          const dx = a.x - b.x, dy = a.y - b.y;
          const d = Math.sqrt(dx * dx + dy * dy);
          if (d < 110) {
            ctx.strokeStyle = linkColor.replace(/[\d.]+\)$/, `${(1 - d / 110) * 0.2})`);
            ctx.lineWidth = 0.6;
            ctx.beginPath();
            ctx.moveTo(a.x, a.y);
            ctx.lineTo(b.x, b.y);
            ctx.stroke();
          }
        }
      }

      raf = requestAnimationFrame(draw);
    };
    draw();

    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener('resize', resize);
      window.removeEventListener('mousemove', onMove);
      canvas.removeEventListener('mouseleave', onLeave);
    };
  }, [density, color, linkColor]);

  return <canvas ref={canvasRef} className="hero-canvas" />;
};

// Reveal-on-scroll wrapper
const Reveal = ({ children, delay = 0, className = '', as: Tag = 'div', ...props }) => {
  const ref = React.useRef(null);
  const [seen, setSeen] = React.useState(false);

  React.useEffect(() => {
    if (!ref.current) return;
    const obs = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setSeen(true); obs.disconnect(); }
    }, { threshold: 0.15 });
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);

  const delayClass = delay ? `delay-${delay}` : '';
  return (
    <Tag ref={ref} className={`reveal ${delayClass} ${seen ? 'in' : ''} ${className}`} {...props}>
      {children}
    </Tag>
  );
};

// Word-by-word reveal for poetic headlines
const WordReveal = ({ children, className = '', as: Tag = 'h1' }) => {
  const ref = React.useRef(null);
  const [seen, setSeen] = React.useState(false);

  React.useEffect(() => {
    if (!ref.current) return;
    const obs = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setSeen(true); obs.disconnect(); }
    }, { threshold: 0.3 });
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);

  // children is array of strings or {it: 'string'}
  const items = Array.isArray(children) ? children : [children];
  let wi = 0;
  const renderToken = (tok, key) => {
    if (typeof tok === 'string') {
      const words = tok.split(/(\s+)/);
      return words.map((w, j) => {
        if (/^\s+$/.test(w)) return <React.Fragment key={`${key}-${j}`}>{w}</React.Fragment>;
        const idx = wi++;
        return (
          <span className="word" key={`${key}-${j}`}>
            <span style={{ '--i': idx }}>{w}</span>
          </span>
        );
      });
    }
    if (tok && tok.it) {
      const words = tok.it.split(/(\s+)/);
      return (
        <span className="word-it-group" key={key}>
          {words.map((w, j) => {
            if (/^\s+$/.test(w)) return <React.Fragment key={`${key}-${j}`}>{w}</React.Fragment>;
            const idx = wi++;
            return (
              <span className="word" key={`${key}-${j}`}>
                <span className="it" style={{ '--i': idx, fontStyle: 'italic', color: 'var(--primary-2)' }}>{w}</span>
              </span>
            );
          })}
        </span>
      );
    }
    return null;
  };

  return (
    <Tag ref={ref} className={`${className} ${seen ? 'in' : ''}`}>
      {items.map((tok, i) => (
        <React.Fragment key={i}>
          {renderToken(tok, i)}
          {i < items.length - 1 ? ' ' : ''}
        </React.Fragment>
      ))}
    </Tag>
  );
};

Object.assign(window, { GradientMesh, ParticleField, Reveal, WordReveal });
