/**
 * Kantan Analytics Tracking
 * Captures visitor data, clicks, scroll depth, page journeys, UTM params, and conversions
 */

(function() {
    'use strict';

    // Generate or retrieve session ID
    function getSessionId() {
        let sessionId = sessionStorage.getItem('kantan_session_id');
        if (!sessionId) {
            sessionId = 'kantan_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
            sessionStorage.setItem('kantan_session_id', sessionId);
        }
        return sessionId;
    }

    // Generate or retrieve persistent visitor ID (survives sessions)
    function getVisitorId() {
        let visitorId = localStorage.getItem('kantan_visitor_id');
        if (!visitorId) {
            visitorId = 'kv_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
            localStorage.setItem('kantan_visitor_id', visitorId);
        }
        return visitorId;
    }

    // Capture UTM parameters from URL before cleaning
    function captureUtmParams() {
        // Only capture on first page of session
        if (sessionStorage.getItem('kantan_utm_captured')) return;

        try {
            const params = new URLSearchParams(window.location.search);
            const utmSource = params.get('utm_source');
            const utmMedium = params.get('utm_medium');
            const utmCampaign = params.get('utm_campaign');
            const utmTerm = params.get('utm_term');
            const utmContent = params.get('utm_content');

            // Passthrough params (CRM/ad click & contact ids) — match the
            // configured allowlist case-insensitively, store under the canonical
            // lowercase key.
            const allow = (window.kantanAnalytics && kantanAnalytics.passthroughParams) || [];
            const passthrough = {};
            if (allow.length) {
                params.forEach(function (value, name) {
                    const ln = name.toLowerCase();
                    if (value && allow.indexOf(ln) !== -1) { passthrough[ln] = value; }
                });
            }
            const hasPassthrough = Object.keys(passthrough).length > 0;

            // Send if at least one UTM OR passthrough param exists.
            if (!utmSource && !utmMedium && !utmCampaign && !utmTerm && !utmContent && !hasPassthrough) {
                sessionStorage.setItem('kantan_utm_captured', '1');
                return;
            }

            const data = new FormData();
            data.append('action', 'kantan_track_utm');
            data.append('session_id', getSessionId());
            data.append('utm_source', utmSource || '');
            data.append('utm_medium', utmMedium || '');
            data.append('utm_campaign', utmCampaign || '');
            data.append('utm_term', utmTerm || '');
            data.append('utm_content', utmContent || '');
            data.append('landing_url', window.location.href);
            if (hasPassthrough) { data.append('passthrough', JSON.stringify(passthrough)); }

            fetch(kantanAnalytics.ajaxUrl, { method: 'POST', body: data, keepalive: true });
            sessionStorage.setItem('kantan_utm_captured', '1');
        } catch (e) {
            // Silently fail
        }
    }

    // Strip tracking parameters from the URL for clean STORAGE only (this never
    // rewrites the address bar, so it's safe even for generic names site JS may read).
    function cleanUrl(url) {
        try {
            const urlObj = new URL(url);
            const builtin = [
                'fbclid', 'gclid', 'msclkid', 'mc_cid', 'mc_eid',
                '_ga', '_gl', '_ke', 'igshid',
                'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',
                'utm_id', 'utm_source_platform', 'utm_creative_format', 'utm_marketing_tactic'
            ];
            const allow = (window.kantanAnalytics && kantanAnalytics.passthroughParams) || [];
            const removeSet = {};
            builtin.concat(allow).forEach(function (p) { removeSet[String(p).toLowerCase()] = true; });

            // Delete case-insensitively (e.g. Snapchat ships both ScCid and sccid).
            Array.from(urlObj.searchParams.keys()).forEach(function (k) {
                if (removeSet[k.toLowerCase()]) { urlObj.searchParams.delete(k); }
            });

            let cleanUrl = urlObj.origin + urlObj.pathname;
            const remainingParams = urlObj.searchParams.toString();
            if (remainingParams) {
                cleanUrl += '?' + remainingParams;
            }

            return cleanUrl;
        } catch (e) {
            return url;
        }
    }

    // Determine traffic source
    function getTrafficSource() {
        const referrer = document.referrer;
        if (!referrer) return 'direct';

        try {
            const referrerHost = new URL(referrer).hostname;
            const currentHost = window.location.hostname;

            if (referrerHost === currentHost) return 'direct';

            const searchEngines = ['google', 'bing', 'yahoo', 'duckduckgo', 'baidu'];
            for (let engine of searchEngines) {
                if (referrerHost.includes(engine)) return 'organic';
            }

            const socialMedia = ['facebook', 'twitter', 'instagram', 'linkedin', 'pinterest', 'tiktok'];
            for (let social of socialMedia) {
                if (referrerHost.includes(social)) return 'social';
            }
        } catch (e) {
            return 'referral';
        }

        return 'referral';
    }

    // Calculate 1-9 grid region from percentages
    function getClickRegion(xPct, yPct) {
        const col = xPct < 33 ? 0 : (xPct < 66 ? 1 : 2);
        const row = yPct < 33 ? 0 : (yPct < 66 ? 1 : 2);
        return row * 3 + col + 1;
    }

    // Throttle function for scroll tracking
    function throttle(func, limit) {
        let inThrottle;
        return function() {
            const args = arguments;
            const context = this;
            if (!inThrottle) {
                func.apply(context, args);
                inThrottle = true;
                setTimeout(() => inThrottle = false, limit);
            }
        };
    }

    // Track page visit — only count time when tab is visible
    let activeTime = 0;
    let lastActiveTimestamp = Date.now();
    let isTabVisible = !document.hidden;

    document.addEventListener('visibilitychange', function() {
        if (document.hidden) {
            // Tab going hidden — bank the active time
            if (isTabVisible) {
                activeTime += Date.now() - lastActiveTimestamp;
            }
            isTabVisible = false;
        } else {
            // Tab becoming visible — restart the clock
            lastActiveTimestamp = Date.now();
            isTabVisible = true;
        }
    });

    function getActiveDuration() {
        var total = activeTime;
        if (isTabVisible) {
            total += Date.now() - lastActiveTimestamp;
        }
        return Math.floor(total / 1000);
    }

    let pageViewCount = parseInt(sessionStorage.getItem('kantan_page_views') || '0');
    pageViewCount++;
    sessionStorage.setItem('kantan_page_views', pageViewCount.toString());

    const sequenceNum = pageViewCount;
    const isBounce = pageViewCount === 1 ? 1 : 0;

    // Click tracking buffer
    let clickBuffer = [];

    // Scroll depth tracking (0-100%)
    let maxScrollDepth = 0;

    // Capture UTM params before anything else
    captureUtmParams();

    // Send tracking data
    function sendTrackingData() {
        const duration = getActiveDuration();

        const data = new FormData();
        data.append('action', 'kantan_track_visit');
        data.append('session_id', getSessionId());
        data.append('page_url', cleanUrl(window.location.href));
        data.append('page_title', document.title);
        data.append('referrer', document.referrer);
        data.append('traffic_source', getTrafficSource());
        data.append('is_bounce', isBounce);
        data.append('visit_duration', duration);
        data.append('screen_width', window.screen.width);
        data.append('screen_height', window.screen.height);
        data.append('sequence_num', sequenceNum);
        data.append('scroll_depth', maxScrollDepth);
        data.append('visitor_id', getVisitorId());

        if (navigator.sendBeacon) {
            navigator.sendBeacon(kantanAnalytics.ajaxUrl, data);
        } else {
            fetch(kantanAnalytics.ajaxUrl, { method: 'POST', body: data, keepalive: true });
        }
    }

    // Send click tracking data
    function sendClickData() {
        if (clickBuffer.length === 0) return;

        const data = new FormData();
        data.append('action', 'kantan_track_clicks');
        data.append('session_id', getSessionId());
        data.append('page_url', cleanUrl(window.location.href));
        data.append('clicks', JSON.stringify(clickBuffer));

        clickBuffer = [];

        if (navigator.sendBeacon) {
            navigator.sendBeacon(kantanAnalytics.ajaxUrl, data);
        } else {
            fetch(kantanAnalytics.ajaxUrl, { method: 'POST', body: data, keepalive: true });
        }
    }

    // Conversion link matching — checks if a URL matches any configured conversion link pattern
    function matchConversionLink(href) {
        if (!kantanAnalytics.conversionLinks || !kantanAnalytics.conversionLinks.length) return null;
        try {
            var url = new URL(href, window.location.origin);
            for (var i = 0; i < kantanAnalytics.conversionLinks.length; i++) {
                var rule = kantanAnalytics.conversionLinks[i];
                if (href.startsWith(rule.domain) || rule.domain.indexOf(url.hostname) !== -1) {
                    return rule;
                }
            }
        } catch (e) {}
        return null;
    }

    // Append UTM params to a URL
    function appendUtm(href, buttonText) {
        try {
            var url = new URL(href);
            if (!url.searchParams.has('utm_source')) {
                url.searchParams.set('utm_source', window.location.hostname);
                url.searchParams.set('utm_medium', 'website');
                url.searchParams.set('utm_campaign', 'organic');
                url.searchParams.set('utm_content', buttonText.toLowerCase().replace(/[^a-z0-9]+/g, '-').substring(0, 50));
            }
            return url.toString();
        } catch (e) {
            return href;
        }
    }

    // Get context about where a link sits on the page
    function getLinkContext(link) {
        // Walk up to find a semantic container
        var el = link;
        var section = '';
        while (el && el !== document.body) {
            if (el.tagName === 'SECTION' || el.tagName === 'HEADER' || el.tagName === 'FOOTER' || el.tagName === 'NAV') {
                section = el.tagName.toLowerCase();
                if (el.id) section += '#' + el.id;
                else if (el.className) {
                    var cls = el.className.split(/\s+/).filter(function(c) { return c.length > 0 && c.length < 30; })[0];
                    if (cls) section += '.' + cls;
                }
                break;
            }
            if (el.hasAttribute && el.hasAttribute('data-block')) {
                section = 'block:' + el.getAttribute('data-block');
                break;
            }
            if (el.id && el.id.length < 40) {
                section = '#' + el.id;
                break;
            }
            el = el.parentElement;
        }
        return section || 'page';
    }

    // Build a clean, human-readable label for a clicked control. Prefers an
    // explicit accessible name (aria-label / title / value / inner img alt) and
    // falls back to trimmed, whitespace-collapsed text. Capped so a stray
    // container click can never store a whole page of text.
    function kantanCleanLabel(el) {
        var label = '';
        if (el.getAttribute) {
            label = el.getAttribute('aria-label') || el.getAttribute('title') || '';
        }
        if (!label && typeof el.value === 'string') {
            label = el.value;
        }
        if (!label) {
            label = el.innerText || el.textContent || '';
        }
        if (!label && el.querySelector) {
            var img = el.querySelector('img[alt]');
            if (img) { label = img.getAttribute('alt') || ''; }
        }
        return label.replace(/\s+/g, ' ').trim().substring(0, 80);
    }

    // Track clicks
    document.addEventListener('click', function(e) {
        const docHeight = Math.max(
            document.body.scrollHeight,
            document.documentElement.scrollHeight
        );
        const xPct = Math.round((e.clientX / window.innerWidth) * 100);
        const yPct = Math.round(((e.clientY + window.scrollY) / docHeight) * 100);

        // Resolve the meaningful control clicked: walk up to the nearest
        // interactive ancestor so we record the actual link/button rather than
        // whatever inner <span>/<i>/<svg> caught the event — and never capture a
        // container's whole-page innerText (which produced garbage rows like
        // <body> "HOME PLANS & PRICING BOOK A TIME ...").
        var interactive = e.target.closest
            ? e.target.closest('a, button, [role="button"], input[type="submit"], input[type="button"], input[type="image"], summary, label')
            : null;
        var clickedEl = interactive || e.target;
        var elementTag = (clickedEl.tagName || 'unknown').toLowerCase();

        // Normalize role-based buttons (e.g. <div role="button">) to 'button' so
        // they read as real controls downstream and aren't filtered out as
        // container clicks alongside genuine <div> dead-space clicks.
        if (interactive && elementTag !== 'a' && elementTag !== 'button' &&
            interactive.getAttribute && interactive.getAttribute('role') === 'button') {
            elementTag = 'button';
        }

        clickBuffer.push({
            x: Math.min(Math.max(xPct, 0), 100),
            y: Math.min(Math.max(yPct, 0), 100),
            region: getClickRegion(xPct, yPct),
            tag: elementTag,
            // Only label interactive controls. A click on dead space still records
            // its coords (for the heatmap) but with an empty label, so it can't
            // pollute the Top Clicked Elements report.
            text: interactive ? kantanCleanLabel(interactive) : ''
        });

        // Auto-track conversion: phone clicks
        const link = e.target.closest('a');
        if (link) {
            const href = link.getAttribute('href') || '';
            if (href.startsWith('tel:')) {
                window.kantanTrackConversion('phone_click', link.textContent.trim().substring(0, 100), href);
            } else if (href.startsWith('mailto:')) {
                window.kantanTrackConversion('email_click', link.textContent.trim().substring(0, 100), href);
            } else if (href.includes('maps.google') || href.includes('maps.apple') || href.includes('goo.gl/maps')) {
                window.kantanTrackConversion('directions_click', link.textContent.trim().substring(0, 100), href);
            }

            // Auto-track conversion: configured conversion links (outbound booking, etc.)
            var rule = matchConversionLink(href);
            if (rule) {
                var btnText = link.textContent.trim().substring(0, 100);
                var context = getLinkContext(link);
                var label = btnText + ' | ' + context;
                window.kantanTrackConversion(
                    rule.type || 'outbound_click',
                    label,
                    href
                );

                // UTM-tag the link if configured
                if (rule.utm) {
                    link.setAttribute('href', appendUtm(href, btnText));
                }
            }
        }
    }, true);

    // Track scroll depth
    window.addEventListener('scroll', throttle(function() {
        const scrollTop = window.scrollY || document.documentElement.scrollTop;
        const docHeight = Math.max(
            document.body.scrollHeight,
            document.documentElement.scrollHeight
        ) - window.innerHeight;

        if (docHeight > 0) {
            const depth = Math.round((scrollTop / docHeight) * 100);
            maxScrollDepth = Math.max(maxScrollDepth, Math.min(depth, 100));
        }
    }, 500));

    // Send initial tracking on page load
    setTimeout(sendTrackingData, 1000);

    // Update tracking before user leaves
    window.addEventListener('beforeunload', function() {
        sendTrackingData();
        sendClickData();
    });

    // Update page view data every 30 seconds
    setInterval(sendTrackingData, 30000);

    // Send click data every 5 seconds if buffer has data
    setInterval(sendClickData, 5000);

    /**
     * Public API: Track a conversion event
     * Usage: kantanTrackConversion('form_submit', 'Contact Form', '/contact/')
     */
    window.kantanTrackConversion = function(type, label, value) {
        const data = new FormData();
        data.append('action', 'kantan_track_conversion');
        data.append('session_id', getSessionId());
        data.append('visitor_id', getVisitorId());
        data.append('conversion_type', type || 'unknown');
        data.append('conversion_label', label || '');
        data.append('conversion_value', value || '');
        data.append('page_url', cleanUrl(window.location.href));

        if (navigator.sendBeacon) {
            navigator.sendBeacon(kantanAnalytics.ajaxUrl, data);
        } else {
            fetch(kantanAnalytics.ajaxUrl, { method: 'POST', body: data, keepalive: true });
        }
    };

})();
