/*
 * gsap-anims.jsx — V69 CALM POLISH (2026-05-19)
 *
 * User feedback (V68 review): "animaciones bruscas en scroll, full bug,
 * hubs vacio y basico, élite ranking falto, compite por la cima fea anim".
 *
 * V69 changes from V68 magic:
 *   - REMOVE char-split hero (it was jumping awkwardly on Babel render)
 *   - REMOVE hubs PIN+ZOOM (too sticky, jarring scroll-jump out)
 *     → replaced with SOFT staggered scale-in as cards enter viewport
 *   - REMOVE color theme shift per section (too distracting)
 *   - REMOVE 3D mouse tilt from generic .card selector
 *     → restrict to only [data-ow-tilt] cards (opt-in, not all)
 *   - REMOVE bento flip rotateY (was distorting tables / non-card elements)
 *     → replaced with simple fade-up + scale
 *   - SOFTEN progress bar
 *   - KEEP: cursor blob, scroll reveals (gentler), magnetic, count-up,
 *           horizontal games scroll, parallax (subtle)
 *   - ADD: Élite ranking empty-state breathe pulse
 *   - ADD: Hubs cards entrance with sequential scale + glow (no pin)
 *
 * Respects prefers-reduced-motion + Potato Mode 🥔.
 */
(function setupGsapAnims() {
  if (typeof window === 'undefined') return;
  if (window.__OW_GSAP_INIT__) return;
  window.__OW_GSAP_INIT__ = true;

  if (window.__OW_PERF__ === 'lite' || document.documentElement.getAttribute('data-perf') === 'lite') {
    console.info('[gsap-anims] 🥔 Potato — skipping');
    return;
  }
  const reduced = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

  const whenReady = (fn) => {
    if (document.readyState === 'complete') setTimeout(fn, 350);
    else window.addEventListener('load', () => setTimeout(fn, 350), { once: true });
  };
  whenReady(() => {
    if (!window.gsap || !window.ScrollTrigger) { console.warn('[gsap-anims] GSAP missing'); return; }
    try {
      window.gsap.registerPlugin(window.ScrollTrigger);
      init();
    } catch (e) { console.warn('[gsap-anims] init fail:', e && e.message); }
  });

  function init() {
    const gsap = window.gsap;
    const ScrollTrigger = window.ScrollTrigger;
    ScrollTrigger.config({ ignoreMobileResize: true });

    setupProgressBar(gsap, ScrollTrigger);
    setupHero(gsap);
    if (!reduced && window.matchMedia('(hover:hover)').matches) setupCursorBlob(gsap);
    setupScrollReveals(gsap, ScrollTrigger);
    setupHubsSoftStagger(gsap, ScrollTrigger);   // V69: replaces hubs pin
    setupBentoFade(gsap, ScrollTrigger);          // V69: replaces flip
    if (!reduced) setupTiltOptIn(gsap);           // V69: opt-in only
    if (!reduced) setupParallax(gsap, ScrollTrigger);
    if (!reduced) setupMagnetic(gsap);
    setupCountUps(gsap, ScrollTrigger);
    setupHorizontalGames(gsap, ScrollTrigger);
    setupEmptyStatePulse(gsap, ScrollTrigger);   // V69: élite ranking life

    setTimeout(() => ScrollTrigger.refresh(), 600);

    // INICIO-FIX-V2 (2026-05-20): hero/reveal safety net. If a tween fails or
    // gets cancelled (Babel reflow, ScrollTrigger out of sync, prefers-reduced-
    // motion edge cases…) the page would stay black. After 2.5s we force-show
    // every element gsap left at opacity:0. The animation effect is lost in
    // those edge cases, but content is always visible — never black.
    setTimeout(() => {
      try {
        const all = document.querySelectorAll('#inicio *, .reveal');
        all.forEach(el => {
          const cs = getComputedStyle(el);
          if (parseFloat(cs.opacity) < 0.05) {
            el.style.opacity = '1';
            el.style.transform = 'none';
          }
        });
      } catch (_) { /* noop */ }
    }, 2500);
  }

  // ─── PROGRESS BAR ──────────────────────────────────────────────────
  function setupProgressBar(gsap, ScrollTrigger) {
    const bar = document.createElement('div');
    bar.id = 'ow-scroll-progress';
    bar.style.cssText = 'position:fixed;top:0;left:0;height:2px;width:0%;background:linear-gradient(90deg,var(--accent),var(--accent-2));z-index:9999;pointer-events:none;box-shadow:0 0 8px var(--accent);';
    document.body.appendChild(bar);
    ScrollTrigger.create({
      trigger: document.body, start: 'top top', end: 'bottom bottom',
      onUpdate: (self) => { bar.style.width = (self.progress * 100).toFixed(2) + '%'; },
    });
  }

  // ─── HERO ENTRANCE (suave, sin char-split) ─────────────────────────
  function setupHero(gsap) {
    const hero = document.getElementById('inicio');
    if (!hero) return;
    const title = hero.querySelector('h1.display');
    const eyebrow = hero.querySelector('.pill');
    const desc = hero.querySelector('p');
    const ctas = hero.querySelectorAll('a.btn');
    const stats = hero.querySelectorAll('.mono');
    const telemetry = hero.querySelector('#hero-grid > div:last-child');

    gsap.set([eyebrow, title, desc, ...ctas, ...stats, telemetry].filter(Boolean), { opacity: 0, y: 30 });

    const tl = gsap.timeline({ defaults: { ease: 'expo.out', duration: 0.9 } });
    if (eyebrow) tl.to(eyebrow, { opacity: 1, y: 0, duration: 0.6 });
    if (title) tl.to(title, { opacity: 1, y: 0, duration: 1.0 }, '-=0.35');
    if (desc) tl.to(desc, { opacity: 1, y: 0 }, '-=0.65');
    if (ctas.length) tl.to(ctas, { opacity: 1, y: 0, stagger: 0.08, duration: 0.7 }, '-=0.6');
    if (stats.length) tl.to(stats, { opacity: 1, y: 0, stagger: 0.05, duration: 0.5 }, '-=0.5');
    if (telemetry) tl.to(telemetry, { opacity: 1, y: 0, duration: 1.0 }, '-=0.95');
  }

  // ─── CURSOR BLOB (gentle) ───────────────────────────────────────────
  function setupCursorBlob() {
    const blob = document.createElement('div');
    blob.id = 'ow-cursor-blob';
    blob.style.cssText = 'position:fixed;top:0;left:0;width:300px;height:300px;border-radius:50%;background:radial-gradient(circle at center, color-mix(in srgb, var(--accent) 25%, transparent), transparent 60%);pointer-events:none;z-index:1;mix-blend-mode:screen;filter:blur(50px);transform:translate(-50%,-50%);opacity:0;transition:opacity .5s';
    document.body.appendChild(blob);
    let mx = innerWidth / 2, my = innerHeight / 2, bx = mx, by = my;
    addEventListener('pointermove', e => { mx = e.clientX; my = e.clientY; blob.style.opacity = '1'; });
    document.addEventListener('mouseleave', () => { blob.style.opacity = '0'; });
    (function tick() {
      bx += (mx - bx) * 0.1; by += (my - by) * 0.1;
      blob.style.transform = `translate(${bx}px, ${by}px) translate(-50%,-50%)`;
      requestAnimationFrame(tick);
    })();
  }

  // ─── SCROLL REVEALS (suave) ────────────────────────────────────────
  function setupScrollReveals(gsap, ScrollTrigger) {
    const hero = document.getElementById('inicio');
    document.querySelectorAll('.reveal').forEach(el => {
      if (hero && hero.contains(el)) return;
      // Skip hubs grid — handled by setupHubsSoftStagger
      if (el.id === 'hubs-grid' || el.closest('#hubs-grid')) return;
      gsap.fromTo(el,
        { opacity: 0, y: 40 },
        {
          opacity: 1, y: 0,
          duration: 0.9, ease: 'expo.out',
          scrollTrigger: { trigger: el, start: 'top 85%', once: true },
        }
      );
    });

    // Section headers: gentle reveal
    document.querySelectorAll('section').forEach(sec => {
      if (hero === sec) return;
      const h2 = sec.querySelector('h2');
      if (!h2) return;
      gsap.fromTo(h2,
        { opacity: 0, y: 30 },
        {
          opacity: 1, y: 0,
          duration: 0.9, ease: 'expo.out',
          scrollTrigger: { trigger: h2, start: 'top 88%', once: true },
        }
      );
    });
  }

  // ─── HUBS SOFT STAGGER (V69 — replaces V68 pin) ────────────────────
  function setupHubsSoftStagger(gsap, ScrollTrigger) {
    const hubs = document.getElementById('hubs');
    if (!hubs) return;
    const grid = hubs.querySelector('#hubs-grid');
    if (!grid) return;
    const cards = Array.from(grid.children);
    if (cards.length < 2) return;

    cards.forEach((card, i) => {
      gsap.fromTo(card,
        { opacity: 0, y: 60, scale: 0.92 },
        {
          opacity: 1, y: 0, scale: 1,
          duration: 1.0,
          ease: 'expo.out',
          scrollTrigger: { trigger: grid, start: 'top 80%', once: true },
          delay: i * 0.12,
        }
      );
    });

    // Subtle hover glow boost on each card (no transform, just shadow)
    cards.forEach(card => {
      card.style.transition = (card.style.transition || '') + ', box-shadow .35s ease';
      card.addEventListener('mouseenter', () => {
        gsap.to(card, { boxShadow: '0 24px 60px -16px rgba(91,140,255,0.4), 0 0 0 1px var(--accent)', duration: 0.4 });
      });
      card.addEventListener('mouseleave', () => {
        gsap.to(card, { boxShadow: '', duration: 0.6 });
      });
    });
  }

  // ─── BENTO FADE (V69 — gentle, no rotateY) ─────────────────────────
  function setupBentoFade(gsap, ScrollTrigger) {
    document.querySelectorAll('.card').forEach(card => {
      if (card.closest('#hubs')) return; // handled separately
      if (card.closest('#hero-grid')) return; // hero handles its own
      gsap.fromTo(card,
        { opacity: 0, y: 30, scale: 0.96 },
        {
          opacity: 1, y: 0, scale: 1,
          duration: 0.9, ease: 'expo.out',
          scrollTrigger: { trigger: card, start: 'top 88%', once: true },
        }
      );
    });
  }

  // ─── 3D TILT OPT-IN (V69 — only [data-ow-tilt]) ────────────────────
  function setupTiltOptIn(gsap) {
    const cards = document.querySelectorAll('[data-ow-tilt]');
    cards.forEach(card => {
      if (card.dataset.owTiltBound === '1') return;
      card.dataset.owTiltBound = '1';
      const parent = card.parentElement;
      if (parent && !parent.style.perspective) parent.style.perspective = '1400px';
      card.style.transformStyle = 'preserve-3d';
      let bounds = null;
      card.addEventListener('mouseenter', () => { bounds = card.getBoundingClientRect(); });
      card.addEventListener('mousemove', e => {
        if (!bounds) bounds = card.getBoundingClientRect();
        const x = (e.clientX - bounds.left) / bounds.width;
        const y = (e.clientY - bounds.top) / bounds.height;
        gsap.to(card, {
          rotateX: -(y - 0.5) * 10,
          rotateY: (x - 0.5) * 12,
          transformPerspective: 1400,
          duration: 0.4, ease: 'power2.out', overwrite: 'auto',
        });
      });
      card.addEventListener('mouseleave', () => {
        bounds = null;
        gsap.to(card, { rotateX: 0, rotateY: 0, duration: 0.6, ease: 'expo.out', overwrite: 'auto' });
      });
    });
  }

  // ─── PARALLAX (subtle) ─────────────────────────────────────────────
  function setupParallax(gsap, ScrollTrigger) {
    document.querySelectorAll('.grid-bg').forEach(el => {
      gsap.fromTo(el, { y: -40 }, {
        y: 40, ease: 'none',
        scrollTrigger: {
          trigger: el.parentElement || el,
          start: 'top bottom', end: 'bottom top', scrub: 1.5,
        },
      });
    });
  }

  // ─── MAGNETIC CTAs ─────────────────────────────────────────────────
  function setupMagnetic(gsap) {
    document.querySelectorAll('.btn-primary, .btn-discord').forEach(btn => {
      if (btn.dataset.owMagBound === '1') return;
      btn.dataset.owMagBound = '1';
      const move = (e) => {
        const r = btn.getBoundingClientRect();
        gsap.to(btn, {
          x: ((e.clientX - r.left) / r.width - 0.5) * 12,
          y: ((e.clientY - r.top) / r.height - 0.5) * 12,
          duration: 0.3, ease: 'power2.out',
        });
      };
      const reset = () => gsap.to(btn, { x: 0, y: 0, duration: 0.5, ease: 'elastic.out(1, 0.5)' });
      btn.addEventListener('mousemove', move);
      btn.addEventListener('mouseleave', reset);
    });
  }

  // ─── NUMBER COUNT-UP ───────────────────────────────────────────────
  function setupCountUps(gsap, ScrollTrigger) {
    document.querySelectorAll('.mono').forEach(el => {
      const raw = (el.textContent || '').trim();
      const m = raw.match(/^(\d[\d,.]*)([+kKmM]?)$/);
      if (!m) return;
      const targetStr = m[1].replace(/,/g, '');
      const suffix = m[2] || '';
      const target = parseFloat(targetStr);
      if (!Number.isFinite(target) || target <= 0) return;
      const obj = { v: 0 };
      ScrollTrigger.create({
        trigger: el, start: 'top 85%', once: true,
        onEnter: () => {
          gsap.to(obj, {
            v: target, duration: 1.6, ease: 'power2.out',
            onUpdate: () => { el.textContent = Math.round(obj.v).toLocaleString('es') + suffix; },
            onComplete: () => { el.textContent = raw; },
          });
        },
      });
    });
  }

  // ─── GAMES SECTION POLISH (V70 — NO horizontal pin, just polish) ────
  // V70: user feedback — "esta parte esta brusca al hacer scroll".
  // The horizontal pin caused the page to "stick" until horizontal scroll
  // completed, then release abruptly — felt broken with only 2 cards.
  // Replaced with: (1) gentle parallax ken-burns on card backgrounds,
  // (2) hover lift + glow, (3) badge pulse, (4) sequential reveal on
  // entrance. Cards keep their original 2-col grid layout.
  function setupHorizontalGames(gsap, ScrollTrigger) {
    let target = null;
    document.querySelectorAll('section').forEach(sec => {
      if (target) return;
      const eb = sec.querySelector('.eyebrow');
      if (eb && /Juegos|Games|Jogos/i.test(eb.textContent || '')) target = sec;
    });
    if (!target) return;

    const cards = target.querySelectorAll('.card, article');
    cards.forEach((card, i) => {
      // (1) Sequential reveal as user scrolls into the section
      gsap.fromTo(card,
        { opacity: 0, y: 50, scale: 0.95 },
        {
          opacity: 1, y: 0, scale: 1,
          duration: 1.0, ease: 'expo.out',
          scrollTrigger: { trigger: target, start: 'top 75%', once: true },
          delay: i * 0.15,
        }
      );

      // (2) Ken-burns slow zoom on the inner background image as user scrolls
      // through the section. Subtle (1 → 1.08 over the section's scroll range).
      const bgEl = card.querySelector('img, .card-bg, .bg-image');
      if (bgEl) {
        gsap.fromTo(bgEl,
          { scale: 1 },
          {
            scale: 1.08, ease: 'none',
            scrollTrigger: { trigger: card, start: 'top bottom', end: 'bottom top', scrub: 1.5 },
          }
        );
      }

      // (3) Hover lift + accent glow (no transform conflicts with reveal)
      card.addEventListener('mouseenter', () => {
        gsap.to(card, { y: -8, boxShadow: '0 30px 80px -20px rgba(91,140,255,0.5), 0 0 0 1px var(--accent)', duration: 0.45, ease: 'expo.out' });
      });
      card.addEventListener('mouseleave', () => {
        gsap.to(card, { y: 0, boxShadow: '', duration: 0.6, ease: 'expo.out' });
      });
    });
  }

  // ─── EMPTY-STATE PULSE (Élite ranking + similar) ───────────────────
  // User said élite del ranking se ve "basico". Adds gentle breathe to
  // the icon inside .ow-empty (or similar empty placeholders).
  function setupEmptyStatePulse(gsap, ScrollTrigger) {
    const emptyIcons = document.querySelectorAll('.ow-empty-icon, .ow-skel-icon, [data-empty-icon]');
    emptyIcons.forEach(el => {
      gsap.to(el, {
        scale: 1.08,
        duration: 1.6,
        ease: 'sine.inOut',
        repeat: -1,
        yoyo: true,
      });
    });
  }
})();
