// ============================================================
// Constellation Hero — variante experimental del Hero.
// Fondo negro + canvas 2D de partículas triangulares que se
// arman/desarman al scrollear dentro del propio Hero.
// Se activa eligiendo "Constellation" en el Tweaks Panel
// (variant === 'constellation' en Hero(), app.jsx).
// Sin imports/exports: se carga como <script type="text/babel">
// global, igual que enhancements.jsx y tweaks-panel.jsx.
// ============================================================

const { useEffect, useRef } = React;

const CH_COLORS = ['#8052ff', '#8052ff', '#b69cff', '#ffb829', '#ffb829', '#ffffff'];
const chRnd = (a, b) => a + Math.random() * (b - a);
const chGauss = (s) => (Math.random() + Math.random() + Math.random() - 1.5) * s * 1.4;

// Distribuye n puntos sobre una lista de segmentos [ [x1,y1],[x2,y2] ], con jitter.
function chSampleSegs(segs, n, jit = 0.02) {
  const lens = segs.map(([a, b]) => Math.hypot(b[0] - a[0], b[1] - a[1]));
  const total = lens.reduce((s, l) => s + l, 0);
  return Array.from({ length: n }, () => {
    let r = Math.random() * total;
    for (let i = 0; i < segs.length; i++) {
      if (r <= lens[i]) {
        const [a, b] = segs[i];
        const t = r / lens[i];
        return [a[0] + (b[0] - a[0]) * t + chGauss(jit), a[1] + (b[1] - a[1]) * t + chGauss(jit)];
      }
      r -= lens[i];
    }
    return [0, 0];
  });
}
const chPath = (pts, closed) => {
  const s = pts.slice(1).map((p, i) => [pts[i], p]);
  if (closed) s.push([pts[pts.length - 1], pts[0]]);
  return s;
};

// Forma A: dispersión suelta, tipo nube — puntos random dentro de una elipse ancha.
function chCloudShape(n) {
  return Array.from({ length: n }, () => {
    const a = chRnd(0, Math.PI * 2);
    const r = Math.sqrt(Math.random());
    return [Math.cos(a) * r * 0.5, Math.sin(a) * r * 0.32];
  });
}

// Forma B: cúmulo triangular — tres triángulos que evocan el motivo de marca
// (genérico, no es un trazado exacto del logo/isotipo real).
function chClusterShape(n) {
  const segs = [
    ...chPath([[-0.22, -0.16], [0.05, -0.22], [0.02, 0.02]], true),
    ...chPath([[0.02, 0.02], [-0.22, -0.16], [-0.2, 0.2]], true),
    ...chPath([[0.1, -0.12], [0.28, -0.02], [0.1, 0.1]], true),
  ];
  return chSampleSegs(segs, n, 0.012);
}

const chShuffle = (a) => {
  for (let i = a.length - 1; i > 0; i--) {
    const j = (Math.random() * (i + 1)) | 0;
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
};
const chEase = (x) => (x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2);

function ParticleMorphCanvas({ active }) {
  const ref = useRef(null);

  useEffect(() => {
    if (!active) return;
    const canvas = ref.current;
    const ctx = canvas.getContext('2d');
    const section = canvas.closest('.cdx-hero');
    const reduced = matchMedia('(prefers-reduced-motion: reduce)').matches;
    const mobile = innerWidth < 768;
    const N = mobile ? 140 : 200;

    const A = chShuffle(chCloudShape(N));
    const B = chShuffle(chClusterShape(N));
    const parts = Array.from({ length: N }, () => {
      const a = chRnd(0, Math.PI * 2);
      const d = chRnd(60, 240);
      return {
        s: chRnd(2.5, 6),
        rot: chRnd(0, 6.28),
        c: CH_COLORS[(Math.random() * CH_COLORS.length) | 0],
        o: chRnd(0.5, 1),
        sx: Math.cos(a) * d,
        sy: Math.sin(a) * d,
        ph: chRnd(0, 6.28),
        sp: chRnd(-1.2, 1.2),
      };
    });

    let W, H, dpr, cx, cy, size, raf, visible = true, cur = 0, target = 0;

    const resize = () => {
      dpr = Math.min(devicePixelRatio || 1, 2);
      W = section.offsetWidth;
      H = section.offsetHeight;
      canvas.width = W * dpr;
      canvas.height = H * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      cx = W * 0.5;
      cy = H * 0.5;
      size = Math.min(W, H) * (mobile ? 0.95 : 1.1);
    };

    const onScroll = () => {
      target = Math.max(0, Math.min(1, scrollY / innerHeight));
    };

    const io = new IntersectionObserver(([entry]) => { visible = entry.isIntersecting; }, { threshold: 0 });
    io.observe(section);

    resize();
    onScroll();
    addEventListener('resize', resize);
    addEventListener('scroll', onScroll, { passive: true });

    const t0 = performance.now();
    const frame = (now) => {
      raf = requestAnimationFrame(frame);
      if (document.hidden || !visible) return;
      cur += (target - cur) * (reduced ? 1 : 0.07);
      const t = reduced ? 0 : (now - t0) / 1000;
      const m = reduced ? 0 : 1;
      const e = chEase(cur);
      const burst = Math.sin(Math.PI * e) * 0.55 * m;

      ctx.clearRect(0, 0, W, H);
      ctx.lineWidth = 1.1;
      ctx.lineJoin = 'miter';
      for (let k = 0; k < N; k++) {
        const q = parts[k];
        const x = cx + (A[k][0] + (B[k][0] - A[k][0]) * e) * size + q.sx * burst + Math.sin(t * 0.9 + q.ph) * 3 * m;
        const y = cy + (A[k][1] + (B[k][1] - A[k][1]) * e) * size + q.sy * burst + Math.cos(t * 0.7 + q.ph) * 3 * m;
        const r = q.rot + cur * 1.8 * q.sp + t * 0.3 * q.sp * m;
        ctx.beginPath();
        for (let v = 0; v < 3; v++) {
          const a = r + v * 2.0944;
          const px = x + q.s * Math.cos(a);
          const py = y + q.s * Math.sin(a);
          v ? ctx.lineTo(px, py) : ctx.moveTo(px, py);
        }
        ctx.closePath();
        ctx.globalAlpha = q.o;
        ctx.strokeStyle = q.c;
        ctx.stroke();
      }
      ctx.globalAlpha = 1;
    };
    raf = requestAnimationFrame(frame);

    return () => {
      cancelAnimationFrame(raf);
      io.disconnect();
      removeEventListener('resize', resize);
      removeEventListener('scroll', onScroll);
    };
  }, [active]);

  if (!active) return null;
  return <canvas ref={ref} className="cdx-ch-canvas" aria-hidden="true" />;
}

function ConstellationHero({ typewriter }) {
  // Tapa los blobs .ambient/.grain globales de Codexa Landing.html mientras
  // esta variante está montada; se restauran solos al cambiar de variante.
  useEffect(() => {
    document.body.classList.add('cdx-hide-ambient');
    return () => document.body.classList.remove('cdx-hide-ambient');
  }, []);

  return (
    <>
      <ParticleMorphCanvas active />
      <div className="cdx-hero-content">
        <div className="cdx-hero-logo">
          <img src="assets/codexa-icon.png" alt="Codexa" />
        </div>
        <span className="cdx-eyebrow"><span className="dot"></span>Software · Solutions · Impact</span>
        <h1>
          Construimos<br />
          <em>{typewriter ? <Typewriter text="software a medida" speed={70} startDelay={400} /> : 'software a medida'}</em><br />
          que mueve negocios.
        </h1>
        <p className="lead">
          Somos un estudio de desarrollo enfocado en webs, aplicaciones y plataformas
          que combinan diseño, ingeniería e identidad de marca.
        </p>
        <div className="cdx-hero-cta">
          <a href="#contact" className="cdx-btn cdx-btn-primary">Empezar un proyecto <Icon.arrow /></a>
          <a href="#projects" className="cdx-btn cdx-btn-ghost">Ver nuestro trabajo</a>
        </div>
      </div>
      <div className="cdx-hero-scroll-cue">
        Scroll
        <div className="line"></div>
      </div>
    </>
  );
}
