/* Blackstock — runtime de animaciones premium (sin libs).
 *
 * Apple/Linear-feel:
 *   - Smooth scroll global con ease-out.
 *   - Scroll reveal: cualquier elemento con `data-bs-reveal` aparece al
 *     entrar en viewport (fade + translate sutil).
 *   - Counters: cualquier `data-bs-count="120"` se anima de 0 a N al
 *     entrar en viewport.
 *   - Navbar reactivo: cualquier `[data-bs-navbar]` recibe la clase
 *     `is-scrolled` cuando scrollY > 24px.
 *   - Smooth anchors: clicks en links `[href^="#"]` hacen scroll suave.
 *   - Click feedback: cualquier `.bs-btn` lanza una micro-onda al pulsar.
 *
 * Sin dependencias, IntersectionObserver nativo, prefers-reduced-motion
 * respetado. Todo idempotente: re-ejecutar no rompe nada.
 */

(function () {
  if (window.__bsAnimationsRuntimeInstalled) return;
  window.__bsAnimationsRuntimeInstalled = true;

  const reduceMotion = window.matchMedia
    && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

  // ── Scroll reveal ───────────────────────────────────────────────
  // Auto-añadir data-bs-reveal a tarjetas comunes (cards, secciones)
  // sin tocar el código existente. El observer aplica .is-visible
  // y CSS hace el resto.
  const revealObserver = new IntersectionObserver(
    (entries) => {
      for (const entry of entries) {
        if (entry.isIntersecting) {
          entry.target.classList.add('bs-reveal-visible');
          revealObserver.unobserve(entry.target);
        }
      }
    },
    { threshold: 0.12, rootMargin: '0px 0px -40px 0px' }
  );

  function watchReveal() {
    if (reduceMotion) return;
    document.querySelectorAll('[data-bs-reveal]').forEach((el) => {
      if (!el.classList.contains('bs-reveal-visible')) {
        el.classList.add('bs-reveal-init');
        revealObserver.observe(el);
      }
    });
  }

  // ── Counters animados ───────────────────────────────────────────
  function animateCounter(el) {
    const target = Number(el.getAttribute('data-bs-count')) || 0;
    const duration = Number(el.getAttribute('data-bs-count-duration')) || 1400;
    const prefix = el.getAttribute('data-bs-count-prefix') || '';
    const suffix = el.getAttribute('data-bs-count-suffix') || '';
    const decimals = Number(el.getAttribute('data-bs-count-decimals')) || 0;
    if (reduceMotion) {
      el.textContent = prefix + target.toFixed(decimals) + suffix;
      return;
    }
    const startTs = performance.now();
    const tick = (now) => {
      const t = Math.min(1, (now - startTs) / duration);
      // ease-out cubic
      const eased = 1 - Math.pow(1 - t, 3);
      const value = target * eased;
      el.textContent = prefix + value.toFixed(decimals) + suffix;
      if (t < 1) requestAnimationFrame(tick);
      else el.textContent = prefix + target.toFixed(decimals) + suffix;
    };
    requestAnimationFrame(tick);
  }
  const counterObserver = new IntersectionObserver(
    (entries) => {
      for (const entry of entries) {
        if (entry.isIntersecting) {
          animateCounter(entry.target);
          counterObserver.unobserve(entry.target);
        }
      }
    },
    { threshold: 0.45 }
  );
  function watchCounters() {
    document.querySelectorAll('[data-bs-count]').forEach((el) => {
      if (!el.dataset.bsCountInit) {
        el.dataset.bsCountInit = '1';
        el.textContent = '0';
        counterObserver.observe(el);
      }
    });
  }

  // ── Navbar reactivo ─────────────────────────────────────────────
  let lastScrolled = false;
  function onScroll() {
    const isScrolled = window.scrollY > 24;
    if (isScrolled !== lastScrolled) {
      lastScrolled = isScrolled;
      document.querySelectorAll('[data-bs-navbar]').forEach((el) => {
        el.classList.toggle('is-scrolled', isScrolled);
      });
      document.body.classList.toggle('bs-scrolled', isScrolled);
    }
  }
  window.addEventListener('scroll', onScroll, { passive: true });
  onScroll();

  // ── Smooth anchors ──────────────────────────────────────────────
  document.addEventListener('click', (e) => {
    const link = e.target?.closest?.('a[href^="#"]');
    if (!link) return;
    const href = link.getAttribute('href');
    if (!href || href === '#' || href.length < 2) return;
    const target = document.querySelector(href);
    if (!target) return;
    e.preventDefault();
    if (reduceMotion) {
      target.scrollIntoView();
    } else {
      target.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }
  });

  // ── Click feedback en botones ───────────────────────────────────
  // Añade un destello sutil al pulsar cualquier .bs-btn (sin romper
  // el comportamiento de los botones existentes).
  document.addEventListener(
    'pointerdown',
    (e) => {
      if (reduceMotion) return;
      const btn = e.target?.closest?.('.bs-btn');
      if (!btn || btn.disabled) return;
      const rect = btn.getBoundingClientRect();
      const ripple = document.createElement('span');
      ripple.className = 'bs-ripple';
      const size = Math.max(rect.width, rect.height) * 1.4;
      ripple.style.width = ripple.style.height = `${size}px`;
      ripple.style.left = `${e.clientX - rect.left - size / 2}px`;
      ripple.style.top = `${e.clientY - rect.top - size / 2}px`;
      btn.appendChild(ripple);
      setTimeout(() => ripple.remove(), 700);
    },
    { passive: true }
  );

  // ── Anti-doble-click sobre botones de submit/CTA ────────────────
  // Solo si se marca explícitamente con data-bs-once. Evita doble
  // submit en formularios sin que rompamos botones normales.
  document.addEventListener('click', (e) => {
    const btn = e.target?.closest?.('button[data-bs-once]');
    if (!btn || btn.disabled) return;
    btn.disabled = true;
    btn.classList.add('bs-loading');
    setTimeout(() => {
      btn.disabled = false;
      btn.classList.remove('bs-loading');
    }, 1800);
  });

  // ── Auto-aplicar data-bs-reveal a secciones/cards comunes ──────
  // Heurística suave: cualquier <section> directa y .bs-card no
  // marcadas. El user puede des-marcar con data-bs-no-reveal.
  function autoMarkReveal() {
    if (reduceMotion) return;
    const candidates = document.querySelectorAll(
      'section, .bs-card, .bs-pricing-card, [data-pricing-card]'
    );
    candidates.forEach((el) => {
      if (
        el.hasAttribute('data-bs-reveal')
        || el.hasAttribute('data-bs-no-reveal')
        || el.closest('[data-bs-no-reveal]')
      ) return;
      el.setAttribute('data-bs-reveal', '');
    });
  }

  // Ejecuta al cargar y observa el DOM por si los componentes React
  // se montan después (Babel runtime es lento).
  function refreshAll() {
    autoMarkReveal();
    watchReveal();
    watchCounters();
  }
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', refreshAll);
  } else {
    refreshAll();
  }
  // Re-aplica cada vez que el DOM cambia (React monta tras Babel)
  const mo = new MutationObserver((muts) => {
    let added = false;
    for (const m of muts) {
      if (m.addedNodes && m.addedNodes.length) { added = true; break; }
    }
    if (added) refreshAll();
  });
  mo.observe(document.body, { childList: true, subtree: true });

  // Smooth scroll global vía CSS — fallback si el browser no aplica.
  document.documentElement.style.scrollBehavior = reduceMotion ? 'auto' : 'smooth';

  window.bsRefreshAnimations = refreshAll;
})();
