(function () {
    /**
     * Logs messages for debugging
     * @param {string} message
     */
    function logMessage(message) {
        console.log('[Verify ID Sync]: ' + message);
    }

    /**
     * Sends an AJAX request to update the user meta in WordPress.
     * @param {string} metaKey - The key to be updated in the user's meta.
     * @param {string} metaValue - The value to be stored.
     */
    function updateUserMeta(metaKey, metaValue) {
        logMessage('Updating user meta: ' + metaKey);

        var xhr = new XMLHttpRequest();
        var params = 'action=update_user_meta&meta_key=' + encodeURIComponent(metaKey) + '&meta_value=' + encodeURIComponent(metaValue) + '&nonce=' + encodeURIComponent(ageVerificationDataUserSync.nonce);

        xhr.open('POST', ageVerificationDataUserSync.ajax_url, true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');

        xhr.onload = function () {
            if (xhr.status >= 200 && xhr.status < 400) {
                var response = JSON.parse(xhr.responseText);
                if (response.success) {
                    logMessage('User meta updated successfully for ' + metaKey);
                } else {
                    logMessage('Failed to update user meta for ' + metaKey);
                }
            } else {
                logMessage('Server responded with an error for ' + metaKey);
            }
        };

        xhr.onerror = function () {
            logMessage('AJAX request failed while updating ' + metaKey);
        };

        xhr.send(params);
    }

    /**
     * Removes DeviceID and Token from localStorage and User Meta.
     */
    function removeDeviceIDAndToken() {
        logMessage('Removing DeviceID and Token from localStorage and user meta.');
        localStorage.removeItem('device_id');
        localStorage.removeItem('x_token_age_verified');
        updateUserMeta('device_id', '');
        updateUserMeta('token_age_verified', '');
    }

    /**
     * Validates the device and token with the auth check API to ensure data validity.
     * If the age is returned as null, it indicates the data is invalid.
     * @param {string} deviceID
     * @param {string} token
     * @param {Function} callback
     */
    function validateWithAuthCheckAPI(deviceID, token, callback) {
        logMessage('Validating DeviceID and Token with the auth check API.');
        var xhr = new XMLHttpRequest();
        var apiURL = 'https://app.verifyid.dk/api/auth_check/' + encodeURIComponent(token) + '/' + encodeURIComponent(deviceID);

        xhr.open('POST', apiURL, true);
        xhr.setRequestHeader('Content-Type', 'application/json');

        xhr.onload = function () {
            if (xhr.status >= 200 && xhr.status < 400) {
                var response = JSON.parse(xhr.responseText);
                logMessage('Auth Check API Response: ' + JSON.stringify(response));

                // If {age: null}, the data is invalid
                if (response.age === null) {
                    logMessage('Invalid data returned from auth check API. Removing DeviceID and Token.');
                    removeDeviceIDAndToken();
                } else {
                    logMessage('Valid age data received: ' + response.age);
                }

                if (typeof callback === 'function') {
                    callback(response);
                }
            } else {
                logMessage('Error in response from auth check API.');
            }
        };

        xhr.onerror = function () {
            logMessage('Auth check API request failed.');
        };

        xhr.send();
    }

    /**
     * Initializes synchronization between localStorage and user meta.
     */
    function initializeSync() {
        var deviceID = localStorage.getItem('device_id');
        var token = localStorage.getItem('x_token_age_verified');

        // Check if the user is logged in and sync is needed
        if (ageVerificationDataUserSync.is_user_logged_in) {
            logMessage('User is logged in. Starting sync.');

            // Case 1: If user has a device ID in user meta, use that and override localStorage
            if (ageVerificationDataUserSync.device_id) {
                logMessage('User meta contains device ID. Syncing to localStorage.');
                localStorage.setItem('device_id', ageVerificationDataUserSync.device_id);
                deviceID = ageVerificationDataUserSync.device_id; // Use this for further processing

            // Case 2: If there’s no device ID in user meta, check if token is present in localStorage
            } else if (!ageVerificationDataUserSync.device_id && token) {
                // If token exists but no device ID, remove both
                logMessage('Token exists but no device ID. Removing both from localStorage and user meta.');
                removeDeviceIDAndToken();
                return; // Exit the function since no further sync is needed

            // Case 3: If no device ID in user meta and token is not set, generate a new device ID
            } else if (!deviceID) {
                logMessage('No device ID found in localStorage. Generating a new one.');
                deviceID = generateUUID();
                localStorage.setItem('device_id', deviceID);
            }

            // Sync token from user meta if not present in localStorage
            if (!token && ageVerificationDataUserSync.token) {
                logMessage('Setting token from user meta to localStorage.');
                localStorage.setItem('x_token_age_verified', ageVerificationDataUserSync.token);
                token = ageVerificationDataUserSync.token;
            }

            // Sync any changes in localStorage back to user meta
            if (deviceID !== ageVerificationDataUserSync.device_id) {
                updateUserMeta('device_id', deviceID);
            }
            if (token !== ageVerificationDataUserSync.token) {
                updateUserMeta('token_age_verified', token);
            }

            // Perform an auth check to validate the data
            if (deviceID && token) {
                validateWithAuthCheckAPI(deviceID, token);
            }

        } else {
            logMessage('User is not logged in. No sync needed.');
        }
    }

    /**
     * Generates a new UUID for DeviceID.
     * @returns {string} A new UUID.
     */
    function generateUUID() {
        return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
            var r = (Math.random() * 16) | 0,
                v = c === "x" ? r : (r & 0x3) | 0x8;
            return v.toString(16);
        });
    }

    // Trigger synchronization when the document is ready
    window.onload = function () {
        logMessage('User sync script initialized.');

        // Initialize the sync process
        initializeSync();

        // Listen for changes in localStorage and sync to user meta if logged in
        window.addEventListener('storage', function (event) {
            if (ageVerificationDataUserSync.is_user_logged_in && (event.key === 'device_id' || event.key === 'x_token_age_verified')) {
                logMessage('LocalStorage changed: ' + event.key);
                updateUserMeta(event.key, event.newValue);
            }
        });
    };
})();
