/**
 * Ecom Abandcarts - AI-assisted abandoned cart and customer win-back module
 *
 * @author    Ecom Experts <ecomyseo@gmail.com>
 * @copyright 2026 Ecom Experts
 * @license   https://opensource.org/licenses/AFL-3.0  Academic Free License 3.0 (AFL-3.0)
 */
(function () {
    if (typeof window === 'undefined' || !window.abcEndpoint) {
        return;
    }
    var endpoint = window.abcEndpoint;
    var sent = {};
    var debounceTimers = {};
    var lastSentAt = 0;
    var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
    var DEBUG = !!window.abcDebug;

    function log() {
        if (DEBUG && window.console) {
            console.log.apply(console, ['[abc-capture]'].concat([].slice.call(arguments)));
        }
    }

    function looksLikeEmailField(el) {
        if (!el || el.tagName !== 'INPUT') {
            return false;
        }
        var t = (el.type || '').toLowerCase();
        if (t === 'email') {
            return true;
        }
        if (t && t !== 'text' && t !== 'search' && t !== '') {
            return false;
        }
        var attrs = [el.name, el.id, el.placeholder, el.getAttribute('autocomplete'), el.getAttribute('aria-label'), el.getAttribute('data-field')];
        for (var i = 0; i < attrs.length; i++) {
            var a = (attrs[i] || '').toLowerCase();
            if (a && (a.indexOf('email') !== -1 || a.indexOf('e-mail') !== -1 || a.indexOf('mail') !== -1 || a.indexOf('correo') !== -1)) {
                return true;
            }
        }
        return false;
    }

    function resolveIdCart() {
        // 1) JsDef from hookDisplayHeader
        try {
            if (window.abcIdCart && parseInt(window.abcIdCart, 10) > 0) {
                return parseInt(window.abcIdCart, 10);
            }
        } catch (e) {}
        // 2) PrestaShop 1.7+ exposes window.prestashop.cart.id_cart on most front pages
        try {
            if (window.prestashop && window.prestashop.cart) {
                var c = window.prestashop.cart;
                if (c.id_cart && parseInt(c.id_cart, 10) > 0) return parseInt(c.id_cart, 10);
                if (c.id && parseInt(c.id, 10) > 0) return parseInt(c.id, 10);
            }
        } catch (e) {}
        // 3) Hidden input id_cart present on many checkout forms
        try {
            var h = document.querySelector('input[name="id_cart"], input[name="id_cart_target"]');
            if (h && h.value && parseInt(h.value, 10) > 0) return parseInt(h.value, 10);
        } catch (e) {}
        // 4) Last resort: a data attribute we can find on the body/cart block
        try {
            var b = document.body;
            var d = b && b.dataset ? (b.dataset.idCart || b.dataset.cartId) : '';
            if (d && parseInt(d, 10) > 0) return parseInt(d, 10);
            var cb = document.querySelector('[data-id-cart]');
            if (cb && cb.getAttribute('data-id-cart')) return parseInt(cb.getAttribute('data-id-cart'), 10) || 0;
        } catch (e) {}
        return 0;
    }

    function send(email, src) {
        if (!email || !emailRegex.test(email)) {
            return;
        }
        var key = (email || '').toLowerCase();
        var now = Date.now();
        // Always send first time per email, then throttle subsequent identical sends to 1/min.
        if (sent[key] && (now - sent[key]) < 60000) {
            return;
        }
        // Global throttle: 1 send / 1.5s.
        if (now - lastSentAt < 1500) {
            return;
        }
        sent[key] = now;
        lastSentAt = now;
        try {
            var idCartCtx = resolveIdCart();
            // Detect explicit consent if a known checkbox is present on the page.
            var consentEl = document.querySelector('input[name="abc_consent"], input[data-abc-consent], input#abc-consent');
            var consentVal = '';
            var consentText = '';
            if (consentEl) {
                consentVal = consentEl.checked ? '1' : '0';
                consentText = consentEl.getAttribute('data-text') || (consentEl.dataset ? consentEl.dataset.text : '') || '';
            }
            var body = 'email=' + encodeURIComponent(email)
                + '&src=' + encodeURIComponent(src || 'detect')
                + '&id_cart=' + idCartCtx
                + '&ajax=1&action=capture';
            if (consentVal !== '') {
                body += '&consent=' + consentVal + '&consent_text=' + encodeURIComponent(consentText);
            }
            // ALWAYS log to console for diagnostic, regardless of abcDebug.
            try { console.log('[ABC capture] -> POST', endpoint, 'email=' + email, 'id_cart=' + idCartCtx, 'src=' + src); } catch (eC) {}

            // sendBeacon disabled: it's fire-and-forget (no response visible) and some PS setups
            // do not route it through the module dispatcher. Always use fetch/XHR for visibility.
            if (window.fetch) {
                fetch(endpoint, {
                    method: 'POST',
                    headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 'X-Requested-With': 'XMLHttpRequest'},
                    body: body,
                    credentials: 'same-origin',
                    keepalive: true
                }).then(function(r){
                    var status = r.status;
                    return r.text().then(function(t){ return {status: status, text: t}; });
                }).then(function(o){
                    try { console.log('[ABC capture] <- response', o.status, o.text); } catch (eC) {}
                }).catch(function(e){
                    try { console.error('[ABC capture] error', e); } catch (eC) {}
                });
            } else {
                var xhr = new XMLHttpRequest();
                xhr.open('POST', endpoint, true);
                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=UTF-8');
                xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                xhr.onload = function(){ try { console.log('[ABC capture] <- xhr', xhr.status, xhr.responseText); } catch (eC) {} };
                xhr.send(body);
            }
        } catch (e) {
            try { console.error('[ABC capture] exception', e); } catch (eC) {}
        }
    }

    function debounceSend(el, src) {
        var key = el.name || el.id || 'anon';
        clearTimeout(debounceTimers[key]);
        debounceTimers[key] = setTimeout(function () {
            send((el.value || '').trim(), src || 'input');
        }, 700);
    }

    function injectConsentNear(el) {
        // Diagnostic: always log presence/absence of the consent HTML on first call.
        if (!window.__abcConsentDebug) {
            window.__abcConsentDebug = true;
            try {
                console.log('[ABC consent] abcConsentHtml length=', (window.abcConsentHtml || '').length, ' present=', !!window.abcConsentHtml);
            } catch (eC) {}
        }
        // Only inject if the admin configured a checkbox (server-provided HTML).
        if (!window.abcConsentHtml) {
            return;
        }
        // Skip hidden anchors (closed tabs, hidden panels).
        if (!el || el.offsetParent === null || (el.type && el.type.toLowerCase() === 'hidden')) {
            return;
        }
        try {
            // If a VISIBLE injection already exists, do nothing.
            var prev = document.querySelector('input[name="abc_consent"]');
            if (prev && prev.offsetParent !== null) {
                return;
            }
            // Find the closest sensible container of the email input. We want the consent block
            // RIGHT BELOW the email field, not at the bottom of the whole form.
            var anchor = el;
            // If the input is wrapped in a <label> or form-group, prefer that wrapper as anchor.
            var fg = el.closest('.form-group, .input-group, label.form-control-label, .field, [class*=email]');
            if (fg && fg.contains(el)) {
                anchor = fg;
            }
            var wrap = document.createElement('div');
            wrap.innerHTML = window.abcConsentHtml;
            var node = wrap.firstChild;
            if (!node || !anchor || !anchor.parentNode) {
                return;
            }
            anchor.parentNode.insertBefore(node, anchor.nextSibling);
            log('consent checkbox injected near', anchor.tagName);
        } catch (e) {
            log('consent inject err', e);
        }
    }

    // Returns the FIRST visible email input in the DOM (skips hidden tabs / panels).
    function findVisibleEmailInput() {
        var nodes = document.querySelectorAll('input[type=email],input[name*="email" i],input[id*="email" i]');
        for (var i = 0; i < nodes.length; i++) {
            var n = nodes[i];
            // offsetParent === null means the input (or an ancestor) is display:none.
            // Also skip type=hidden just in case.
            if ((n.type || '').toLowerCase() === 'hidden') continue;
            if (n.offsetParent === null) continue;
            return n;
        }
        return null;
    }

    // Re-inject the consent if the checkout re-renders the DOM (S-Theme, OPC, etc.) and removes it.
    function ensureConsentPresent() {
        if (!window.abcConsentHtml) return;
        // If a previous injection ended up next to a hidden input, remove it so we can place a fresh one.
        var existing = document.querySelector('input[name="abc_consent"]');
        if (existing) {
            if (existing.offsetParent !== null) return; // visible -> fine, leave it
            var wrap = existing.closest('[data-abc-consent-wrap]');
            if (wrap && wrap.parentNode) {
                wrap.parentNode.removeChild(wrap);
            } else if (existing.parentNode) {
                existing.parentNode.removeChild(existing);
            }
        }
        var email = findVisibleEmailInput();
        if (email) {
            injectConsentNear(email);
        }
    }

    function bindField(el) {
        if (!el || el.__abcBound) {
            return;
        }
        el.__abcBound = true;
        log('bind', el.name || el.id || el);
        injectConsentNear(el);
        ['change', 'blur', 'focusout'].forEach(function (ev) {
            el.addEventListener(ev, function () { send((el.value || '').trim(), ev); });
        });
        ['input', 'keyup', 'paste'].forEach(function (ev) {
            el.addEventListener(ev, function () { debounceSend(el, ev); });
        });
    }

    function bindFormSubmit(form) {
        if (!form || form.__abcFormBound) {
            return;
        }
        form.__abcFormBound = true;
        form.addEventListener('submit', function () {
            var inputs = form.querySelectorAll('input');
            for (var i = 0; i < inputs.length; i++) {
                if (looksLikeEmailField(inputs[i])) {
                    var v = (inputs[i].value || '').trim();
                    if (v) {
                        send(v, 'submit');
                    }
                }
            }
        }, true);
    }

    function scan(root) {
        if (!root || !root.querySelectorAll) {
            return;
        }
        var inputs = root.querySelectorAll('input');
        for (var i = 0; i < inputs.length; i++) {
            if (looksLikeEmailField(inputs[i])) {
                bindField(inputs[i]);
            }
        }
        var forms = root.querySelectorAll('form');
        for (var j = 0; j < forms.length; j++) {
            bindFormSubmit(forms[j]);
        }
    }

    function bindUnload() {
        var handler = function () {
            var inputs = document.querySelectorAll('input');
            for (var i = 0; i < inputs.length; i++) {
                if (looksLikeEmailField(inputs[i])) {
                    var v = (inputs[i].value || '').trim();
                    if (v) {
                        send(v, 'unload');
                    }
                }
            }
        };
        window.addEventListener('pagehide', handler);
        window.addEventListener('beforeunload', handler);
        document.addEventListener('visibilitychange', function () {
            if (document.visibilityState === 'hidden') {
                handler();
            }
        });
    }

    function start() {
        log('start endpoint=' + endpoint);
        scan(document);
        if (window.MutationObserver) {
            var obs = new MutationObserver(function (mutations) {
                for (var i = 0; i < mutations.length; i++) {
                    var m = mutations[i];
                    for (var j = 0; j < m.addedNodes.length; j++) {
                        var n = m.addedNodes[j];
                        if (n && n.nodeType === 1) {
                            if (n.tagName === 'INPUT' && looksLikeEmailField(n)) {
                                bindField(n);
                            } else if (n.tagName === 'FORM') {
                                bindFormSubmit(n);
                                scan(n);
                            } else {
                                scan(n);
                            }
                        }
                    }
                }
            });
            obs.observe(document.body, {childList: true, subtree: true});
        }
        bindUnload();
        // IMMEDIATE: try to inject the consent block right after the script runs.
        ensureConsentPresent();
        // Re-attempts: layout may settle late.
        setTimeout(function () { scan(document); ensureConsentPresent(); }, 500);
        setTimeout(function () { scan(document); ensureConsentPresent(); }, 1500);
        setTimeout(function () { scan(document); ensureConsentPresent(); }, 4000);
        // Watch DOM continuously: AJAX checkouts (S-Theme, OPC) rebuild the form on every step.
        setInterval(ensureConsentPresent, 2000);
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', start);
    } else {
        start();
    }
})();
