/* global React */
const { useState, useEffect, useRef, useMemo } = React;

// ============================================
// HERO PINNED — text esquerra + mosaic dreta
// ============================================
// - Scroll dins del hero és CAPTURAT (pinned) fins completar la seqüència.
// - Columna esquerra: 3 missatges de text que es creuen en fade/translate.
// - Columna dreta: mosaic 8×6 que passa de caos a tauler d'escacs + logo.
// - Layout dins del container del site (no full-bleed).

const MCOLS = 8;
const MROWS = 6;

const PALETTE_CHAOS = ['#E5E7EB', '#CBD5E1', '#FFFFFF', '#003C70', '#005096', '#FF4E00'];

const buildMosaicCells = () => {
  const rnd = (min, max) => min + Math.random() * (max - min);
  const cells = [];
  // àrea central on apareixerà el logo
  const logoTop = 2, logoBottom = 3;
  const logoLeft = 1, logoRight = MCOLS - 2;
  for (let r = 0; r < MROWS; r++) {
    for (let c = 0; c < MCOLS; c++) {
      const chaosColor = PALETTE_CHAOS[Math.floor(Math.random() * PALETTE_CHAOS.length)];
      const isCheck = (r + c) % 2 === 0;
      const inLogo = r >= logoTop && r <= logoBottom && c >= logoLeft && c <= logoRight;
      let orderColor;
      if (inLogo) {
        orderColor = '#FFFFFF';
      } else {
        const navyPick = ((r * 3 + c * 5) % 7 === 0);
        const orangePick = ((r * 7 + c * 11) % 19 === 0);
        if (orangePick) orderColor = '#FF4E00';
        else if (navyPick) orderColor = '#003C70';
        else orderColor = isCheck ? '#E5E7EB' : '#FFFFFF';
      }
      cells.push({
        r, c,
        dx: rnd(-50, 50),
        dy: rnd(-50, 50),
        rot: rnd(-25, 25),
        scl: rnd(0.78, 1.12),
        chaosColor,
        orderColor,
        inLogo,
        delay: Math.random() * 0.35,
      });
    }
  }
  return cells;
};

const easeOutCubic = (t) => 1 - Math.pow(1 - t, 3);
const clampP = (v, a = 0, b = 1) => Math.max(a, Math.min(b, v));

// ─────────────────────────────────────────────
// Missatges (3 estats del text)
// ─────────────────────────────────────────────
const HERO_MESSAGES = [
  {
    eyebrow: 'Gobernanza de datos · Digitalización · IA aplicada · Inmersión aplicada',
    title: (
      <>Tus datos están ahí.<br/>Tu ventaja competitiva,<br/>también.</>
    ),
    lead: (
      <>Ordenamos tu información, digitalizamos tus procesos y aplicamos
      inteligencia artificial donde realmente importa. En ese orden, porque
      no se puede automatizar lo que no está organizado.{' '}
      <strong>Tú decides el ritmo. Nosotros ponemos la hoja de ruta.</strong></>
    ),
  },
  {
    eyebrow: 'El problema',
    title: (
      <>Hoy tus datos son<br/>un <span className="hl">mosaico sin gobierno</span>.</>
    ),
    lead: (
      <>Duplicados, silos, Excels que viven en carpetas privadas. Nadie sabe
      quién manda en qué — y automatizar encima de eso es acelerar el caos.</>
    ),
  },
  {
    eyebrow: 'La solución',
    title: (
      <>Primero el <span className="accent">orden</span>.<br/>
      Después, la <span className="accent">inteligencia</span>.</>
    ),
    lead: (
      <>Ponemos cada pieza en su sitio, la digitalización llega natural y la
      IA se aplica donde de verdad cambia el negocio.</>
    ),
  },
];

const HeroPinned = () => {
  const stageRef = useRef(null);
  const mosaicRef = useRef(null);
  const logoRef = useRef(null);
  const progressRef = useRef(0);
  const virtualRef = useRef(0);
  const rafRef = useRef(null);
  const cells = useMemo(buildMosaicCells, []);
  const [activeMsg, setActiveMsg] = useState(0);
  const [progress, setProgress] = useState(0);

  // Pinta el mosaic
  const drawMosaic = (p) => {
    const grid = mosaicRef.current;
    if (!grid) return;
    const pEase = easeOutCubic(p);
    const children = grid.children;
    for (let i = 0; i < cells.length && i < children.length; i++) {
      const cell = cells[i];
      const localP = clampP((pEase - cell.delay * 0.4) / (1 - cell.delay * 0.4));
      const invP = 1 - localP;
      const tx = cell.dx * invP;
      const ty = cell.dy * invP;
      const rot = cell.rot * invP;
      const scl = 1 + (cell.scl - 1) * invP;
      const el = children[i];
      el.style.transform = `translate(${tx}px, ${ty}px) rotate(${rot}deg) scale(${scl})`;
      el.style.background = localP < 0.5 ? cell.chaosColor : cell.orderColor;
      // Cel·les del logo: fade-out cap al final per donar espai al logo
      if (cell.inLogo && p > 0.78) {
        el.style.opacity = Math.max(0, 1 - (p - 0.78) * 5);
      } else {
        el.style.opacity = 1;
      }
    }
    // Logo emergeix al final
    if (logoRef.current) {
      const lp = clampP((p - 0.82) / 0.18);
      logoRef.current.style.opacity = lp;
      logoRef.current.style.transform = `translate(-50%, -50%) scale(${0.92 + lp * 0.08})`;
      logoRef.current.style.filter = `blur(${(1 - lp) * 8}px)`;
    }
  };

  // Actualitza quin missatge es mostra segons progress
  const updateMessage = (p) => {
    let idx = 0;
    if (p >= 0.66) idx = 2;
    else if (p >= 0.33) idx = 1;
    else idx = 0;
    setActiveMsg(idx);
  };

  useEffect(() => {
    const isMobile = window.matchMedia('(max-width: 768px)').matches;
    // Total "virtual distance" que cal consumir per completar la seqüència
    const TOTAL = 1400; // px

    const apply = (v) => {
      const p = clampP(v / TOTAL);
      progressRef.current = p;
      virtualRef.current = v;
      setProgress(p);
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
      rafRef.current = requestAnimationFrame(() => {
        drawMosaic(p);
        updateMessage(p);
      });
    };

    // Mentre la secció toca la part superior del viewport, capturem wheel/touch
    // tant en sentit avall (per avançar la seqüència) com amunt (per reversar-la).
    // Només deixem passar el scroll nadiu quan:
    //   - estem a 0 i l'usuari tira amunt (deixa sortir per dalt)
    //   - estem a TOTAL i l'usuari tira avall (deixa continuar cap a les seccions)
    const isEngaged = () => {
      const stage = stageRef.current;
      if (!stage) return false;
      const rect = stage.getBoundingClientRect();
      // Enganxat quan el top del stage ja ha arribat (o sobrepassat) el top del viewport
      // i encara no ha sortit per baix.
      return rect.top <= 0.5 && rect.bottom > 0;
    };

    const onWheel = (e) => {
      if (!isEngaged()) return;
      const v = virtualRef.current;
      const dy = e.deltaY;
      // Si estem al final i l'usuari tira avall → deixa passar
      if (v >= TOTAL && dy > 0) return;
      // Si estem al principi i l'usuari tira amunt → deixa passar
      if (v <= 0 && dy < 0) return;
      // Altrament, captura i avança/retrocedeix el progrés virtual
      e.preventDefault();
      const next = clampP(v + dy, 0, TOTAL);
      apply(next);
    };

    let touchY = 0;
    const onTouchStart = (e) => { touchY = e.touches[0].clientY; };
    const onTouchMove = (e) => {
      if (!isEngaged()) return;
      const y = e.touches[0].clientY;
      const delta = (touchY - y) * 1.8;
      touchY = y;
      const v = virtualRef.current;
      if (v >= TOTAL && delta > 0) return;
      if (v <= 0 && delta < 0) return;
      e.preventDefault();
      const next = clampP(v + delta, 0, TOTAL);
      apply(next);
    };

    // Si fan scroll programàtic i tornen al top, sincronitza el progrés a 0
    const onScroll = () => {
      if (!stageRef.current) return;
      const rect = stageRef.current.getBoundingClientRect();
      // Si la secció està completament per sota del viewport (tornem a dalt), reset a 0
      if (rect.top > 20 && virtualRef.current !== 0) {
        apply(0);
      }
    };

    // Keyboard
    const onKey = (e) => {
      if (!isEngaged()) return;
      const v = virtualRef.current;
      if (e.key === 'ArrowDown' || e.key === 'PageDown' || e.key === ' ') {
        if (v >= TOTAL) return; // deixa el scroll nadiu
        e.preventDefault();
        apply(clampP(v + 160, 0, TOTAL));
      } else if (e.key === 'ArrowUp' || e.key === 'PageUp') {
        if (v <= 0) return;
        e.preventDefault();
        apply(clampP(v - 160, 0, TOTAL));
      }
    };

    if (!isMobile) {
      window.addEventListener('wheel', onWheel, { passive: false });
      window.addEventListener('touchstart', onTouchStart, { passive: true });
      window.addEventListener('touchmove', onTouchMove, { passive: false });
      window.addEventListener('keydown', onKey);
    }
    window.addEventListener('scroll', onScroll, { passive: true });

    apply(0);

    return () => {
      if (!isMobile) {
        window.removeEventListener('wheel', onWheel);
        window.removeEventListener('touchstart', onTouchStart);
        window.removeEventListener('touchmove', onTouchMove);
        window.removeEventListener('keydown', onKey);
      }
      window.removeEventListener('scroll', onScroll);
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <section ref={stageRef} className="hero-pinned">
      <div className="hero-pinned-sticky">
        <div className="container-wide hero-pinned-inner">
          <div className="hero-pinned-grid">
            {/* ESQUERRA — text */}
            <div className="hero-pinned-copy">
              {HERO_MESSAGES.map((m, i) => (
                <div
                  key={i}
                  className={`hero-pinned-msg ${i === activeMsg ? 'is-active' : i < activeMsg ? 'is-past' : 'is-future'}`}
                >
                  <p className="hero-pinned-eyebrow">{m.eyebrow}</p>
                  <h1 className="hero-pinned-h1">{m.title}</h1>
                  <p className="hero-pinned-lead">{m.lead}</p>
                </div>
              ))}

              {/* CTAs només al tercer missatge */}
              <div className={`hero-pinned-cta ${activeMsg === 2 ? 'is-active' : ''}`}>
                <a className="btn btn-primary" href="#contacto">Solicita tu diagnóstico →</a>
                <a className="btn btn-ghost" href="#metodologia">Ver cómo trabajamos</a>
              </div>

              {/* Progress + hint */}
              <div className="hero-pinned-footer">
                <div className="hero-pinned-dots">
                  {HERO_MESSAGES.map((_, i) => (
                    <span key={i} className={`dot ${i === activeMsg ? 'is-active' : ''} ${i < activeMsg ? 'is-past' : ''}`} />
                  ))}
                </div>
                <div className="hero-pinned-hint">
                  <span className="arr">↓</span>
                  <span>{progress < 0.99 ? 'Sigue bajando para poner orden' : 'Continúa para descubrir más'}</span>
                </div>
              </div>
            </div>

            {/* DRETA — mosaic */}
            <div className="hero-pinned-visual">
              <div className="mosaic-square">
                <div
                  ref={mosaicRef}
                  className="mosaic-grid-tight"
                  style={{ '--cols': MCOLS, '--rows': MROWS }}
                >
                  {cells.map((_, i) => <div key={i} className="mosaic-tile" />)}
                </div>
                <div ref={logoRef} className="mosaic-logo-center" aria-hidden="true">
                  <img src="assets/logo-horizontal.svg" alt="" />
                </div>
                <div className="mosaic-state">
                  <span className="dot" style={{
                    background: progress < 0.33 ? '#FF4E00' : progress < 0.82 ? '#B45309' : '#16A34A'
                  }} />
                  <span>{progress < 0.33 ? 'Sin gobierno' : progress < 0.82 ? 'Auditando' : 'Gobernado'}</span>
                </div>
                <div className="mosaic-progress">
                  <div className="mosaic-progress-bar" style={{ width: `${progress * 100}%` }} />
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
};

Object.assign(window, { HeroPinned });
