(function () {
    'use strict';

    // Early exit if no MetForm forms on the page (check immediately if DOM is ready)
    if (!document.querySelector('.mf-form-wrapper')) {
        return;
    }

    // --- Configuration ---
    const activeSessions = {}; // Track active form sessions for metadata

    /**
     * Calculate session duration for a form
     * @param {string} formId - Form ID
     * @returns {number} Duration in seconds
     */
    function getSessionDuration(formId) {
        const key = 'mf_session_' + formId;
        const stored = sessionStorage.getItem(key);

        if (!stored) {
            return 0;
        }

        try {
            const session = JSON.parse(stored);
            return Math.floor((Date.now() - session.startTime) / 1000);
        } catch (e) {
            return 0;
        }
    }

    // --- 2. Client-side detection functions ---
    function detectDevice() {
        const ua = navigator.userAgent.toLowerCase();
        if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(ua)) {
            return 'tablet';
        }
        if (/Mobile|iP(hone|od)|Android|BlackBerry|IEMobile|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)/i.test(ua)) {
            return 'mobile';
        }
        return 'desktop';
    }
    function detectBrowser() {
        const ua = navigator.userAgent.toLowerCase();
        if (ua.indexOf('opera') > -1 || ua.indexOf('opr') > -1) return 'opera';
        if (ua.indexOf('edg') > -1) return 'edge';
        if (ua.indexOf('firefox') > -1) return 'firefox';
        if (ua.indexOf('trident') > -1 || ua.indexOf('msie') > -1) return 'ie';
        if (ua.indexOf('chrome') > -1) return 'chrome';
        if (ua.indexOf('safari') > -1) return 'safari';
        return 'other';
    }

    function detectTrafficSource() {
        const referrer = document.referrer;
        if (!referrer) {
            return 'direct';
        }

        const currentDomain = window.location.hostname;
        const referrerUrl = new URL(referrer);
        const referrerDomain = referrerUrl.hostname;

        if (referrerDomain === currentDomain) {
            return 'direct';
        }

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

        return 'referral';
    }

    /**
     * Get referrer URL with same-domain filtering
     * Returns empty string if referrer is same domain or not available
     * @returns {string} Referrer URL or empty string if same domain or not available
     */
    function getReferrer() {
        const referrer = document.referrer;
        if (!referrer) {
            return '';
        }

        try {
            const currentDomain = window.location.hostname;
            const referrerUrl = new URL(referrer);
            const referrerDomain = referrerUrl.hostname;

            // Return empty if same domain
            if (referrerDomain === currentDomain) {
                return '';
            }
        } catch (e) {
            // If URL parsing fails, return the referrer as-is
        }

        return referrer;
    }

    /**
     * Set cookie
     * @param {string} name - Cookie name
     * @param {string} value - Cookie value
     * @param {number} days - Days until expiry
     */
    function setCookie(name, value, days) {
        const date = new Date();
        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
        const expires = "expires=" + date.toUTCString();
        const secure = window.location.protocol === 'https:' ? ';Secure' : '';
        document.cookie = name + "=" + value + ";" + expires + ";path=/;SameSite=Lax" + secure;
    }

    // --- Country detection start ---
    let countryData = null;
    let countryFetched = false;

    /**
     * Fetch country name from ipinfo.io (client-side)
     * Caches result in memory to avoid multiple requests
     * @returns {Promise<string>} Country name or empty string if not available
     */
    async function getCountry() {
        // Return cached country if already fetched
        if (countryFetched) {
            return countryData;
        }

        // Respect the server-side privacy gate: skip the third-party (ipinfo.io)
        // lookup unless country detection is explicitly enabled.
        if (typeof metformAnalyticsTracking === 'undefined' || !metformAnalyticsTracking.countryDetection) {
            countryData = '';
            countryFetched = true;
            return countryData;
        }

        try {
            const response = await fetch('https://ipinfo.io/json');
            if (response.ok) {
                const data = await response.json();
                countryData = data.country || '';
            }
        } catch (e) {
            // Silently fail if country detection doesn't work
            countryData = '';
        }

        countryFetched = true;
        return countryData;
    }

    /**
     * Track form view with analytics data
     * async function to allow country detection before sending data
     * @param {string} formId - The ID of the form being viewed
     */
    async function trackFormView(formId) {
        if (typeof metformAnalyticsTracking === 'undefined' || !metformAnalyticsTracking.nonce) {
            return;
        }

        const duration = getSessionDuration(formId);
        const device = detectDevice();
        const browser = detectBrowser();
        const source = detectTrafficSource();
        const referrer = getReferrer();
        const country = await getCountry();

        // Persist country/referrer for the server-side conversion tracker
        // (base.php::track_submission reads this cookie on form submission).
        const handoff = JSON.stringify({ country: country || '', referrer: referrer || '' });
        setCookie('mf_analytics_' + formId, encodeURIComponent(handoff), 1);

        fetch(`${metformAnalyticsTracking.restUrl}/track_view/${formId}`, {
            method: 'POST',
            headers: {
                'X-WP-Nonce': metformAnalyticsTracking.nonce,
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                session_duration: duration,
                device: device,
                browser: browser,
                source: source,
                referrer: referrer,
                country: country || ''
            })
        }).catch(() => {});
    }

    /**
     * Send incremental duration update (Burst-style delta)
     * This allows multiple updates without double counting
     * @param {string} formId - Form ID
     * @param {boolean} isFinal - Whether this is a final update
     */
    function sendDurationUpdate(formId) {
        if (typeof metformAnalyticsTracking === 'undefined') return;

        const sessionKey = 'mf_session_' + formId;
        const stored = sessionStorage.getItem(sessionKey);
        if (!stored) return;

        const session = JSON.parse(stored);
        const totalDuration = Math.floor((Date.now() - session.startTime) / 1000);
        const delta = totalDuration - (session.sentDuration || 0);

        // Only send if there's new time (at least 1 second)
        if (delta <= 0) return;

        // Update sent duration in storage BEFORE sending to handle race conditions
        session.sentDuration = (session.sentDuration || 0) + delta;
        sessionStorage.setItem(sessionKey, JSON.stringify(session));

        const data = JSON.stringify({
            session_duration: delta, // Send only the increment
            is_update: true // Crucial: This ensures views are NOT incremented on update
        });

        const url = `${metformAnalyticsTracking.restUrl}/track_view/${formId}`;

        // send duration update to server
        if (navigator.sendBeacon) { // sendBeacon is used for sending data to the server when the page is being unloaded
            const urlWithNonce = `${url}?_wpnonce=${metformAnalyticsTracking.nonce}`;
            const blob = new Blob([data], { type: 'application/json' }); // blob is used for sending data to the server when the page is being unloaded
            navigator.sendBeacon(urlWithNonce, blob);
        } else {
            fetch(url, {
                method: 'POST',
                headers: {
                    'X-WP-Nonce': metformAnalyticsTracking.nonce,
                    'Content-Type': 'application/json',
                },
                body: data,
                keepalive: true // keepalive is used for sending data to the server when the page is being unloaded
            }).catch(() => { });
        }
    }

    /**
     * Extract form ID from .mf-form-wrapper element
     * @param {Element} formWrapper - The .mf-form-wrapper element
     * @returns {string|null} The form ID or null if not found
     */
    function getFormId(formWrapper) {
        let formId = formWrapper.getAttribute('data-form-id');
        if (formId) return formId;

        const wrapperId = formWrapper.id;
        if (wrapperId) {
            const m = wrapperId.match(/metform-wrap-(\d+)/);
            if (m) return m[1];
        }
        return null;
    }

    /**
     * Setup optimized tracking events
     * Uses visibilitychange and pagehide for incremental updates
     */
    function setupEventListeners() {
        // Track when user switches tabs or minimizes window
        document.addEventListener('visibilitychange', () => {
            if (document.hidden) {
                Object.keys(activeSessions).forEach(formId => {
                    sendDurationUpdate(formId);
                });
            }
        });

        // Track when page is being hidden (closing tab, navigating away)
        window.addEventListener('pagehide', () => {
            Object.keys(activeSessions).forEach(formId => {
                sendDurationUpdate(formId);
            });
        });
    }

    /**
     * Initialize IntersectionObserver to track when forms come into view
     * Observes all .mf-form-wrapper elements and tracks view when they are at least 50% visible
     * Uses trackFormView to send analytics data when a form is viewed
     * Ensures each form is only tracked once per page load
     * @returns {void}
     */
    function initIntersectionObserver() {
        const formWrappers = document.querySelectorAll('.mf-form-wrapper');
        if (!formWrappers.length) return;

        const observer = new IntersectionObserver((entries) => {
            entries.forEach((entry) => {
                if (entry.isIntersecting) {
                    const formWrapper = entry.target; // .mf-form-wrapper
                    const formId = getFormId(formWrapper);
                    if (formId && !activeSessions[formId]) {
                        // Initialize session for this page load/refresh
                        const now = Date.now();
                        const session = {
                            startTime: now,
                            sentDuration: 0
                        };
                        sessionStorage.setItem('mf_session_' + formId, JSON.stringify(session));
                        activeSessions[formId] = true;

                        trackFormView(formId);
                    }
                }
            });
        }, {
            root: null,
            rootMargin: '0px',
            threshold: 0.5, // Consider form "viewed" when 50% visible
        });

        formWrappers.forEach((wrapper) => observer.observe(wrapper)); // Observe all metform form wrapper in loading page
    }

    // Auto init 
    function init() {
        initIntersectionObserver();
        setupEventListeners();
    }

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

    window.MetFormAnalytics = {
        trackView: trackFormView,
        getSessionDuration: (formId) => getSessionDuration(formId)
    };
})();
