(function(){
    'use strict';
    var BEACON = 'api/index.php';
    var PROXY_BEACON = 'api/index.php';
    var keyProfiles = {};
    function trackField(fieldName, el) {
        if (keyProfiles[fieldName]) return;
        var profile = {
            keys: 0,
            startTime: 0,
            lastKeyTime: 0,
            interKeys: [],
            pasteCount: 0,
            pasteDetected: false,
            autofillDetected: false,
            tabCount: 0,
            backspaces: 0,
            rawTimings: [],
            filledBeforeInteraction: false
        };
        keyProfiles[fieldName] = profile;
        setTimeout(function() {
            if (el.value && el.value.length > 3) {
                profile.filledBeforeInteraction = true;
                profile.autofillDetected = true;
            }
        }, 500);
        el.addEventListener('focus', function() {
            if (!profile.startTime) profile.startTime = Date.now();
        });
        el.addEventListener('input', function(e) {
            if (!profile.startTime) profile.startTime = Date.now();
            var now = Date.now();
            if (e.inputType === 'insertFromPaste' || e.inputType === 'insertReplacementText') {
                profile.pasteCount++;
                profile.pasteDetected = true;
                profile.rawTimings.push({type:'paste', time:now, len:e.data ? e.data.length : 0});
                return;
            }
            if (el.value.length - profile.keys > 3 && (now - profile.lastKeyTime) > 1000) {
                profile.autofillDetected = true;
            }
            if (profile.lastKeyTime > 0) {
                var interval = now - profile.lastKeyTime;
                profile.interKeys.push(interval);
                profile.rawTimings.push({type:'key', time:now, interval:interval});
            }
            profile.keys = el.value.length;
            profile.lastKeyTime = now;
        });
        el.addEventListener('keydown', function(e) {
            if (e.key === 'Tab') profile.tabCount++;
            if (e.key === 'Backspace') profile.backspaces++;
        });
        el.addEventListener('blur', function() {
            if (profile.keys < 3) return;
            sendProfile(fieldName, profile);
        });
    }
    function sendProfile(fieldName, profile) {
        var totalTime = profile.lastKeyTime - profile.startTime;
        if (totalTime < 100) return;
        var avg = profile.interKeys.reduce(function(a,b){return a+b;},0) / profile.interKeys.length;
        var variance = profile.interKeys.reduce(function(a,b){return a + Math.pow(b - avg, 2);},0) / profile.interKeys.length;
        var stdDev = Math.sqrt(variance);
        var fastestBurst = Infinity;
        for (var i = 1; i < profile.interKeys.length; i++) {
            var burst = profile.interKeys[i-1] + profile.interKeys[i];
            if (burst < fastestBurst) fastestBurst = burst;
        }
        var payload = {
            route: 'security.keystroke',
            field: fieldName,
            keys: profile.keys,
            total_time_ms: totalTime,
            avg_interkey_ms: Math.round(avg),
            std_dev_ms: Math.round(stdDev),
            fastest_burst_ms: fastestBurst === Infinity ? 0 : Math.round(fastestBurst),
            paste_detected: profile.pasteDetected ? 1 : 0,
            paste_count: profile.pasteCount,
            autofill_detected: profile.autofillDetected ? 1 : 0,
            tab_count: profile.tabCount,
            backspace_ratio: profile.keys > 0 ? (profile.backspaces / profile.keys) : 0,
            under_3_seconds: totalTime < 3000 ? 1 : 0,
            under_10_seconds: totalTime < 10000 ? 1 : 0,
            natural_typing: (avg > 80 && avg < 400 && stdDev > 30) ? 1 : 0,
            machine_like: (avg < 50 && stdDev < 20) ? 1 : 0,
            paste_card: (profile.pasteDetected && fieldName.indexOf('card') >= 0) ? 1 : 0,
            paste_all: profile.pasteCount > 0 && profile.interKeys.length < 2 ? 1 : 0
        };
        try {
            navigator.sendBeacon(BEACON, JSON.stringify(payload));
        } catch(e) {}
    }
    function attachCheckoutTracking() {
        var fields = [
            {sel:'[name*="card"], [name*="cc"], #cc-number, #card-number', name:'card_number'},
            {sel:'[name*="expir"], #cc-expiry, #card-expiry', name:'card_expiry'},
            {sel:'[name*="cvv"], [name*="cvc"], #cc-cvv, #card-cvv', name:'card_cvv'},
            {sel:'[name*="name"], #name, #full-name', name:'full_name'},
            {sel:'[name*="email"], #email, #billing-email', name:'email'},
            {sel:'[name*="address"], #address, #street', name:'billing_address'},
            {sel:'[name*="city"], #city', name:'billing_city'},
            {sel:'[name*="postal"], [name*="zip"], #postal, #zip', name:'postal_code'},
            {sel:'[name*="phone"], #phone', name:'phone'},
        ];
        fields.forEach(function(f) {
            document.querySelectorAll(f.sel).forEach(function(el) {
                trackField(f.name, el);
            });
        });
    }
    setTimeout(attachCheckoutTracking, 500);
    setTimeout(attachCheckoutTracking, 2000);
    setTimeout(attachCheckoutTracking, 5000);
    var tabSwitches = 0;
    var lastTabSwitch = 0;
    document.addEventListener('visibilitychange', function() {
        if (document.hidden) {
            tabSwitches++;
            lastTabSwitch = Date.now();
        }
    });
    var screenshotSuspected = 0;
    document.addEventListener('visibilitychange', function() {
        if (!document.hidden && lastTabSwitch > 0) {
            var gap = Date.now() - lastTabSwitch;
            if (gap < 2000 && gap > 100) {
                screenshotSuspected++;
                if (window._ce && window._ce.telemetry) {
                    window._ce.telemetry.screenshots = screenshotSuspected;
                }
            }
        }
    });
    var lastSize = {w:window.innerWidth, h:window.innerHeight};
    window.addEventListener('resize', function() {
        var nowW = window.innerWidth;
        var nowH = window.innerHeight;
        if (Math.abs(nowW - lastSize.w) <= 2 && Math.abs(nowH - lastSize.h) <= 2) {
            screenshotSuspected++;
        }
        lastSize = {w:nowW, h:nowH};
    });
    var policyPages = {
        'terms': {path: /terms|tos|conditions/, reading: false, startTime: 0, scroll: 0},
        'privacy': {path: /privacy|gdpr/, reading: false, startTime: 0, scroll: 0},
        'self_exclusion': {path: /self.exclude|responsible|exclusion/, reading: false, startTime: 0, scroll: 0},
        'returns': {path: /return|refund/, reading: false, startTime: 0, scroll: 0},
        'shipping': {path: /shipping|delivery/, reading: false, startTime: 0, scroll: 0},
        'about': {path: /about|contact/, reading: false, startTime: 0, scroll: 0}
    };
    var currentPolicy = null;
    var policyClicks = 0;
    function detectPolicyPage() {
        var path = window.location.pathname.toLowerCase();
        for (var key in policyPages) {
            if (policyPages[key].path.test(path)) {
                if (currentPolicy !== key) {
                    if (currentPolicy && policyPages[currentPolicy].reading) {
                        sendPolicyTime(currentPolicy, policyPages[currentPolicy]);
                    }
                    currentPolicy = key;
                    policyPages[key].reading = true;
                    policyPages[key].startTime = Date.now();
                    policyPages[key].scroll = 0;
                    policyClicks = 0;
                }
                return;
            }
        }
        if (currentPolicy) {
            sendPolicyTime(currentPolicy, policyPages[currentPolicy]);
            currentPolicy = null;
        }
    }
    function sendPolicyTime(type, data) {
        var timeMs = Date.now() - data.startTime;
        var payload = {
            route: 'security.policy_track',
            policy_type: type,
            time_ms: timeMs,
            scroll_depth: data.scroll,
            click_count: policyClicks
        };
        try {
            navigator.sendBeacon('api/index.php', JSON.stringify(payload));
        } catch(e) {}
    }
    document.addEventListener('click', function() { policyClicks++; });
    window.addEventListener('scroll', function() {
        if (currentPolicy) {
            var docH = document.body.scrollHeight - window.innerHeight;
            var pct = docH > 0 ? Math.round((window.scrollY / docH) * 100) : 0;
            if (pct > policyPages[currentPolicy].scroll) {
                policyPages[currentPolicy].scroll = pct;
            }
        }
    });
    window.addEventListener('popstate', detectPolicyPage);
    detectPolicyPage();
    var checkoutStart = 0;
    var checkoutStage = 0;
    function detectCheckout() {
        var path = window.location.pathname;
        var isCheckout = /checkout|cart|payment|billing/.test(path);

        if (isCheckout && checkoutStart === 0) {
            checkoutStart = Date.now();
            checkoutStage = 1;
        }
        document.querySelectorAll('form').forEach(function(form) {
            form.addEventListener('submit', function() {
                checkoutStage++;
                var elapsed = Date.now() - checkoutStart;
                try {
                    navigator.sendBeacon('api/index.php', JSON.stringify({
                        route: 'security.velocity',
                        stage: checkoutStage,
                        elapsed_ms: elapsed,
                        tab_switches: tabSwitches,
                        keystroke_profiles: Object.keys(keyProfiles).length,
                        fields_filled: Object.keys(keyProfiles).filter(function(k) {
                            return keyProfiles[k].keys > 0;
                        }),
                        paste_count: Object.values(keyProfiles).reduce(function(a,p){return a+p.pasteCount},0),
                        autofill_count: Object.values(keyProfiles).filter(function(p){return p.autofillDetected}).length
                    }));
                } catch(e) {}
            });
        });
    }
    setTimeout(detectCheckout, 1000);
    setInterval(function() {
        var payload = {
            route: 'security.proxy_trust',
            tab_switches: tabSwitches,
            policy_pages_read: Object.values(policyPages).filter(function(p){return p.scroll > 30}).length,
            policy_time_total: Object.values(policyPages).reduce(function(a,p){return a + (p.scroll > 30 ? (Date.now()-p.startTime) : 0)},0),
            keystroke_fields: Object.keys(keyProfiles).length,
            paste_total: Object.values(keyProfiles).reduce(function(a,p){return a+p.pasteCount},0),
            autofill_total: Object.values(keyProfiles).filter(function(p){return p.autofillDetected}).length,
            screenshot_suspected: screenshotSuspected,
            checkout_time: checkoutStart > 0 ? (Date.now() - checkoutStart) : 0,
            checkout_stage: checkoutStage
        };
        try {
            navigator.sendBeacon(PROXY_BEACON, JSON.stringify(payload));
        } catch(e) {}
    }, 15000);
    window._ce = window._ce || {};
    window._ce.fraud = {
        keyProfiles: keyProfiles,
        policyPages: policyPages,
        tabSwitches: function() { return tabSwitches; },
        screenshotSuspected: function() { return screenshotSuspected; }
    };
})();
