// visualfx.jsx - camada de efeitos visuais editoriais (compatível com o tema cream)
// Inclui:
//   - <ScrollProgress/>      barra fina de progresso de scroll no topo
//   - <AmbientOrbs/>          orbs em gradiente animados no background do hero
//   - <ParallaxLayer/>        camada parallax leve (mouse + scroll)
//   - <MagneticCTA/>          wrapper que aplica magnetismo aos botões CTA
//   - <CursorAura/>           glow sutil seguindo o mouse (desativa em touch)
//   - aplica .tilt-card a .svc-card / .case-card / .insight-card / .clients-item
//   - aplica reveal stagger automático em headings de seção
//
// IMPORTANT: não substitui nada existente. Apenas adiciona.

const { useEffect: useEffectVfx, useRef: useRefVfx, useState: useStateVfx } = React;

// ---------- Scroll progress bar ----------
const ScrollProgress = () => {
  const ref = useRefVfx(null);
  useEffectVfx(() => {
    const onScroll = () => {
      const h = document.documentElement;
      const max = h.scrollHeight - h.clientHeight;
      const p = max > 0 ? (h.scrollTop || document.body.scrollTop) / max : 0;
      if (ref.current) ref.current.style.transform = `scaleX(${p})`;
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    return () => { window.removeEventListener('scroll', onScroll); window.removeEventListener('resize', onScroll); };
  }, []);
  return <div className="vfx-progress" aria-hidden="true"><div ref={ref} className="vfx-progress-bar"/></div>;
};

// ---------- Ambient gradient orbs (atrás do hero) ----------
const AmbientOrbs = () => {
  return (
    <div className="vfx-orbs" aria-hidden="true">
      <div className="orb orb-1"/>
      <div className="orb orb-2"/>
      <div className="orb orb-3"/>
      <div className="vfx-grain"/>
    </div>
  );
};

// ---------- Cursor aura (glow sutil segue o mouse) ----------
const CursorAura = () => {
  const ref = useRefVfx(null);
  useEffectVfx(() => {
    if (matchMedia('(pointer: coarse)').matches) return;
    let tx = -9999, ty = -9999, x = -9999, y = -9999, raf;
    const move = (e) => { tx = e.clientX; ty = e.clientY; };
    const tick = () => {
      x += (tx - x) * 0.12;
      y += (ty - y) * 0.12;
      if (ref.current) ref.current.style.transform = `translate3d(${x}px, ${y}px, 0) translate(-50%, -50%)`;
      raf = requestAnimationFrame(tick);
    };
    window.addEventListener('mousemove', move);
    raf = requestAnimationFrame(tick);
    return () => { cancelAnimationFrame(raf); window.removeEventListener('mousemove', move); };
  }, []);
  return <div ref={ref} className="vfx-cursor-aura" aria-hidden="true"/>;
};

// ---------- Magnetismo SOMENTE no CTA primário do hero ----------
// (aplicar a todos os botões fica brega; reservar para um só elemento de destaque)
const useMagnetic = () => {
  useEffectVfx(() => {
    if (matchMedia('(pointer: coarse)').matches) return;
    const target = document.querySelector('.hero-actions .cta-btn:not(.ghost)');
    if (!target) return;
    const onMove = (e) => {
      const r = target.getBoundingClientRect();
      const mx = e.clientX - (r.left + r.width / 2);
      const my = e.clientY - (r.top + r.height / 2);
      target.style.transform = `translate(${mx * 0.12}px, ${my * 0.16}px)`;
    };
    const onLeave = () => { target.style.transform = ''; };
    target.addEventListener('mousemove', onMove);
    target.addEventListener('mouseleave', onLeave);
    return () => {
      target.removeEventListener('mousemove', onMove);
      target.removeEventListener('mouseleave', onLeave);
      target.style.transform = '';
    };
  }, []);
  return null;
};

// ---------- Tilt 3D removido - fica brega em massa ----------
// Hover states são gerenciados em CSS por seletor (linha gold no top, etc).
const useCardTilt = () => null;

// ---------- Parallax sutil em [data-parallax] ----------
const useParallaxScroll = () => {
  useEffectVfx(() => {
    const els = document.querySelectorAll('[data-parallax]');
    if (!els.length) return;
    let raf;
    const onScroll = () => {
      const sy = window.scrollY;
      els.forEach((el) => {
        const speed = parseFloat(el.dataset.parallax || '0.15');
        const r = el.getBoundingClientRect();
        const center = r.top + r.height / 2 - window.innerHeight / 2;
        el.style.transform = `translate3d(0, ${center * speed * -0.4}px, 0)`;
      });
    };
    onScroll();
    const handler = () => { cancelAnimationFrame(raf); raf = requestAnimationFrame(onScroll); };
    window.addEventListener('scroll', handler, { passive: true });
    window.addEventListener('resize', handler);
    return () => { window.removeEventListener('scroll', handler); window.removeEventListener('resize', handler); cancelAnimationFrame(raf); };
  }, []);
  return null;
};

// ---------- Word reveal removido - o shimmer cintilante competia com o italic do Fraunces ----------
const useWordReveal = () => null;

// ---------- Word reveal in section titles (hover stagger) ----------
// Each <.section-title> has its visible words wrapped in <span class="word">
// with --i index so CSS can stagger them on :hover. Preserves inner spans
// like .em and .thin (recursive walk). Skipped on touch and reduced-motion.
const useWordRevealTitles = () => {
  useEffectVfx(() => {
    if (matchMedia('(pointer: coarse)').matches) return;
    if (matchMedia('(prefers-reduced-motion: reduce)').matches) return;

    const wrapTitle = (title) => {
      // Avoid re-wrapping the same title
      if (title.querySelector('.word')) return;
      let i = 0;
      const wrapNode = (node) => {
        if (node.nodeType === 3) { // TEXT_NODE
          const text = node.textContent;
          if (!text || !text.trim()) return;
          const parts = text.split(/(\s+)/);
          const frag = document.createDocumentFragment();
          parts.forEach((part) => {
            if (/^\s+$/.test(part)) {
              frag.appendChild(document.createTextNode(part));
            } else if (part.length > 0) {
              const span = document.createElement('span');
              span.className = 'word';
              span.style.setProperty('--i', i++);
              span.textContent = part;
              frag.appendChild(span);
            }
          });
          node.parentNode.replaceChild(frag, node);
        } else if (node.nodeType === 1 && !node.classList.contains('word')) {
          // ELEMENT_NODE - recurse, preserving inner <span class="em"> etc.
          Array.from(node.childNodes).forEach(wrapNode);
        }
      };
      Array.from(title.childNodes).forEach(wrapNode);
      title.style.setProperty('--word-count', i);
    };

    const wrapAll = () => {
      document.querySelectorAll('.section-title').forEach(wrapTitle);
    };

    // Initial wrap (deferred so React has time to render text)
    requestAnimationFrame(wrapAll);

    // Re-wrap on DOM changes (lang switch replaces text nodes)
    const main = document.querySelector('main');
    if (!main) return;
    let pending = false;
    const obs = new MutationObserver(() => {
      if (pending) return;
      pending = true;
      requestAnimationFrame(() => {
        pending = false;
        wrapAll();
      });
    });
    obs.observe(main, { childList: true, subtree: true, characterData: true });
    return () => obs.disconnect();
  }, []);
  return null;
};

// ---------- Wrapper único ----------
const VisualFXLayer = () => {
  useMagnetic();
  useCardTilt();
  useParallaxScroll();
  useWordReveal();
  useWordRevealTitles();
  // Re-run effects when DOM changes (lang switch)
  const [, setTick] = useStateVfx(0);
  useEffectVfx(() => {
    const obs = new MutationObserver(() => setTick(t => t + 1));
    obs.observe(document.body, { childList: true, subtree: true });
    const id = setTimeout(() => obs.disconnect(), 5000); // só reativa nos primeiros 5s
    return () => { obs.disconnect(); clearTimeout(id); };
  }, []);
  return (
    <>
      <ScrollProgress/>
      <CursorAura/>
    </>
  );
};

window.VisualFXLayer = VisualFXLayer;
window.AmbientOrbs = AmbientOrbs;
