/* =====================================================================
   ONAPB — Kinetic FX
   Capa de interacciones del frontend.
   Vanilla JS, sin dependencias. Cargar al final de <body> con defer.
   ===================================================================== */
(function () {
    'use strict';

    var prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    var hasFinePointer = window.matchMedia('(hover: hover) and (pointer: fine)').matches;
    var isTouch = !hasFinePointer || ('ontouchstart' in window) || (navigator.maxTouchPoints > 0);

    function ready(fn) {
        if (document.readyState !== 'loading') fn();
        else document.addEventListener('DOMContentLoaded', fn);
    }

    /* ─────────────────────────────────────────────────────────────────
       1. Reveal on scroll (.kfx-reveal, [data-stagger], .kfx-section-tag)
       ───────────────────────────────────────────────────────────────── */
    function initReveal() {
        if (!('IntersectionObserver' in window)) {
            document.querySelectorAll('.kfx-reveal, [data-stagger], .kfx-section-tag, .hero-title, .kinetic-reveal-text, .kinetic-highlight')
                .forEach(function (el) { el.classList.add('is-in'); });
            return;
        }
        var io = new IntersectionObserver(function (entries) {
            entries.forEach(function (e) {
                if (e.isIntersecting) {
                    e.target.classList.add('is-in');
                    io.unobserve(e.target);
                }
            });
        }, { threshold: 0.12, rootMargin: '0px 0px -60px 0px' });

        document.querySelectorAll('.kfx-reveal, [data-stagger], .kfx-section-tag, .hero-title, .kinetic-reveal-text, .kinetic-highlight')
            .forEach(function (el) { io.observe(el); });
    }

    /* ─────────────────────────────────────────────────────────────────
       2. Word splitter para reveal de títulos (hero-title, kinetic-reveal-text)
       ───────────────────────────────────────────────────────────────── */
    function splitWords() {
        document.querySelectorAll('.hero-title:not([data-split]), .kinetic-reveal-text:not([data-split])').forEach(function (el) {
            if (el.children.length > 0 && el.querySelector('.word')) return;
            var text = el.textContent.trim();
            if (!text) return;
            var words = text.split(/\s+/);
            el.innerHTML = words.map(function (w) {
                return '<span class="word"><span>' + w + '</span></span>';
            }).join(' ');
            el.setAttribute('data-split', 'true');
        });
    }

    /* ─────────────────────────────────────────────────────────────────
       3. Reading progress bar (top)
       ───────────────────────────────────────────────────────────────── */
    function initReadingBar() {
        if (prefersReduced) return;
        var bar = document.getElementById('kinetic-reading-bar');
        if (!bar) {
            bar = document.createElement('div');
            bar.id = 'kinetic-reading-bar';
            document.body.appendChild(bar);
        }
        var ticking = false;
        function update() {
            var scrollTop = window.scrollY || document.documentElement.scrollTop;
            var docHeight = document.documentElement.scrollHeight - window.innerHeight;
            var pct = docHeight > 0 ? Math.min(100, (scrollTop / docHeight) * 100) : 0;
            bar.style.width = pct + '%';
            ticking = false;
        }
        window.addEventListener('scroll', function () {
            if (!ticking) {
                window.requestAnimationFrame(update);
                ticking = true;
            }
        }, { passive: true });
        update();
    }

    /* ─────────────────────────────────────────────────────────────────
       4. Navbar scroll state
       ───────────────────────────────────────────────────────────────── */
    function initNavbarScroll() {
        var nav = document.querySelector('.custom-navbar');
        if (!nav) return;
        function update() {
            if (window.scrollY > 30) nav.classList.add('is-scrolled');
            else nav.classList.remove('is-scrolled');
        }
        window.addEventListener('scroll', update, { passive: true });
        update();
    }

    /* ─────────────────────────────────────────────────────────────────
       5. Spotlight para .kinetic-card y .kfx-img-spotlight
       ───────────────────────────────────────────────────────────────── */
    function initSpotlight() {
        if (isTouch) return;
        var els = document.querySelectorAll('.kinetic-card, .kfx-img-spotlight');
        els.forEach(function (el) {
            el.addEventListener('mousemove', function (e) {
                var rect = el.getBoundingClientRect();
                var x = ((e.clientX - rect.left) / rect.width) * 100;
                var y = ((e.clientY - rect.top) / rect.height) * 100;
                el.style.setProperty('--mx', x + '%');
                el.style.setProperty('--my', y + '%');
            });
        });
    }

    /* ─────────────────────────────────────────────────────────────────
       6. Tilt 3D (data-tilt)
       ───────────────────────────────────────────────────────────────── */
    function initTilt() {
        if (isTouch || prefersReduced) return;
        document.querySelectorAll('[data-tilt]').forEach(function (el) {
            var max = parseFloat(el.getAttribute('data-tilt-max') || '8');
            el.addEventListener('mousemove', function (e) {
                var rect = el.getBoundingClientRect();
                var x = (e.clientX - rect.left) / rect.width - 0.5;
                var y = (e.clientY - rect.top) / rect.height - 0.5;
                el.classList.add('is-tilting');
                el.style.setProperty('--ry', (x * max) + 'deg');
                el.style.setProperty('--rx', (-y * max) + 'deg');
            });
            el.addEventListener('mouseleave', function () {
                el.classList.remove('is-tilting');
                el.style.setProperty('--rx', '0deg');
                el.style.setProperty('--ry', '0deg');
            });
        });
    }

    /* ─────────────────────────────────────────────────────────────────
       7. Magnetic buttons (data-magnetic)
       ───────────────────────────────────────────────────────────────── */
    function initMagnetic() {
        if (isTouch || prefersReduced) return;
        document.querySelectorAll('[data-magnetic]').forEach(function (el) {
            var strength = parseFloat(el.getAttribute('data-magnetic-strength') || '0.25');
            el.addEventListener('mousemove', function (e) {
                var rect = el.getBoundingClientRect();
                var x = e.clientX - rect.left - rect.width / 2;
                var y = e.clientY - rect.top - rect.height / 2;
                el.style.transform = 'translate(' + (x * strength) + 'px, ' + (y * strength) + 'px)';
            });
            el.addEventListener('mouseleave', function () {
                el.style.transform = '';
            });
        });
    }

    /* ─────────────────────────────────────────────────────────────────
       8. Ripple en clicks (cualquier .btn, .btn-kinetic-primary)
       ───────────────────────────────────────────────────────────────── */
    function initRipple() {
        document.addEventListener('click', function (e) {
            var btn = e.target.closest('.btn, .btn-kinetic-primary, .btn-admin-primary, .sidebar-link');
            if (!btn || btn.classList.contains('no-ripple')) return;
            var rect = btn.getBoundingClientRect();
            var size = Math.max(rect.width, rect.height);
            var wave = document.createElement('span');
            wave.className = 'kinetic-ripple-wave';
            wave.style.width = wave.style.height = size + 'px';
            wave.style.left = (e.clientX - rect.left) + 'px';
            wave.style.top = (e.clientY - rect.top) + 'px';
            // Posición relativa para contener el ripple
            var pos = window.getComputedStyle(btn).position;
            if (pos === 'static') btn.style.position = 'relative';
            btn.style.overflow = 'hidden';
            btn.appendChild(wave);
            setTimeout(function () { wave.remove(); }, 650);
        });
    }

    /* ─────────────────────────────────────────────────────────────────
       9. Counter animado (.kfx-counter con data-target)
       ───────────────────────────────────────────────────────────────── */
    function initCounters() {
        if (!('IntersectionObserver' in window)) return;
        var counters = document.querySelectorAll('.kfx-counter[data-target]');
        if (!counters.length) return;
        var io = new IntersectionObserver(function (entries) {
            entries.forEach(function (entry) {
                if (!entry.isIntersecting) return;
                var el = entry.target;
                var target = parseFloat(el.getAttribute('data-target')) || 0;
                var duration = parseInt(el.getAttribute('data-duration') || '1400', 10);
                var decimals = parseInt(el.getAttribute('data-decimals') || '0', 10);
                var prefix = el.getAttribute('data-prefix') || '';
                var suffix = el.getAttribute('data-suffix') || '';
                var start = 0;
                var startTime = null;
                if (prefersReduced) {
                    el.textContent = prefix + target.toFixed(decimals) + suffix;
                    io.unobserve(el);
                    return;
                }
                function tick(ts) {
                    if (!startTime) startTime = ts;
                    var progress = Math.min(1, (ts - startTime) / duration);
                    var eased = 1 - Math.pow(1 - progress, 3); // easeOutCubic
                    var current = start + (target - start) * eased;
                    el.textContent = prefix + current.toFixed(decimals) + suffix;
                    if (progress < 1) requestAnimationFrame(tick);
                }
                requestAnimationFrame(tick);
                io.unobserve(el);
            });
        }, { threshold: 0.4 });
        counters.forEach(function (c) { io.observe(c); });
    }

    /* ─────────────────────────────────────────────────────────────────
       10. Parallax suave (data-parallax="speed")
       ───────────────────────────────────────────────────────────────── */
    function initParallax() {
        if (prefersReduced) return;
        var els = Array.prototype.slice.call(document.querySelectorAll('[data-parallax]'));
        if (!els.length) return;
        var ticking = false;
        function update() {
            var vh = window.innerHeight;
            els.forEach(function (el) {
                var rect = el.getBoundingClientRect();
                if (rect.bottom < 0 || rect.top > vh) return;
                var speed = parseFloat(el.getAttribute('data-parallax')) || 0.2;
                var offset = (rect.top - vh / 2) * speed * -1;
                el.style.transform = 'translate3d(0, ' + offset.toFixed(1) + 'px, 0)';
            });
            ticking = false;
        }
        window.addEventListener('scroll', function () {
            if (!ticking) {
                requestAnimationFrame(update);
                ticking = true;
            }
        }, { passive: true });
        update();
    }

    /* ─────────────────────────────────────────────────────────────────
       11. Marquee duplicador (.kfx-marquee con un solo track)
       ───────────────────────────────────────────────────────────────── */
    function initMarquee() {
        document.querySelectorAll('.kfx-marquee').forEach(function (el) {
            var track = el.querySelector('.kfx-marquee__track');
            if (!track || track.dataset.cloned === '1') return;
            track.dataset.cloned = '1';
            track.innerHTML += track.innerHTML; // duplicar para loop seamless
        });
    }

    /* ─────────────────────────────────────────────────────────────────
       12. Cursor personalizado (sólo desktop hover-fino)
       ───────────────────────────────────────────────────────────────── */
    function initCustomCursor() {
        if (!hasFinePointer || isTouch || prefersReduced) return;
        if (document.querySelector('.kinetic-cursor-dot')) return;

        var dot = document.createElement('div');
        var ring = document.createElement('div');
        dot.className = 'kinetic-cursor-dot';
        ring.className = 'kinetic-cursor-ring';
        document.body.appendChild(dot);
        document.body.appendChild(ring);
        document.body.classList.add('kinetic-cursor-on');

        var mx = window.innerWidth / 2, my = window.innerHeight / 2;
        var rx = mx, ry = my;

        document.addEventListener('mousemove', function (e) {
            mx = e.clientX; my = e.clientY;
            dot.style.transform = 'translate(' + mx + 'px, ' + my + 'px) translate(-50%, -50%)';
        }, { passive: true });

        function loop() {
            rx += (mx - rx) * 0.18;
            ry += (my - ry) * 0.18;
            ring.style.transform = 'translate(' + rx + 'px, ' + ry + 'px) translate(-50%, -50%)';
            requestAnimationFrame(loop);
        }
        loop();

        // Hover en interactivos
        var hoverSel = 'a, button, .btn, .kinetic-card, [role="button"], [data-tilt], [data-magnetic], .nav-link, input[type="submit"]';
        document.addEventListener('mouseover', function (e) {
            if (e.target.closest(hoverSel)) {
                ring.classList.add('is-hover');
                dot.classList.add('is-hover');
            }
        });
        document.addEventListener('mouseout', function (e) {
            if (e.target.closest(hoverSel)) {
                ring.classList.remove('is-hover');
                dot.classList.remove('is-hover');
            }
        });
        document.addEventListener('mouseleave', function () {
            ring.style.opacity = '0';
            dot.style.opacity = '0';
        });
        document.addEventListener('mouseenter', function () {
            ring.style.opacity = '1';
            dot.style.opacity = '1';
        });
    }

    /* ─────────────────────────────────────────────────────────────────
       13. Auto-aplicar reveal a tarjetas / encabezados (best-effort)
       ───────────────────────────────────────────────────────────────── */
    function autoTagReveal() {
        // Tarjetas comunes en home/eventos
        document.querySelectorAll('.kinetic-card:not(.kfx-reveal)').forEach(function (el) {
            el.classList.add('kfx-reveal');
            if (!el.hasAttribute('data-fx')) el.setAttribute('data-fx', 'up');
        });

        // Display headings (h1.display-* / h2.display-*)
        document.querySelectorAll('h1.display-1, h1.display-2, h1.display-3, h1.display-4, h2.display-3, h2.display-4, h2.display-5')
            .forEach(function (el) {
                if (!el.classList.contains('kfx-reveal') && !el.classList.contains('hero-title')) {
                    el.classList.add('kfx-reveal');
                    el.setAttribute('data-fx', 'up');
                }
            });
    }

    /* ─────────────────────────────────────────────────────────────────
       14. Smooth anchor scroll
       ───────────────────────────────────────────────────────────────── */
    function initAnchorSmooth() {
        document.addEventListener('click', function (e) {
            var a = e.target.closest('a[href^="#"]');
            if (!a) return;
            var href = a.getAttribute('href');
            if (!href || href === '#' || href.length < 2) return;
            var target = document.querySelector(href);
            if (!target) return;
            e.preventDefault();
            target.scrollIntoView({ behavior: prefersReduced ? 'auto' : 'smooth', block: 'start' });
        });
    }

    /* ─────────────────────────────────────────────────────────────────
       15. SweetAlert2 patcher (a prueba de cache)
       Detecta cuando aparece un .swal2-popup y fuerza inline styles en
       los botones para garantizar fondo rojo en confirm y gris en cancel,
       sin importar el orden/cache del CSS o el confirmButtonColor del JS.
       ───────────────────────────────────────────────────────────────── */
    function initSwalPatcher() {
        if (!('MutationObserver' in window)) return;

        var BRAND_RED = '#c20000';
        var BRAND_RED_DEEP = '#8a0000';
        var BRAND_GRAY = '#6c757d';

        // Inyectar reglas críticas como <style> en runtime para evitar
        // problemas de caché del archivo .css (LiteSpeed/Cloudflare).
        if (!document.getElementById('kfx-swal-runtime-style')) {
            var s = document.createElement('style');
            s.id = 'kfx-swal-runtime-style';
            s.textContent = [
                /* Selección visible dentro del modal SweetAlert (rojo + texto blanco). */
                '.swal2-popup ::selection,.swal2-popup *::selection{background-color:' + BRAND_RED + ' !important;color:#fff !important;}',
                '.swal2-popup ::-moz-selection,.swal2-popup *::-moz-selection{background-color:' + BRAND_RED + ' !important;color:#fff !important;}',
                /* Selección global (failsafe por si el CSS principal cachea viejo). */
                '::selection{background-color:' + BRAND_RED + ' !important;color:#fff !important;}',
                '::-moz-selection{background-color:' + BRAND_RED + ' !important;color:#fff !important;}',
                /* Botones de SweetAlert (failsafe). */
                'body .swal2-popup .swal2-actions .swal2-styled.swal2-confirm{' +
                    'background-color:' + BRAND_RED + ' !important;' +
                    'background-image:linear-gradient(135deg,' + BRAND_RED + ',' + BRAND_RED_DEEP + ') !important;' +
                    'color:#fff !important;border:none !important;' +
                '}',
                'body .swal2-popup .swal2-actions .swal2-styled.swal2-cancel{' +
                    'background-color:' + BRAND_GRAY + ' !important;' +
                    'background-image:none !important;' +
                    'color:#fff !important;border:none !important;' +
                '}'
            ].join('\n');
            document.head.appendChild(s);
        }

        function styleConfirm(btn) {
            if (!btn) return;
            btn.style.setProperty('background-color', BRAND_RED, 'important');
            btn.style.setProperty('background-image',
                'linear-gradient(135deg, ' + BRAND_RED + ', ' + BRAND_RED_DEEP + ')', 'important');
            btn.style.setProperty('color', '#ffffff', 'important');
            btn.style.setProperty('border', 'none', 'important');
            btn.style.setProperty('text-shadow', 'none', 'important');
            btn.style.setProperty('font-weight', '700', 'important');
            btn.style.setProperty('text-transform', 'uppercase', 'important');
            btn.style.setProperty('letter-spacing', '0.08em', 'important');
        }
        function styleCancel(btn) {
            if (!btn) return;
            btn.style.setProperty('background-color', BRAND_GRAY, 'important');
            btn.style.setProperty('background-image', 'none', 'important');
            btn.style.setProperty('color', '#ffffff', 'important');
            btn.style.setProperty('border', 'none', 'important');
            btn.style.setProperty('font-weight', '700', 'important');
            btn.style.setProperty('text-transform', 'uppercase', 'important');
            btn.style.setProperty('letter-spacing', '0.08em', 'important');
        }
        function styleDeny(btn) {
            if (!btn) return;
            btn.style.setProperty('background-color', '#b91c1c', 'important');
            btn.style.setProperty('color', '#ffffff', 'important');
        }

        function patch(popup) {
            if (!popup || popup.dataset.kfxPatched === '1') return;
            popup.dataset.kfxPatched = '1';
            styleConfirm(popup.querySelector('.swal2-confirm'));
            styleCancel(popup.querySelector('.swal2-cancel'));
            styleDeny(popup.querySelector('.swal2-deny'));
        }

        // Patch popups que ya estén en el DOM al cargar
        document.querySelectorAll('.swal2-popup').forEach(patch);

        // Observa nuevos popups (SWAL los agrega/quita dinámicamente)
        var obs = new MutationObserver(function (mutations) {
            mutations.forEach(function (m) {
                m.addedNodes && m.addedNodes.forEach(function (n) {
                    if (!(n instanceof HTMLElement)) return;
                    if (n.classList && n.classList.contains('swal2-popup')) {
                        patch(n);
                    } else {
                        // Por si el contenedor agrega un wrapper antes del popup
                        var inner = n.querySelector && n.querySelector('.swal2-popup');
                        if (inner) patch(inner);
                    }
                });
            });
        });
        obs.observe(document.body, { childList: true, subtree: true });
    }

    /* ─────────────────────────────────────────────────────────────────
       Init
       ───────────────────────────────────────────────────────────────── */
    ready(function () {
        try { splitWords(); } catch (e) { console.warn('kinetic-fx splitWords:', e); }
        try { autoTagReveal(); } catch (e) { console.warn('kinetic-fx autoTagReveal:', e); }
        try { initReveal(); } catch (e) { console.warn('kinetic-fx reveal:', e); }
        try { initReadingBar(); } catch (e) { console.warn('kinetic-fx readingBar:', e); }
        try { initNavbarScroll(); } catch (e) { console.warn('kinetic-fx navbarScroll:', e); }
        try { initSpotlight(); } catch (e) { console.warn('kinetic-fx spotlight:', e); }
        try { initTilt(); } catch (e) { console.warn('kinetic-fx tilt:', e); }
        try { initMagnetic(); } catch (e) { console.warn('kinetic-fx magnetic:', e); }
        try { initRipple(); } catch (e) { console.warn('kinetic-fx ripple:', e); }
        try { initCounters(); } catch (e) { console.warn('kinetic-fx counters:', e); }
        try { initParallax(); } catch (e) { console.warn('kinetic-fx parallax:', e); }
        try { initMarquee(); } catch (e) { console.warn('kinetic-fx marquee:', e); }
        try { initCustomCursor(); } catch (e) { console.warn('kinetic-fx cursor:', e); }
        try { initAnchorSmooth(); } catch (e) { console.warn('kinetic-fx anchor:', e); }
        try { initSwalPatcher(); } catch (e) { console.warn('kinetic-fx swalPatcher:', e); }
    });

    // API pública mínima (por si una vista necesita re-inicializar tras AJAX)
    window.KineticFX = {
        rescan: function () {
            splitWords();
            autoTagReveal();
            initReveal();
            initSpotlight();
            initTilt();
            initMagnetic();
            initCounters();
            initMarquee();
        }
    };
})();
