<?php
/*
Plugin Name: InflatableOffice
Plugin URI: https://rental.software
Description: Integrates your InflatableOffice inventory into your wordpress site to generate and keep updated products and categories.
Author: InflatableOffice
Author URI: https://rental.software
Version: 1.0.5
*/
$keep_going = TRUE;

//raise the limit on the number of items per page
ini_set('pcre.backtrack_limit', '20000000');  // 20M. tested with 360 items per page
//ini_set('pcre.recursion_limit', '1000000');   // 1M

function io_check_old_plugin_installed() {
    // Check if the old plugin is installed (not just active)
    // The old plugin path would be wp-plugin/inflatableoffice/inflatableoffice.php
    if (!function_exists('get_plugins')) {
        require_once(ABSPATH . 'wp-admin/includes/plugin.php');
    }

    // Get all installed plugins
    $all_plugins = get_plugins();

    // Check if any plugin matches the old plugin pattern
    foreach ($all_plugins as $plugin_path => $plugin_data) {
        // Look for the old plugin by checking if it contains inflatableoffice.php but NOT wp-plugin-2
        // The old plugin would be in paths like 'wp-plugin/inflatableoffice/inflatableoffice.php' or similar
        if (strpos($plugin_path, 'inflatableoffice.php') !== false && strpos($plugin_path, 'wp-plugin') === false) {
            // Additional check: ensure it's the old plugin by checking the plugin name
            if (isset($plugin_data['Name']) && $plugin_data['Name'] === 'InflatableOffice WP Integration') {
                return true;
            }
        }
    }

    return false;
}

function io_old_plugin_admin_notice() {
    // Only show in admin area
    if (!is_admin()) {
        return;
    }

    // Check if old plugin is installed
    if (io_check_old_plugin_installed()) {
        $plugins_url = admin_url('plugins.php');
        $warning_message = '<div class="notice notice-error" style="padding: 15px; border-left: 4px solid #dc3232;">'
            . '<h3 style="margin-top: 0;">⚠️ Action Required: Old InflatableOffice Plugin Detected</h3>'
            . '<p><strong>The old "InflatableOffice WP Integration" plugin is still installed on your site.</strong></p>'
            . '<p>You must completely remove the old plugin before you can use the new InflatableOffice plugin. Both plugins cannot be installed at the same time as they will conflict.</p>'
            . '<p><strong>Steps to resolve:</strong></p>'
            . '<ol style="margin-left: 20px;">'
            . '<li>If the old plugin is active, deactivate it first</li>'
            . '<li>Delete/uninstall the old "InflatableOffice WP Integration" plugin completely</li>'
            . '<li>Then you can activate the new InflatableOffice plugin</li>'
            . '</ol>'
            . '</div>';
        printf($warning_message);
    }
}

$old_installed =  io_check_old_plugin_installed();
if($old_installed || ($old_installed && function_exists('inoff_setup'))){
    add_action('admin_notices', 'io_old_plugin_admin_notice');
    deactivate_plugins(plugin_basename(__FILE__));
    $keep_going = FALSE;
    return;
}

function register_lead_action($form_actions_registrar){
    require_once(__DIR__ . '/includes/elementor-actions/io-lead-action.php');
    $form_actions_registrar->register(new \IO_Entity_Action());
}
add_action('elementor_pro/forms/actions/register', 'register_lead_action');

// Register IO custom Elementor Pro Form Field: Rental Picker
function io_register_rental_picker_field($form_fields_registrar ) {
    require_once(__DIR__ . '/includes/elementor-fields/IO_Rental_Picker_Field.php');
    $form_fields_registrar->register( new \IO_Rental_Picker_Field() );
}
#add_action( 'elementor_pro/forms/fields/register', 'io_register_rental_picker_field' );


if($keep_going){
    $plugin_current_version = '1.0.5';//also set it above in the comments
    require_once('shortcoder.php');
    require_once('wp-oauth.php');
    //require_once('wp-rest-api.php');
    require_once ('wp_autoupdate.php');
    require_once ('widget-featured.php');
    require_once ('widget-filter.php');
    require_once ('widget-TentCalc.php');
//require_once ('widget-datepicker.php');
    require_once ('search_widget/includes/class-widget.php');
    require_once ('search_widget/searchio-live-ajax-search.php');


    $plugin_remote_path = 'https://rental.software/wp-plugin-2/update.php';
    $plugin_slug = 'inflatableoffice-v2/inflatableoffice.php';
//$license_user = 'user';
//$license_key = 'abcd';
    new IOWP_AutoUpdate ( $plugin_current_version, $plugin_remote_path, $plugin_slug);//, $license_user, $license_key );

    function inoff_setup($network_wide){
        if(is_user_logged_in()) {
            _wo_server_activation($network_wide);
            $wo = new WO_Server();
            $wo->setup();
            $wo->upgrade();
            //json_api_activation(false);
            sc_setup();

            //flush_rewrite_rules();//force permalink refresh which is needed due to api update

            if (!get_option('io_checkavail')) update_option("io_checkavail", 'warn');//default

            //create pages for quote integration
            create_io_pages();//running it every page load now as well as on plugin activation (bc if they switch themes we have to re-activate to create the pages)
        }
    }

    register_activation_hook( __FILE__, 'inoff_setup' );

    function io_check_plugin_version() {
        if( !function_exists('get_plugin_data') ){
            require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
        }
        $current_version = get_plugin_data( (__FILE__), false, false )['Version'];
        $old_version = get_option( 'io_plugin_version' );
        if(empty($old_version)) $old_version= 0;
        if (version_compare($current_version,$old_version,'>')) {
            //this code only runs 1x after plug-in is upgraded
            //sc_setup();//below so it runs all the time...
            // flush_rewrite_rules();
            add_action("shutdown", "flush_rewrite_rules");

            //check shortcodes to make sure all are set to auto-upgade for this version
            if (version_compare($old_version,'4.0.0','<')) {
                $autoupdate=1;
                $shortcoder_data = get_option('shortcoder_data');
                if (!empty($shortcoder_data)) {
                    foreach ($shortcoder_data as $k => $v) {
                        if (empty($shortcoder_data[$k]['autoupdate']) && $k<>'io_category' && $k<>'io_categroy') {
                            $autoupdate=0;
                        }
                    }
                    if($autoupdate==0) {
                        foreach ($shortcoder_data as $k => $v) {
                            $shortcoder_data[$k]['autoupdate'] = 0;
                        }
                        update_option('shortcoder_data', $shortcoder_data);
                    }
                }
            }
            // remove this page, as changes may have been made to it.
            if(file_exists(get_template_directory().'/page-io_reviews.php')){
                unlink(get_template_directory().'/page-io_reviews.php');
            }

            // update not to run twice
            update_option('io_plugin_version', $current_version);
        }
    }
    io_check_plugin_version();

    function unhash_login() {
        // Only continue if 'io_auth' parameter is set
        if (!isset($_REQUEST['io_auth'])) {
            return; // Exit early if the 'io_auth' parameter isn't set, no redirection happens
        }

        // Process login only if user is not already logged in
        if (!is_user_logged_in()) {
            $key = 'cGSmuRB/EB6P5ylv"mk!';
            $encrypted = urldecode($_REQUEST['io_auth']);
            $decrypted = base64_decode($encrypted);
            $plaintext = str_replace($key, '', $decrypted);
            $credentials = explode('&', $plaintext, 2);

            if (empty($credentials[0]) || empty($credentials[1])) {
                wp_mail("dan@inflatableoffice.com", "Unhash Login Error", "Decryption failed or incomplete credentials");
                return; // Stop further processing if decryption fails
            }

            auto_login_temp($credentials[0], $credentials[1]);
        }

        // Redirect to the admin dashboard after successful login
        if (is_user_logged_in() && !is_admin()) {
            wp_redirect(admin_url());
            exit();
        }
    }
    add_action('init', 'unhash_login');

    function auto_login_temp($u, $p) {
        if (!is_user_logged_in()) {
            $user = get_user_by('login', $u);
            if (!$user) {
                wp_mail("dan@inflatableoffice.com", "Auto Login Temp Error", "User not found with username - {$u}");
                return;
            }

            if (!wp_check_password($p, $user->data->user_pass, $user->ID)) {
                wp_mail("dan@inflatableoffice.com", "Auto Login Temp Error", "Password check failed for user - {$u}");
                return; // Incorrect password
            }

            $loginusername = $user->user_login;
            wp_set_current_user($user->ID, $loginusername);
            wp_set_auth_cookie($user->ID, true);
            do_action('wp_login', $loginusername, $user);

            // Redirect after login
            if (isset($_REQUEST['redirect_to'])) {
                $redirect_page = $_REQUEST['redirect_to'];
            } else {
                $redirect_page = admin_url();
            }

            wp_redirect($redirect_page);
            exit();
        }
    }

    function extend_login_sessions($expire) {
        // Set the expiration to 30 days (30 days * 24 hours * 60 minutes * 60 seconds)
        return 90 * 24 * 3600;
    }
    add_filter('auth_cookie_expiration', 'extend_login_sessions');

// Fixes shortcode update issue
    sc_setup();

/**
 * Retrieves the client's IP address from server headers, prioritizing headers
 * that may indicate the actual client IP in cases where a proxy or CDN is involved.
 * Falls back to a default IP of '127.0.0.1' if no valid IP is found.
 * @return string The client's IP address.
 */
function io_get_client_ip() {
    $headers =
            [
        'HTTP_X_SUCURI_CLIENTIP',
        'HTTP_X_FORWARDED_FOR',
                    'HTTP_CLIENT_IP',
                    'REMOTE_ADDR',
            ];

    $flags = FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;

    foreach ($headers as $h)
    {
        if (empty($_SERVER[$h])) continue;

            $ip = $_SERVER[$h];

    // If header has a chain of IPs, take the left-most
        if (strpos($ip, ',') !== false) $ip = trim(explode(',', $ip, 2)[0]);
        else $ip = trim($ip);

        if (filter_var($ip, FILTER_VALIDATE_IP, ['flags' => $flags]) !== false) {
            return $ip; // raw IPv4/IPv6, public only
        }
    }
    return $_SERVER['REMOTE_ADDR'] ?? '127.0.0.1';
}

// Fixes multisite activation issue. #14422
    add_action('init', 'inoff_setup');

//can probably remove this eventually
//add_action( 'shutdown', 'flush_rewrite_rules');//force permalink refresh which is needed due to api update

    function widget_featured() {
        register_widget( 'IO_Featured' );

    }
    add_action( 'widgets_init', 'widget_featured');

    function widget_filter() {
        register_widget( 'Widget_Filter' );

    }
    add_action( 'widgets_init', 'widget_filter' );

    function widget_TentCalculator() {
        register_widget( 'Widget_TentCalculator' );

    }
    add_action( 'widgets_init', 'widget_TentCalculator');

    function searchio_live_search() {
        register_widget( 'IO_Search' );

    }
    add_action( 'widgets_init', 'searchio_live_search' );

/*
function widget_datepicker() {
    register_widget( 'Widget_DatePicker' );

}
add_action( 'widgets_init', 'widget_datepicker' );
*/
//removes wrong p tags that are added to descr, but didn't solve
    /*add_filter('the_content', 'test_cont','10.1');
    function test_cont($content) {
        $content = str_replace(' description="</p>',' description="',$content);
        $content = str_replace('<p>" notes=','" notes=',$content);
        return $content;
    };*/

//links are verified externally. removing them will only delist your links
    function get_io_links(){
        $links = get_option( 'io_links' );
        $links_obj = json_decode($links);
        echo get_header();
        echo "<br><br><br>";
        echo '<h2>Other great rental companies</h2>';
        if(is_iterable($links_obj)) {
            foreach ($links_obj as $item) {
                echo $item . "<br><br>";
            }
        }
        echo get_footer();
    }

    // Create or replace pages with the widget
    function create_io_pages() {
        $pages_config = [
            'io_quoteform' => ['title' => 'Quote Form', 'type' => 'quoteme'],
            'io_quoteconfirm' => ['title' => 'Quote Details', 'type' => 'quote_confirm'],
            'io_contract' => ['title' => 'Event Contract', 'type' => 'contractme'],
            'io_contactform' => ['title' => 'Contact Us', 'type' => 'contactme'],
            'io_receipt' => ['title' => 'Payment Receipt', 'type' => 'receipt'],
            'io_vendor' => ['title' => 'Vendor Contract', 'type' => 'vendorme'],
            'io_quotedone' => ['title' => 'Quote Done', 'type' => 'quote_done']
        ];

        $new_plugin_path = "get_template_directory() . '/../../plugins/inflatableoffice-v2/io-getpagecontent.php'";
        $template_content = '<?php $page_type = \'%s\'; require_once(' . $new_plugin_path . '); ?>';

        foreach ($pages_config as $slug => $config) {
            $file_path = get_template_directory() . '/page-' . $slug . '.php';
            $needs_update = false;

            // Check if file exists and contains old plugin path
            if (file_exists($file_path)) {
                $current_content = file_get_contents($file_path);
                if (strpos($current_content, 'inflatableoffice/io-getpagecontent.php') !== false) {
                    $needs_update = true;
                }
            } else {
                $needs_update = true;
            }

            // Create or update the file
            if ($needs_update) {
                $content = sprintf($template_content, $config['type']);
                file_put_contents($file_path, $content);
            }

            $page = get_page_by_path($slug);
            if (empty($page)) {
                wp_insert_post([
                    'post_title' => $config['title'],
                    'post_name' => $slug,
                    'post_type' => 'page',
                    'post_status' => 'publish',
                    'post_content' => 'Do not delete. This page\'s content is generated.'
                ]);
            }
        }
    }

    if (strpos($_SERVER['REQUEST_URI'],'io_') !== false) {
        create_io_pages();
    }
#region IO-27771: Improved Reviews II ----------------------------------------------------------
    function does_io_reviews_widget_exist($post_id) {
        if (is_plugin_active('elementor/elementor.php')) {
            // Ensure that the Elementor instance exists before proceeding
            if (class_exists('\Elementor\Plugin') && \Elementor\Plugin::$instance->documents->get($post_id)->is_built_with_elementor()) {

                // Get the Elementor data
                $elementor_data = get_post_meta($post_id, '_elementor_data', true);

                if ($elementor_data) {
                    // Decode the JSON data
                    $elementor_content = json_decode($elementor_data, true);

                    // Search for the IO_Reviews_Widget in the content
                    return search_for_widget($elementor_content, 'io_reviews_widget');
                }
            }
        }

        return false;
    }

    function search_for_widget($elements, $widget_name) {
        foreach ($elements as $element) {
            // Check if the element is a widget and matches the widget name
            if (isset($element['widgetType']) && $element['widgetType'] === $widget_name) {
                return true;
            }

            // Recursively check inner elements if they exist
            if (isset($element['elements']) && is_array($element['elements'])) {
                if (search_for_widget($element['elements'], $widget_name)) {
                    return true;
                }
            }
        }

        return false;
    }


    function create_or_update_reviews_page()
    {

        if ( is_plugin_active( 'elementor/elementor.php' ) )
        {

            $review_page = get_page_by_path('reviews', OBJECT);
            $post_id = $review_page->ID;

            //basically a short circuit where if the page exists and has the widgety we don't care about the rest of the code
            if ($review_page && does_io_reviews_widget_exist($post_id))
                return;

            // If /reviews/ exists without the widget, delete it to allow re-creation
            if ($review_page && !does_io_reviews_widget_exist($post_id)) {
                wp_delete_post($post_id, true);
            }

            // Create the new Reviews page (this should only ever run if the page doesn't exist with the widget on it)
            $page_id = wp_insert_post
            (
                array
                (
                    'post_title' => 'Reviews',
                    'post_name' => 'reviews',
                    'post_type' => 'page',
                    'post_status' => 'publish',
                )
            );

            if (!$page_id)
                error_log('Failed to create the Reviews page.');
            else
                error_log('Reviews page created with ID: ' . $page_id);

            // Set the page to use Elementor
            if (defined('ELEMENTOR_VERSION'))
            {
                update_post_meta($page_id, '_elementor_edit_mode', 'builder');
                update_post_meta($page_id, '_elementor_version', ELEMENTOR_VERSION);
            }

            // Generate unique IDs for section, column, and widget
            $unique_section_id = uniqid('section_');
            $unique_column_id = uniqid('column_');
            $unique_widget_id = uniqid('widget_');

            // Add Elementor widget data using actual widget settings
            $elementor_data =
                [
                    [
                        'id' => $unique_section_id,
                        'elType' => 'section',
                        'elements' =>
                            [
                                [
                                    'id' => $unique_column_id,
                                    'elType' => 'column',
                                    'elements' =>
                                        [
                                            [
                                                'id' => $unique_widget_id,
                                                'elType' => 'widget',
                                                'widgetType' => 'io_reviews_widget',
                                                'settings' =>
                                                    [
                                                        'slides_to_show' => 3,
                                                        'autoplay' => 'yes',
                                                        'autoplay_speed' => 2,
                                                        'infinite' => 'yes',
                                                        'slides_to_scroll' => 1,
                                                        'show_all_reviews' => 'yes',
                                                        'number_of_reviews' => 5,
                                                        'show_average_rating' => 'yes',
                                                        'show_stars' => 'yes',
                                                        'show_review_date' => 'yes',
                                                        'show_reviewer_name' => 'yes',
                                                        'show_reviewer_photo' => 'yes',
                                                        'review_order' => 'random',
                                                    ],
                                            ]
                                        ]
                                ]
                            ]
                    ]
                ];

            update_post_meta($page_id, '_elementor_data', json_encode($elementor_data));
            if (function_exists('force_elementor_rebuild'))
            {
                force_elementor_rebuild($page_id);
            }
        }
    }
    add_action('wp_loaded', 'create_or_update_reviews_page');

#endregion -----------------------------------------------------------------------------------

// #5474 - add adwords tracking
// #6028 - add facebook tracking
    function io_analytics_tracking() {
        // IO-28339
        $io_url_params = get_option('io_url_params');
        if($io_url_params) {
            $io_url_params = json_decode($io_url_params);
            foreach ($io_url_params as $io_url_param) {
                if (array_key_exists($io_url_param->urlparam_paramname, $_REQUEST)) {
                    $param_value = stripslashes($_REQUEST[$io_url_param->urlparam_paramname]);
                    // Protect against XSS by only allowing alphanumeric characters and basic punctuation
                    if (preg_match('/^[a-zA-Z0-9\s\-_.,;:!?\'"\(\)]+$/', $param_value)) {
                        //setcookie($io_url_param->urlparam_cookiename, $param_value, time() + $io_url_param->urlparam_expiresin, '/');
                        setcookie(
                            $io_url_param->urlparam_cookiename,
                            $param_value,
                            [
                                'expires'  => time() + $io_url_param->urlparam_expiresin,
                                'path'     => '/',
                                'domain'   => '',         // leave empty to use current host; set explicitly if needed
                                'secure'   => true,       // only send over HTTPS
                                'httponly' => true,       // inaccessible to JS
                                'samesite' => 'Lax'       // or 'Strict' or 'None' (None requires Secure)
                            ]
                        );
                    }
                }
            }
        }
    }
    add_action( 'init', 'io_analytics_tracking' );

    add_action( 'wp_footer', 'io_addtracking_allpages' );
    function io_addtracking_allpages() {
        // IO-28339 add additional
        if(strpos(get_site_url(), 'localhost') !== false){
            $url = "http://localhost/io/bugs/include/iotracking.php";
        }else{
            $url = "https://rental.software/include/iotracking.php";
        }
        $io_url_params = get_option('io_url_params');
        if($io_url_params) {
            $io_url_params = json_decode($io_url_params);
            $is_first = true;
            foreach ($io_url_params as $key => $io_url_param) {
                if (array_key_exists($io_url_param->urlparam_cookiename, $_COOKIE) && isset($_COOKIE[$io_url_param->urlparam_cookiename])) {
                    $cookie_value = stripslashes($_COOKIE[$io_url_param->urlparam_cookiename]);
                    // Protect against XSS by only allowing alphanumeric characters and basic punctuation
                    if (preg_match('/^[a-zA-Z0-9\s\-_.,;:!?\'"\(\)]+$/', $cookie_value)) {
                        if ($is_first) {
                            $url .= "?" . $io_url_param->urlparam_paramname . "=" . $cookie_value;
                            $is_first = false;
                        } else {
                            $url .= "&" . $io_url_param->urlparam_paramname . "=" . $cookie_value;
                        }
                    }
                }
            }
        }
        $html = '<img src="'.$url.'" style="display:none;" importance="low" alt="dynamic io trk code" />';
        echo $html;
    }
    if(get_option('io_username')<>'inflatableoffice'){
        add_action( 'wp_footer', 'io_add_code_allpages' );
    }
    function set_custom_referrer_policy() {
        header('Referrer-Policy: no-referrer-when-downgrade');
    }
    add_action('send_headers', 'set_custom_referrer_policy');

    //for pci compliance - force cache-control output if non specified
    add_action('send_headers', function () {
        // Only care about POST responses
        if (empty($_SERVER['REQUEST_METHOD']) || $_SERVER['REQUEST_METHOD'] !== 'POST') {
            return;
        }

        $headers = headers_list();

        $has_cache_control = false;
        $has_pragma        = false;
        $has_expires       = false;

        foreach ($headers as $header) {
            $header_lower = strtolower($header);
            if (strpos($header_lower, 'cache-control:') === 0) {
                $has_cache_control = true;
            } elseif (strpos($header_lower, 'pragma:') === 0) {
                $has_pragma = true;
            } elseif (strpos($header_lower, 'expires:') === 0) {
                $has_expires = true;
            }
        }

        // Only set these if nothing else has already set them
        if (! $has_cache_control) {
            header('Cache-Control: no-cache', false);
        }
        if (! $has_expires) {
            header('Expires: 0', false);
        }
    }, 999); // run late so other plugins have already added their headers
    function io_add_code_allpages(){

        $showCategoryLong = get_option('io_showCategoryLong');
        $showCategoryLong_css = '';
        if($showCategoryLong && $showCategoryLong =='off'){
            $showCategoryLong_css = '.io_cat_longdescription{display:none !important;}';
        }

    // Base CSS: Always hide list view on inventory/all-items pages (no category ID)
    $hide_listview_css = "
    /* ALWAYS hide toggle buttons and list view on inventory/all-items pages (no category ID) */
    body.io-no-category-id .io_view_toggle_container,
    body.io-no-category-id .io_list_view_content
    {
        display: none !important;
    }
    
    /* Force grid/tile layout on pages without category IDs */
    body.io-no-category-id .io_catdiv2.list-view {
        display: grid !important;
        grid-template-columns: repeat(auto-fit, minmax(250px, 350px)) !important;
        grid-gap: 10px !important;
        margin: 50px !important;
        max-width: none !important;
        justify-content: space-evenly !important;
    }
    body.io-no-category-id .io_catdiv2.list-view .io_item2_list {
        display: block !important;
        flex-direction: column !important;
        margin-bottom: 0 !important;
        padding: 0 !important;
        align-items: initial !important;
        text-align: center !important;
    }
    body.io-no-category-id .io_catdiv2.list-view .cat_div {
        flex: initial !important;
        margin-right: 0 !important;
        position: relative !important;
    }
    body.io-no-category-id .io_catdiv2.list-view .cat_img {
        width: 100% !important;
        height: auto !important;
        object-fit: cover !important;
    }
    body.io-no-category-id .io_catdiv2.list-view .io_item2_list_inner {
        flex: initial !important;
        margin-top: initial !important;
        display: block !important;
        flex-direction: initial !important;
        justify-content: initial !important;
        min-height: auto !important;
        height: auto !important;
    }
    ";

    // Admin option: Hide list view on actual category pages (has category ID) when enabled
    $io_disable_listview = get_option('io_disable_listview');
    if($io_disable_listview=='on'){
        $hide_listview_css .= "
        /* Admin option enabled: Hide toggle buttons and list view on all pages */
        .io_view_toggle_container,
        .io_list_view_content
        {
            display: none !important;
        }
        
        /* Force grid/tile layout when admin option is enabled */
        .io_catdiv2.list-view {
            display: grid !important;
            grid-template-columns: repeat(auto-fit, minmax(250px, 350px)) !important;
            grid-gap: 10px !important;
            margin: 50px !important;
            max-width: none !important;
            justify-content: space-evenly !important;
        }
        .io_catdiv2.list-view .io_item2_list {
            display: block !important;
            flex-direction: column !important;
            margin-bottom: 0 !important;
            padding: 0 !important;
            align-items: initial !important;
            text-align: center !important;
        }
        .io_catdiv2.list-view .cat_div {
            flex: initial !important;
            margin-right: 0 !important;
            position: relative !important;
        }
        .io_catdiv2.list-view .cat_img {
            width: 100% !important;
            height: auto !important;
            object-fit: cover !important;
        }
        .io_catdiv2.list-view .io_item2_list_inner {
            flex: initial !important;
            margin-top: initial !important;
            display: block !important;
            flex-direction: initial !important;
            justify-content: initial !important;
            min-height: auto !important;
            height: auto !important;
        }
        ";
    }

        $io_hidetimes = get_option('io_hidetimes');
        $hidetimes_css = '';
        if($io_hidetimes=='on'){
            $hidetimes_css = "#cartTimePicker .timepicker,#cartTimePicker .fa-clock{display: none !important;}
        .ioCartCompanyTimeslots{display: none !important;}
        .calTimeLabel{display: none !important;}       
        #cartDateRange{margin-bottom: 10px;margin-left: 40px;font-size: x-large;}";
        }
        $io_checkavail = get_option('io_checkavail');
        $hide_checkavail_css = '';
        if($io_checkavail=='off'){
            $hide_checkavail_css = ".item-availability{display: none !important;}";
        }

        //hide price setting
        $hide_price_css = '';
        $io_hide_prices = get_option('io_hide_prices');
        if($io_hide_prices==1){
            $hide_price_css = "
        .rentNameIO_price, .io_product_price_box, .item-total, .cartSubtotalBox
        {
            display: none !important;
        }
        ";
        }

        //hide cat price setting
        $hide_price_catpages_css = '';
        $io_hide_prices_catpages = get_option('io_hide_prices_catpages');
        if($io_hide_prices_catpages==1){
            $hide_price_catpages_css = "
        .rentNameIO_price
        {
            display: none !important;
        }
        ";
        }

        //hide price setting
        $hide_live_price_css = '';
        $io_hide_live_prices = get_option('io_hide_live_prices');
        if($io_hide_live_prices==1 && get_option('io_always_display_live_price') != "on"){
            $hide_live_price_css = "
        .io_product_cust_price
        {
            display: none !important;
        }
        #item_live_price_time_set_message
        {
            display: none !important;
        }
        ";
        }

        //product page price settings
        //todo  master theme has settings on
        //todo mega menu choices (theme menu section)
        $price_override_css = '';
        $prices_css_hide_defaults = '';
        $prices_override_hide_css = '';
        $prices_default_product_page_css = '';
        $prices = get_option('io_prices');
        if(!empty($prices)) {
            //hide the defaults
            $prices_css_hide_defaults = '.io_product_price_4h,.io_product_price_8h,.io_product_price_24h,.io_product_price_additionalday{display:none}';
            //show these
            foreach ($prices as $v) {
                if(is_array($v)) continue;
                $split = explode('_', $v);
                if(isset($split[1])) {
                    if (sizeof($split) == 4 && $split[1] == 'product' && $split[2] == 'price') {
                        $prices_default_product_page_css .= '.' . $v . ',';
                    } else if(sizeof($split) == 5 && $split[1] == 'product' && $split[2] == 'price'){
                        $price_override_css .= '.' . $v . ',';
                    }else if(sizeof($split) == 6 && $split[1] == 'product' && $split[2] == 'price'){
                        // IO-21808
                        $price_override_css .= '.' . $v . ',';
                    }
                }
            }
            $prices_default_product_page_css = rtrim($prices_default_product_page_css, ',');
            $price_override_css = rtrim($price_override_css, ',');
            if (!empty($prices_default_product_page_css)) {
                $prices_default_product_page_css .= '{display: grid !important}';
            }
            if (!empty($price_override_css)) {
                $price_override_css .= '{display: grid !important}';
            }
            //for override prices, we must hide default pricing
            $prices_override_hide_css = '';
            foreach ($prices as $v) {
                if(is_array($v)) continue;
                $split = explode('_', $v);
                //for each default price
                if(!is_array($split)) continue;
                if (sizeof($split) == 4 && ($split[1] == 'product' || $split[1] == 'custom' || $split[1] == 'delivery')) {
                    //for each override
                    foreach ($prices as $ov) {
                        if(is_array($ov)) continue;
                        $osplit = explode('_', $ov);
                        if(!is_array($osplit)) continue;
                        if (sizeof($osplit) >= 5 && ($split[1] == 'product' || $split[1] == 'custom' || $split[1] == 'delivery')) {
                            if(sizeof($osplit) == 5){
                                if (!in_array('io_product_price_' . $split[3] . '_' . $osplit[4], $prices)) {
                                    $prices_override_hide_css .= '.io_product_price_' . $split[3] . '_' . $osplit[4].',';//disable it
                                }
                            }else if(sizeof($osplit) == 6){
                                if (!in_array('io_product_price_' . $split[3] . '_' . $osplit[4] . '_' . $osplit[5], $prices)) {
                                    $prices_override_hide_css .= '.io_product_price_' . $split[3] . '_' . $osplit[4] . '_' . $osplit[5].',';//disable it
                                }
                            }

                            //if 0h, hide on cat too
                            if($osplit[3]=="0h"){
                                $prices_override_hide_css .= '.rentNameIO_price_'.$osplit[4].',';
                            }
                        }
                    }
                }
            }
            $prices_override_hide_css = rtrim($prices_override_hide_css, ',');
            if(!empty($prices_override_hide_css)){
                $prices_override_hide_css.='{display: none !important}';
            }
        }





        $html = '
     <style>
     '.$prices_css_hide_defaults.$prices_default_product_page_css.$hide_price_css.$hide_price_catpages_css.$price_override_css.$prices_override_hide_css.$hide_checkavail_css.$hidetimes_css.$hide_live_price_css.$showCategoryLong_css.'
    .io_all_item_cat{
        display:none;
        float:none;
        width:100%;
        margin-top:20px;
    }
    </style>
    <script>
    //var io_seocitylinktext = "'.get_option('io_seocitylinktext').'";
    jQuery( document ).ready(function() {
        
        //force all quote form links to use cart data
        //removing back to cart shortcode as this needs to only be done if cart is not empty IO-22561
        /*
        let headerBookButton = jQuery("a[href$=\'io_quoteform/\']");
        headerBookButton.addClass("ioCart_link");
        headerBookButton.attr("href", "javascript:;");
        */
    
        
        let last_cat_name = "";
        let ioTrigger = false;
        jQuery(".io_all_item_cat").each(function() {
            current_cat_name = jQuery(this).html();
            if(last_cat_name !== current_cat_name) {
                jQuery(this).show();
                ioTrigger = true;
            }
            last_cat_name = current_cat_name;
        });
        
        // Setup gen page blocks
		let io_divs = document.querySelectorAll(".io_item2_list, .io_item2_listcat, .io_item2_listrent, .io_all_item_cat");
		let io_divscat = document.querySelectorAll(".io_item2_listcat");
		let io_divsrent = document.querySelectorAll(".io_item2_listrent");
		let io_divcat = document.querySelector(".io_catdiv2");
		let io_pcc = document.querySelector(".page-content");
		let io_html;
		
		if (io_divs.length > 0) {
	      for (let i of io_divs) {
	        if(i.parentNode.className.indexOf("io_mm_") === -1){
	          io_divcat.appendChild(i);
	        }
		  }
		  if(io_divcat!==null) io_divcat.style.display = "grid";
		}
		
		if (ioTrigger) {
            let pageBlock = document.querySelector(".io_catdiv2");
            pageBlock.classList.add("elementor-widget-heading");
            let scanRes = pageBlock.querySelectorAll(".io_item2_listrent");
            pageBlock.style.display = "block";
            pageBlock.style.margin = "auto";
            pageBlock.style.textAlign = "center";
            pageBlock.style.marginLeft = "5px";
            pageBlock.style.marginRight = "5px";
            for (let i of scanRes) {
                i.style.display = "inline-block";
                i.style.marginLeft = "5px";
                i.style.marginRight = "5px";
            }
        }
		
		/* fix font color on older sites */
		if(jQuery("#cartData").css("background-color")=="rgb(35, 36, 37)"){
		    jQuery("#cartData").css("color","white");
		}
    });
  </script>';

        //add the cart code to all pages
        $html .= shortcoder(Array('io_cart','page'=>get_option('io_pagename')),'');

        //add the review code to all pages
        $html .= io_get_review_script();

//remove contact us form from checkout pages
    if (get_option('is_template_site') == 1)
    {
        $html .= io_hide_contact_form_from_checkout();
    }
        if(is_multisite()){
            $io_multisiteRedirect = get_option('io_multisiteRedirect');
        $home = network_home_url();
            if($io_multisiteRedirect == "on"){
                $html .= '
                <script>
                    jQuery(document).on("click", ".io_locationRedirectLink", io_location_redirect_click);
                    jQuery(document).ready(function(){
                        let url = window.location.href;

                        if(!getCookie("io_location") || !url.includes(getCookie("io_location"))){
                            jQuery(".io_locationRedirectLink").css("display", "block");
                        }
                    });
                    function io_location_redirect_click(){
                        window.location.href = "'.$home.'";
                    }
                </script>
            ';
            }
        }

        echo $html;
    }

    function io_get_review_script(){
        $show_all_reviews = get_option('io_showAllReviews');
        $number_of_reviews = '10';
        if($show_all_reviews && $show_all_reviews == 'off'){
            $number_of_reviews = get_option('io_reviewAmount');
        }else if($show_all_reviews && $show_all_reviews == 'on'){
            $number_of_reviews = 'all';
        }
        $show_average_rating = get_option('io_showAverageRating');
        $show_average_style = '';
        if($show_average_rating && $show_average_rating =='off'){
            $show_average_style = 'style="display:none"';
        }
        $show_review_stars = get_option('io_showReviewStars');
        if(!$show_review_stars){
            $show_review_stars = 'on';
        }
        $show_review_date = get_option('io_showReviewDate');
        $show_date_style = '';
        if($show_review_date && $show_review_date =='off'){
            $show_date_style = 'style="display:none"';
        }
        $show_reviewer_name = get_option('io_showReviewerName');
        $show_name_style = '';
        if($show_reviewer_name && $show_reviewer_name =='off'){
            $show_name_style = 'style="display:none"';
        }
        $review_order = 'time';
        if(get_option('io_reviewOrder')){
            $review_order = get_option('io_reviewOrder');
        }
        $html = '
        <script>
        jQuery(".io_testimonials, #io_testimonials").each(function(){
           io_get_reviews(this);
        })
        setTimeout(function(){
            jQuery(".io_testimonials .w3-ul li p").each(function(){
                const container = jQuery(this).parent()
                const element = jQuery(this);
                
                if (element[0].scrollHeight > container[0].clientHeight) {
                    
                    jQuery(this).parent().parent().append(create_read_more());
                }
            });
        }, 500);
        
        function create_read_more(){
            let html = "<p class=\"io_review_readmore\" onClick=\"review_readmore_clicked(this)\">read more</p>"
            return html;
        }
        
        function review_readmore_clicked(element){
            let review_li = jQuery(element).parent().find("li:eq(3)");
            new_height = jQuery(review_li).find("p").height() + 16;
            jQuery(review_li).height(new_height);
            jQuery(element).hide();
        }
        
        function io_get_reviews(element){
        let io_un = "' . get_option('io_username') . '";
	  let io_loc = "' . get_option('io_locationid') . '";
	  let io_url1 = \'https://rental.software/testimonials_iframe.php?user=\';
	  if (location.hostname === "localhost"){
	      io_url1 = \'http://localhost/io/bugs/testimonials_iframe.php?user=\';
          //io_url1 = \'http://localhost/jbug/trunk/testimonials_iframe.php?user=\';
        }
	  let io_url2 = \'&location_id=\';
	  let io_url3 = \'&width=100%&number_of_reviews='.$number_of_reviews.'&show_average_rating=1&show_stars=1&show_date=&show_reviewer_name=1&orderby='.$review_order.'&iframe=0\';
	  let io_url_c = io_url1 + io_un + io_url2 + io_loc + io_url3;
	  fetch(io_url_c, {
		method: \'get\'
	}).then(
	  function(response){
		 return response.json();
		}
	).then(function(data) {

    
        
	//let element = document.getElementById("io_testimonials");
	let out = "";
	let review_cnt=0;
	let rating_sum = 0;
	data.forEach((user) => {
				const { name, review, rating, time } = user;
				rating_sum += Number(rating);
				review_cnt++;
				let img_star = Math.round(parseFloat(rating));
				star = `<img class="review_img" src="https://rental.software/images/${img_star}star.png" />`;
				';
        if ($show_review_stars == "off"){
            $html.="star=``;";
        }
        $html.='
				out +=
				`<div>
					<ul class="w3-ul">
						<li '.$show_name_style.'>${name}</li>
						<li>${rating} ${star}</li>
						<li '.$show_date_style.'>${time}</li>
						<li> <p>${review}</p> </li>
					</ul>
				</div>`;
	});
	let avg = (parseFloat(rating_sum)/parseFloat(review_cnt)).toFixed(1);
	let avg_img = Math.round(avg);
	let head = `<div '.$show_average_style.'><h2>Avg Rating: ${avg}</h2><img class="review_avg_img" src="https://rental.software/images/${avg_img}star.png" /></div>`;
	element.innerHTML = head + out;
	return head+out;
	}).catch(function(err) {
		console.log(err);
	});
}
    
	  </script>';
        return $html;
    }

function io_hide_contact_form_from_checkout()
{
    $keywords = array
    (
            'io_quoteform',
            'io_quoteconfirm',
            'io_contract',
            'io_contactform',
            'io_receipt',
            'io_vendor',
            'io_quotedone'
    );

    $current_uri = $_SERVER['REQUEST_URI'];

    // If any keyword is found in the URL, inject the CSS to hide .btm-sec
    foreach ($keywords as $keyword)
    {
        if ( strpos( $current_uri, $keyword ) !== false )
        {
            echo '<style>
                    .btm-sec 
                    {
                        display: none !important;
                    }
                  </style>';
            break;
        }
    }
}

    function io_add_assets() {
        global $plugin_current_version;
        wp_enqueue_script( 'jquery' );
        wp_enqueue_style( 'io_styles', plugin_dir_url( __FILE__ ) . "io_styles_v6.css" );//WARN: Don't add v=? to URL can cause issues. css combiners detect changes, but we need to still version in case they aren't using one
        wp_enqueue_style('font-awesome', 'https://use.fontawesome.com/releases/v5.12.0/css/all.css');//if elementor installed, this gets skipped
        wp_enqueue_script( 'simpleCart', plugin_dir_url( __FILE__ ) . "simpleCart_v10.js", array('jquery'), null, true );
        wp_enqueue_script( 'io_cart', plugin_dir_url( __FILE__ ) . "/includes/io_cart.js", array('jquery', 'simpleCart'), null, true );
        wp_enqueue_script( 'io_category', plugin_dir_url( __FILE__ ) . "/includes/io_category.js", array('jquery', 'io_cart'), null, true );
        wp_enqueue_script( 'io_rental', plugin_dir_url( __FILE__ ) . "/includes/io_rental.js", array('jquery', 'io_cart'), null, true );
        $io_global_vars = get_io_global_vars();
        wp_localize_script( 'io_cart', 'io_cart_vars', $io_global_vars);


        wp_enqueue_script( 'jquery-ui-core' );
        wp_enqueue_script( 'jquery-ui-dialog' );
        wp_enqueue_script( 'jquery-ui-datepicker' );;
        wp_enqueue_style('datepicker_css', plugin_dir_url( __FILE__ ) . "jquery.datepicker.css" );
        wp_enqueue_script( 'timePicker', plugin_dir_url( __FILE__ ) . "jquery.timepicker.1_8_1.js" );
        wp_enqueue_style( 'timePicker_css', plugin_dir_url( __FILE__ ) . "jquery.timepicker.css" );
        wp_enqueue_script( 'fancyBox', plugin_dir_url( __FILE__ ) . "jquery.fancybox.js" );
        wp_enqueue_script( 'flickity', plugin_dir_url( __FILE__ ) . "flickity.js" );
        wp_enqueue_style( 'fancyBox_css', plugin_dir_url( __FILE__ ) . "jquery.fancybox.css" );
        wp_enqueue_script( 'widget-TentCalcJS', plugin_dir_url( __FILE__ ) . "widget-TentCalculator.js" );

    }
    function io_add_admin_assets(){
        wp_enqueue_script( 'timePicker', plugin_dir_url( __FILE__ ) . "jquery.timepicker.1_8_1.js" );
        wp_enqueue_style( 'timePicker_css', plugin_dir_url( __FILE__ ) . "jquery.timepicker.css" );
        wp_enqueue_script( 'io_url_protection', plugin_dir_url( __FILE__ ) . "io_url_protection.js" );
        wp_enqueue_script( 'hide_visual_tab_tinymce', plugin_dir_url( __FILE__ ) . "hide_visual_tab_tinymce.js" );
        wp_enqueue_style( 'io_admin_modal_css', plugin_dir_url( __FILE__ ) . "assets/css/admin-modal.css" );
    }
    add_action( 'admin_footer', 'io_admin_footer' );
    function io_admin_footer() {
        $html = '<style>.e-notice--dismissible,.e-notice-bar{display:none}</style>';
        echo $html;
    }

    // Inject shortcode data into footer before JS files execute
    function io_inject_shortcode_data() {
        global $io_shortcode_data;

        if (!isset($io_shortcode_data)) {
            return;
        }

        echo "\n<!-- IO Shortcode Data -->\n";
        echo "<script>\n";

        // Output category data if present
        if (!empty($io_shortcode_data['category'])) {
            echo "window.io_category_data = window.io_category_data || {};\n";
            foreach ($io_shortcode_data['category'] as $rental_id => $data) {
                echo "window.io_category_data['" . esc_js($rental_id) . "'] = " . json_encode($data, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) . ";\n";
            }
        }

        // Output rental data if present
        if (!empty($io_shortcode_data['rental'])) {
            echo "window.io_rental_data = " . json_encode($io_shortcode_data['rental'], JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) . ";\n";
        }

        echo "</script>\n";
        echo "<!-- End IO Shortcode Data -->\n";
    }

    if(get_option('io_username')<>'inflatableoffice') {
        add_action('wp_enqueue_scripts', 'io_add_assets');
        add_action('admin_enqueue_scripts', 'io_add_admin_assets');
        add_action('wp_footer', 'io_inject_shortcode_data', 5); // Priority 5 - runs early in footer, before scripts
        /*
        add_action( 'elementor/editor/before_enqueue_scripts', function() {
            wp_enqueue_script( 'hide_visual_tab_tinymce', plugin_dir_url( __FILE__ ) . "hide_visual_tab_tinymce.js" );
        } );
        */
    }

    function get_io_global_vars()
    {
        $LOCAL_PATH = get_bloginfo('url');
        $LOCAL_PATH = parse_url($LOCAL_PATH, PHP_URL_PATH);

        $timeslots = get_option('io_company_timeslots');
        if (empty($timeslots)) $timeslots = "[]";//so js doesn't error

        $delivery_methods = get_option('io_delivery_methods');
        if (empty($delivery_methods)) $delivery_methods = "[]";//so js doesn't error

        $accessory_data = get_option('io_accessory_data');
        if (empty($accessory_data)) $accessory_data = "[]";//so js doesn't error

        $io_delivery_prices_json = get_option('io_delivery_prices');
        if (!$io_delivery_prices_json || empty($io_delivery_prices_json)) {
            $io_delivery_prices_json = '{"default":[], "override":[]}';//so js doesn't error
        } else {
            $io_delivery_prices_json = json_encode($io_delivery_prices_json);
        }

        $io_custom_prices_json = get_option('io_custom_prices');
        if (!$io_custom_prices_json || empty($io_custom_prices_json)) {
            $io_custom_prices_json = '{"default":[], "override":[]}';//so js doesn't error
        } else {
            $io_custom_prices_json = json_encode($io_custom_prices_json);
        }

        $io_info_required_data_json = get_option('io_info_required_data');
        if (!$io_info_required_data_json || empty($io_info_required_data_json)) {
            $io_info_required_data_json = "[]";//so js doesn't error
        } else {
            $io_info_required_data_json = json_encode($io_info_required_data_json);
        }

        $io_prices_json = json_encode(get_option('io_prices'));
        if (empty($io_prices_json)) $io_prices_json = "[]";//so js doesn't error

        $delivery_methods_restrict = get_option('io_deliveryMethodRestrict');
        if (empty($delivery_methods_restrict)) $delivery_methods_restrict = "[]";//so js doesn't error

        $io_hideQuantityAvail = get_option('io_hideQuantityAvail');
        if (empty($io_hideQuantityAvail)) $io_hideQuantityAvail = "off";

        $io_hide_live_prices = get_option('io_hide_live_prices');
        if (empty($io_hide_live_prices)) $io_hide_live_prices = 1;

        $io_global_vars = array(
            "io_wp_local_path" => $LOCAL_PATH,
            "io_checkavail" => get_option('io_checkavail'),
            "io_hidetimes" => get_option('io_hidetimes'),
            "io_user_country" => get_option('io_user_country'),
            "io_user_currency" => get_option('io_user_currency'),
            "io_default_start_time" => get_option('io_default_start_time'),
            "io_default_end_time" => get_option('io_default_end_time'),
            "io_force_blank_timepickers" => get_option('io_cartForceBlank'),
            "io_hide_end_time" => get_option('io_cartHideEndTime'),
            "io_cart_date_format" => get_option('io_cart_date_format'),
            "io_cart_message" => get_option('io_cartmessage'),
            "io_cart_time_format" => get_option('io_cart_time_format'),
            "io_multidayquote" => get_option('io_multidayquote'),
            "io_cartdayselect" => get_option('io_cartdayselect'),
            "io_cartAllowSameDay" => get_option('io_cartAllowSameDay'),
            "io_overnightPickupTime" => get_option('io_overnightPickupTime'),
            "io_incartupsell" => get_option('io_incartupsell'),
            "io_distancecharge" => get_option('io_distancecharge'),
            "io_deliverymethod" => get_option('io_deliverymethod'),
            "io_brand" => get_option('io_brand'),
            "io_restrict_times" => get_option('io_restricttimes'),
            "io_restrict_time_start" => get_option('io_restrictTimeStart'),
            "io_restrict_time_end" => get_option('io_restrictTimeEnd'),
            "io_default_state" => get_option('io_default_state'),
            "io_hide_zero" => get_option('io_hide_zero'),
            "io_weekEndPrice" => get_option('io_weekEndPrice'),
            "io_weekDayText" => get_option('io_weekDayText'),
            "io_weekEndText" => get_option('io_weekEndText'),
            "io_weekendDefine" => get_option('io_weekendDefine'),
            "io_accessory_price" => get_option('io_accessory_price'),
            "io_accessory_select" => get_option('io_accessoriesSelect'),
            "io_upsell_price" => get_option('io_upsell_price'),
            "io_cart_party_planner_email" => get_option('io_cartPartyPlannerEmail'),
            "io_cart_party_planner_destination" => get_option('io_cartPartyPlannerDestination'),
            "io_cart_current_specials_phone" => get_option('io_cartCurrentSpecialsPhone'),
            "io_cart_current_specials_destination" => get_option('io_cartCurrentSpecialsDestination'),
            "io_hideQuantityAvail" => empty(get_option('io_hideQuantityAvail')) ? "off" : get_option('io_hideQuantityAvail'),
            "io_company_timeslots" => $timeslots,
            "io_info_required" => get_option('io_info_required'),
            "io_always_display_live_price" => get_option('io_always_display_live_price'),
            "io_default_delivery_method" => get_option('io_defaultDeliveryMethod'),
            "io_hide_live_prices" => $io_hide_live_prices,
            "io_info_required_data" => $io_info_required_data_json,
            "io_prices" => $io_prices_json,
            "io_delivery_prices" => $io_delivery_prices_json,
            "io_custom_prices" => $io_custom_prices_json,
            "io_delivery_methods" => $delivery_methods,
            "io_accessory_data" => $accessory_data,
            "io_delivery_methods_restrict" => $delivery_methods_restrict,
            "io_pagename" => get_option('io_pagename'),
            "io_rest_lead_url" => rest_url('inflatableoffice/v1/lead'),
            "io_categoryVariantImages" => get_option('io_categoryVariantImages')
        );

        return $io_global_vars;
    }

    add_action( 'wp_head', 'io_add_analytics_code_allpages' );
    function io_add_analytics_code_allpages(){
        if(strpos($_SERVER['REQUEST_URI'],'io_')!==FALSE) return;
        $html = '';
        $io_analytics_active = get_option('io_analytics_active');
        if($io_analytics_active==1){
            $html .= get_option('io_analytics_code');
        }
        echo $html;
    }



//custom options
    function customtheme_customize_register_io( $wp_customize ) {

        $wp_customize->add_section(
            'customtheme_header_options2',
            array(
                'title'       => __( 'IO Plugin Settings', 'customtheme' ),
                'priority'    => 100,
                'capability'  => 'edit_theme_options',
                'description' => __('Change IO plugin options here.', 'customtheme'),
            )
        );
        $wp_customize->add_setting( 'darkmode_enable',
            array(
                'default' => '',
                "transport" => "refresh",
                'sanitize_callback' => 'io_sanitize_checkbox',
            )
        );
        $wp_customize->add_control( new WP_Customize_Control(
            $wp_customize,
            'darkmode_enable_control',
            array(
                'label'    => __( 'Enable Dark Mode', 'customtheme' ),
                'description' => __( 'Warning! Experimental Feature' ),
                'section'  => 'customtheme_header_options2',
                'settings' => 'darkmode_enable',
                'priority' => 10,
                'type'  => 'checkbox',
            )
        ));
        $wp_customize->add_setting( 'iopageext_enable',
            array(
                'default' => '',
                "transport" => "refresh",
                'sanitize_callback' => 'io_sanitize_checkbox',
            )
        );
        $wp_customize->add_control( new WP_Customize_Control(
            $wp_customize,
            'iopageext_enable_control',
            array(
                'label'    => __( 'Enable Extended Feature Mode', 'customtheme' ),
                'description' => __( 'Warning! Experimental Feature' ),
                'section'  => 'customtheme_header_options2',
                'settings' => 'iopageext_enable',
                'priority' => 10,
                'type'  => 'checkbox',
            )
        ));

        function io_sanitize_checkbox( $checked ) {
            return ( ( isset( $checked ) && true == $checked ) ? true : false );
        }
    }
//add_action( 'customize_register', 'customtheme_customize_register_io', 11 );

//allows sync of elementor pages via meta tbl
#region REST API Endpoints

    /* Register post meta fields for REST API */
    function register_posts_meta_field() {
        $object_type = 'post';
        $args1 = array( // Validate and sanitize the meta value.
            // Note: currently (4.7) one of 'string', 'boolean', 'integer',
            // 'number' must be used as 'type'. The default is 'string'.
            'type'         => 'string',
            // Shown in the schema for the meta key.
            'description'  => 'A meta key associated with a string meta value.',
            // Return a single value of the type.
            'single'       => true,
            // Show in the WP REST API response. Default: false.
            'show_in_rest' => true,
            'auth_callback' => function() {
                return current_user_can( 'edit_posts' );
            },
        );
        register_meta( $object_type, '_elementor_data', $args1 );
        register_meta( $object_type, 'io_meta_description', $args1 );
    }

    /* Register site options endpoint - allows sync of analytics code (or any option) */
    function register_site_options() {
        register_rest_route( 'inflatableoffice/v1', '/options/(?P<id>[-_a-zA-Z0-9-]+)', array(
            'methods' => 'GET,POST',
            'callback' => 'io_options',
            'permission_callback' => function() {
                return current_user_can( 'edit_posts' );
                //     return true;
            },
        ) );
    }
    function io_options($data) {
        if($data->get_method()=='POST'){
            if($data['id']=='io_cart_time_format'){
                //$value = get_option($data['id']);
                //so we only run this if it's changed, but okay to run it every time
                //if($value<>$data->get_body()){
                //convert times. the sync handles this as well for start/end but not for the other time fields
                //it's good to have it in both places in case they aren't using newer plugin that has this
                $time = date($data->get_body(), strtotime(get_option('io_default_start_time')));
                update_option('io_default_start_time', $time);
                $time = date($data->get_body(), strtotime(get_option('io_default_end_time')));
                update_option('io_default_end_time', $time);
                $time = date($data->get_body(), strtotime(get_option('io_overnightPickupTime')));
                update_option('io_overnightPickupTime', $time);
                $time = date($data->get_body(), strtotime(get_option('io_restrictTimeStart')));
                update_option('io_restrictTimeStart', $time);
                $time = date($data->get_body(), strtotime(get_option('io_restrictTimeEnd')));
                update_option('io_restrictTimeEnd', $time);
                //}
            }
            update_option($data['id'],$data->get_body());
        }
        $value = get_option($data['id']);
        return $value;
    }

    /* IO-14955: Register social API endpoint - get/set option in wp_options */
    function register_social_api() {
        register_rest_route( 'inflatableoffice/v1', '/social_posts/(?P<id>[-_a-zA-Z0-9-]+)', array(
            'methods' => 'POST',
            'callback' => 'io_social_posts'
        ) );
    }

    /**
     * The call back for when the REST endpoint for marketing posts gets hit
     * $data['id'] = 'wp_options' table => 'option_name' field
     * @param $data
     * @return mixed
     */
    function io_social_posts(WP_REST_Request $request) {

        //Route data based on optionName param
        $params = $request->get_params();
        $optionName = urldecode($params['optionName']);

        switch($optionName) {
            case "io_gmb_access":

                require_once(dirname(__FILE__) . '/social_api_factory.php');

                $data = array
                (
                    'option_name' => $optionName,
                    'site_url'=> urldecode($params['siteURL']),
                    'rental_name' => urldecode($params['rentalName']),
                    'rental_description' => urldecode($params['rentalDescription']),
                    'rental_image' => urldecode($params['rentalImage']),
                    'rental_url' => urldecode($params['rentalURL']),
                    'category_name' => urldecode($params['categoryName']),
                    'category_description' => urldecode($params['categoryDescription']),
                    'category_image' => urldecode($params['categoryImage']),
                    'category_url' => urldecode($params['categoryURL']),
                );

                $logoURL = get_media_url_by_name('logoForGooglePosts.png');
                if ($logoURL)
                {
                    $data['hype_description'] = urldecode($params['hypeText']);
                    $data['hype_image'] = $logoURL;
                }

                //logging
                if (! update_option('io_gmb_rest_params', json_encode($data))){
                    add_option('io_gmb_rest_params', json_encode($data));
                }

                $gmb = social_api_factory::create("GoogleMyBusiness");

                return $gmb->createPost($data);
        }

    }

    /* Register testimonials API endpoint */
    function register_testimonials_api()
    {
        register_rest_route('inflatableoffice/v1', '/sync_testimonials', array
        (
            'methods' => 'POST',
            'callback' => 'io_sync_testimonials'
        ));
    }
    /**
     * The callback for when the REST endpoint for syncing testimonials gets hit.
     * @param WP_REST_Request $request
     * @return mixed
     */
    function io_sync_testimonials(WP_REST_Request $request)
    {
        $testimonials = $request->get_params();

        // Get the excluded testimonial IDs
        $excludedTestimonials = get_option('io_reviews_iotestimonials_exclusions', []);

        // Filter out excluded testimonials
        $filteredTestimonials = array_filter($testimonials, function($testimonial) use ($excludedTestimonials)
        {
            return !in_array($testimonial['testimonial_id'], $excludedTestimonials);
        });

        if (!update_option('io_reviews_iotestimonials', json_encode($filteredTestimonials)))
        {
            add_option('io_reviews_iotestimonials', json_encode($filteredTestimonials));
        }
    }

    /* Register disconnect endpoint */
    function register_connect_api() {
        register_rest_route('inflatableoffice/v1', '/connect', [
            'methods' => 'POST',
            'callback' => 'io_connect',
            'permission_callback' => function() {
                return current_user_can('edit_posts');
            }
        ]);
    }

    function io_connect(){
        $username = sanitize_text_field($_POST['username']);
        $password = sanitize_text_field($_POST['password']);

        if (empty($username) || empty($password)) {
            wp_send_json_error(['message' => 'Username and password are required']);
            return;
        }

        $api_url = 'https://rental.software/api6/authenticate';
        $response = wp_remote_post($api_url, [
            'timeout' => 30,
            'body' => [
                'username' => $username,
                'password' => $password,
                'wp_plugin' => 1
            ]
        ]);

        if (is_wp_error($response)) {
            wp_send_json_error(['message' => $response->get_error_message()]);
            return;
        }

        $response_body = wp_remote_retrieve_body($response);
        $response_code = wp_remote_retrieve_response_code($response);
        $response_data = json_decode($response_body, true);

        if ($response_code !== 200) {
            $error_message = isset($response_data['message']) ? $response_data['message'] : 'Authentication failed';
            wp_send_json_error(['message' => $error_message]);
            return;
        }

        // Return the API key and pages
        if (isset($response_data['apiKey'])) {
            wp_send_json_success($response_data);
        } else {
            wp_send_json_error(['message' => 'Error obtaining API Key']);
        }
    }

    /* Register disconnect endpoint */
    function register_disconnect_api() {
        register_rest_route('inflatableoffice/v1', '/disconnect', [
            'methods' => 'POST',
            'callback' => 'io_disconnect',
            'permission_callback' => function() {
                return current_user_can('edit_posts');
            }
        ]);
    }

    function io_disconnect(){
        delete_option('io_lead_apikey');
        delete_option('io_pagename');
        delete_option('io_username');

        wp_send_json_success("disconnected successfully");
    }

    /* Register save API key endpoint */
    function register_save_key_api() {
        register_rest_route('inflatableoffice/v1', '/save_key', [
            'methods' => 'POST',
            'callback' => 'io_save_api_key',
            'permission_callback' => function() {
                return current_user_can('edit_posts');
            }
        ]);
    }

    function io_save_api_key(){
        $api_key = sanitize_text_field($_POST['api_key']);
        $page_name = sanitize_text_field($_POST['page_name']);
        $user_name = sanitize_text_field($_POST['username']);


        if (empty($api_key) || empty($page_name)) {
            wp_send_json_error('No API key provided');
            return;
        }

        update_option('io_lead_apikey', $api_key);
        update_option('io_pagename', $page_name);
        update_option('io_username', $user_name);

        wp_send_json_success('API key saved successfully');
    }

    add_filter('determine_current_user', function($user_id){
        if (defined('REST_REQUEST') && REST_REQUEST) {
            $route = $_GET['rest_route'] ?? '';
            // Matches /wp-json/inflatableoffice/v1/lead
            if (strpos($route, '/inflatableoffice/v1/lead') === 0) {
                return 0; // treat as not-logged-in; avoids auth work
            }
        }
        return $user_id;
    }, 1);

    add_filter('rest_send_nocache_headers', function($send){
        if (defined('REST_REQUEST') && REST_REQUEST) {
            $route = $_GET['rest_route'] ?? '';
            if (strpos($route, '/inflatableoffice/v1/lead') === 0) {
                return false;
            }
        }
        return $send;
    });

    /* Register lead proxy endpoint */
    function register_lead_api() {
        register_rest_route('inflatableoffice/v1', '/lead', [
            'methods' => ['GET', 'POST'],
            'callback' => 'io_lead_proxy_handler',
            'permission_callback' => '__return_true'
        ]);
    }

    function io_lead_proxy_handler(WP_REST_Request $request) {
        // Get API key from WordPress option
        $io_lead_apikey = get_option('io_lead_apikey');


        // Validate API key
        if (empty($io_lead_apikey)) {
            return new WP_Error('invalid_api_key', 'Invalid API key', ['status' => 403]);
        }

        // Get the request body
        $body = $request->get_body();
        $data = $body;

        if (!$data) {
            return new WP_Error('invalid_request', 'Invalid request data', ['status' => 400]);
        }

        if(is_string($data)){
            $data = json_decode($data);
        }

        // Determine which API6 endpoint to call based on request data/method
        $action = 'get'; // default
        if ($request->get_method() === 'POST') {
            // Check if we have type parameter to determine create vs update
            if (isset($data->action) && !empty($data->action)) {
                $action = $data->action;
            }
        }

        // Determine the API6 URL
        $api_base = 'https://rental.software/api6/lead/';

        // Check for localhost (dev environment)
        if (strpos($_SERVER['HTTP_HOST'], 'localhost') !== false) {
            $api_base = 'http://localhost/io/bugs/api6/lead/';
            $io_lead_apikey = "1072c32fd1d2df2f1927a6f4656aea9a";
        }

        $api_url = $api_base . $action . '/?apiKey=' . urlencode($io_lead_apikey);

        // Make the API call to rental.software
        $response = wp_remote_post($api_url, [
            'headers' => [
                'Content-Type' => 'application/json'
            ],
            'body' => $body,
            'timeout' => 30
        ]);


        // Check for errors
        if (is_wp_error($response)) {
            return new WP_Error('api_error', $response->get_error_message(), ['status' => 500]);
        }

        // Get the response body
        $response_body = wp_remote_retrieve_body($response);
        $response_code = wp_remote_retrieve_response_code($response);

        // Decode and return the response
        $response_data = json_decode($response_body, true);

        if ($response_code !== 200) {
            return new WP_Error('api_error', 'API returned error', ['status' => $response_code, 'data' => $response_data]);
        }

        return rest_ensure_response($response_data);
    }

    /* Register clear Elementor cache endpoint */
    function register_clear_elementor_cache_api() {
        register_rest_route('inflatableoffice/v1', '/clear_elementor_cache', [
            'methods'             => 'POST',
            'permission_callback' => function() {
                return current_user_can('edit_posts');
            },
            'callback'            => function() {
                if ( ! class_exists( \Elementor\Plugin::class ) ) {
                    return new WP_Error( 'elementor_missing', 'Elementor plugin not installed/activated', [ 'status' => 404 ] );
                }

                $el = \Elementor\Plugin::instance();
                $caches_cleared = [];
                foreach ( [ 'files_manager', 'assets_manager' ] as $mgr ) {
                    if ( isset( $el->$mgr ) && is_callable( [ $el->$mgr, 'clear_cache' ] ) ) {
                        $el->$mgr->clear_cache();
                        $caches_cleared[] = $mgr;
                    }
                }

                return rest_ensure_response( [ 'success' => true, 'cleared' => $caches_cleared, 'code' => 200] );
            },
        ]);
    }

    /* Hook all REST API endpoints */
    add_action( 'rest_api_init', 'register_posts_meta_field' );
    add_action( 'rest_api_init', 'register_site_options' );
    add_action( 'rest_api_init', 'register_social_api' );
    add_action( 'rest_api_init', 'register_testimonials_api' );
    add_action( 'rest_api_init', 'register_connect_api' );
    add_action( 'rest_api_init', 'register_disconnect_api' );
    add_action( 'rest_api_init', 'register_save_key_api' );
    add_action( 'rest_api_init', 'register_lead_api' );
    add_action( 'rest_api_init', 'register_clear_elementor_cache_api' );

#endregion REST API Endpoints

    add_action('TentCalcSubmit', function(){
        $thing = 1;
    });

//add to the submit of the elementor form to call our contact us page
    /*
    add_action( 'elementor_pro/forms/new_record', "io_handle_elementor_form_submit", 10, 3);
    function io_handle_elementor_form_submit($record, $handler){
        $io_makeLeadsOnForms = get_option('io_makeLeadsOnForms');
        $io_excludeforms = get_option('io_excludeforms');
        $io_excludeforms_arr = array_map('trim', explode(',', $io_excludeforms));

        if($io_makeLeadsOnForms == 'on'){
            $form_name = $record->get_form_settings( 'form_name' );
            if(in_array($form_name,$io_excludeforms_arr)) return;
            $io_pagename = get_option('io_pagename');
            $page_name = urlencode($io_pagename);//'Demo+Rentals+LLC';
            $page_name = '&name='.$page_name;
            $link_params = '&elemCTA=1';
            // IO-28339 add additional
            $io_url_params = get_option('io_url_params');
            if($io_url_params) {
                $io_url_params = json_decode($io_url_params);
                foreach ($io_url_params as $io_url_param) {
                    if (isset($_COOKIE[$io_url_param->urlparam_cookiename])) {
                        $cookie_value = $_COOKIE[$io_url_param->urlparam_cookiename];
                        // Protect against XSS by only allowing alphanumeric characters and basic punctuation
                        if (preg_match('/^[a-zA-Z0-9\s\-_.,;:!?\'"\(\)]+$/', $cookie_value)) {
                            $link_params .= '&' . $io_url_param->urlparam_paramname . '=' . $cookie_value;
                        }
                    }
                }
            }


            $cust_ip = $_SERVER['REMOTE_ADDR'];
            if(!empty($_SERVER['HTTP_CLIENT_IP']) && filter_var($_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP)) $cust_ip = $_SERVER['HTTP_CLIENT_IP'];
            if(!empty($_SERVER['HTTP_X_FORWARDED_FOR']) && filter_var($_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP)) $cust_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
            if(!empty($_SERVER['HTTP_X_SUCURI_CLIENTIP']) && filter_var($_SERVER['HTTP_X_SUCURI_CLIENTIP'], FILTER_VALIDATE_IP)) $cust_ip = $_SERVER['HTTP_X_SUCURI_CLIENTIP'];
            $ips = explode(',', $cust_ip, 2);
            $cust_ip = urlencode(trim($ips[0]));
            $link_params .= '&io_custip='.$cust_ip.'&io_custguid='.urlencode($_COOKIE['guid']);

            $link = 'https://rental.software/quotes/contactme.php?nowrap=1'.$page_name.$link_params;
            //$link = 'http://localhost/io/bugs/quotes/contactme.php?nowrap=1'.$page_name.$link_params;
            $fields = Array();
            $raw_fields = $record->get( 'fields' );
            foreach ($raw_fields as $k=>$v){
                if($k=='name') $k='firstandlastname';
                if($k=='message') $k='notes';
                if($v['type']=='html') continue;
                if(strpos($k,'customfield_')!==FALSE) $k=str_replace('customfield_','customfield-',$k);
                $v = trim($v["value"]);

                //non-standard fields will additionally get appended to the notes
                // setupduration
                if(!in_array($k,Array('okToTextPresent','oktotext','startdate','starttime','enddate','endtime','taxexempt',
                        'eventname','salesrep','eventstreet','eventzip','eventcity','eventstate','deliverytype', 'street',
                        'zip','state','city','officephone','custtags','oktotext','firstandlastname','cellphone','email',
                        'firstname','lastname','eventorganization','notes','title', 'attachment', 'surface',
                        'elementor_statusid', 'utm_source', 'utm_medium', 'utm_campaign')) && strpos($k,'customfield-')===FALSE){
                    $fields['notes'] .= "\n".$k.': '.$v;
                }

                $fields[$k] .= $v;
            }
            $fields['notes'] = trim($fields['notes']);
            $fields['from_wp'] = 1;
            //$fields['notes'].="\nPage URL: ".$_POST['referrer'];

            $result = wp_safe_remote_post( $link, [
                'body' => $fields,
                'timeout' => 20
            ]);
            $result = json_decode($result['body']);
            if($result->redirect_url && empty($record->get_form_settings('redirect_to'))){
                $handler->add_response_data( 'redirect_url', $result->redirect_url );
            }
            //echo $result;
        }
    } */

//prevent sg optimizer from combining our js files otherwise it screws up the quote page (if that option is turned on)
    add_filter( 'sgo_javascript_combine_exclude_all_inline', '__return_true' );
    add_filter( 'sgo_javascript_combine_excluded_external_paths', 'js_combine_exclude_external_script' );
    function js_combine_exclude_external_script( $exclude_list ) {
        $exclude_list[] = 'rental.software';

        return $exclude_list;
    }

    add_action('admin_head-edit.php','add_remove_dupes_button');
    function add_remove_dupes_button(){
        global $current_screen;
        $username = get_option('io_username');
        $location_id = get_option('io_locationid');
        add_thickbox();

        if($current_screen->post_type == "page"){
            ?>
            <style>
                .io_load_spinner {
                    margin-left: 5px;
                    border: 5px solid #d4d3d3;
                    border-top: 5px solid #2271b1;
                    border-radius: 50%;
                    width: 16px;
                    height: 16px;
                    animation: spin 2s linear infinite;
                    display: none;
                }

                @keyframes spin {
                    0% { transform: rotate(0deg); }
                    100% { transform: rotate(360deg); }
                }
            </style>
            <script>
                jQuery(document).ready(function(){
                    let html = '<div style="display:inline-flex">' +
                        '<a title="Warning" href="#TB_inline?width=600&height=220&inlineId=io-remove-pages_warning" class="page-title-action thickbox">Remove Duplicate IO Pages</a>' +
                        '<div class="io_load_spinner"></div>' +
                        '</div>' +
                        '<div id="io-remove-pages_warning" style="display:none;">' +
                        '<p> Be aware. This is a fully automated process with NO human supervision. Pages you may not want removed may be moved to trash or deleted. If you are not hosted on an IO server be sure to make a backup of your site in case you need to restore.</p>' +
                        '<p> If you have a very large number of pages to sift through this process may take some time and will time out after 10 minutes. While the process is running do not close this page and do not attempt to start another.</p>' +
                        '<div style="width:100%;display: inline-flex;justify-content: space-between;">' +
                        '<button onClick="cancel_io_page_remove()">Cancel</button>' +
                        '<button onClick="remove_orphan_pages()" style="background-color: #d63638;border-color: #d63638;" class="button button-primary">I Understand. Proceed.</button></div></div>';
                    jQuery(html).insertBefore(".wp-header-end");
                    jQuery('#io_remove_dupe').on("click", remove_orphan_pages);
                });

                function cancel_io_page_remove(){
                    jQuery("#TB_closeWindowButton").trigger("click");
                }

                function remove_orphan_pages(){
                    jQuery("#TB_closeWindowButton").trigger("click");
                    jQuery(".io_load_spinner").show();
                    var params = "username=<?php echo $username ?>&location=<?php echo $location_id ?>&url=";
                    var domain = window.location.href.replace("/wp-admin/edit.php", "").split("?")[0];
                    params += domain;
                    var io_filter_dir = "<?php echo$_SERVER['SCRIPT_NAME'] ?>";
                    var io_filter_server_name = "<?php echo$_SERVER['SERVER_NAME'] ?>";
                    var io_filter_server_scheme = "<?php echo$_SERVER['REQUEST_SCHEME'] ?>";
                    var url = io_filter_server_scheme+"://"+io_filter_server_name+io_filter_dir.replace("/wp-admin/edit.php", "/wp-content/plugins/inflatableoffice-v2/remove_orphan_pages.php?");
                    url += params;
                    jQuery.ajax({
                        type: "POST",
                        url: url,
                        dataType: "text",
                        success: function(data){location.reload()},
                        error: function(data){location.reload()},
                        timeout: 600000 // 10 minute timer
                    });
                }

                function reload_after_remove(data){
                    window.location.reload();
                }
            </script>
            <?php
        }
    }

    add_action("add_meta_boxes", "add_custom_meta_box");
    function add_custom_meta_box(){
        add_meta_box("demo-meta-box", "InflatableOffice", "custom_meta_box_markup", "page", "side", "high", null);
    }

    function custom_meta_box_markup($object){
        wp_nonce_field(basename(__FILE__), "meta-box-nonce");
        $checkbox_value = get_post_meta($object->ID, "io-include-featured", true);

        if($checkbox_value == "")
        {
            ?>
            <input name="io-include-featured" type="checkbox" value="true">
            <label>Make this page selectable in IO Featured Product Widget</label>
            <?php
        }
        else if($checkbox_value == "true")
        {
            ?>
            <input name="io-include-featured" type="checkbox" value="true" checked>
            <label>Make this page selectable in IO Featured Product Widget</label>
            <?php
        }
    }
    add_action("save_post", "save_custom_meta_box", 10, 3);
    function save_custom_meta_box($post_id, $post, $update)
    {
        if (!isset($_POST["meta-box-nonce"]) || !wp_verify_nonce($_POST["meta-box-nonce"], basename(__FILE__)))
            return $post_id;

        if(!current_user_can("edit_post", $post_id))
            return $post_id;

        if(defined("DOING_AUTOSAVE") && DOING_AUTOSAVE)
            return $post_id;

        $slug = "page";
        if($slug != $post->post_type)
            return $post_id;

        $meta_box_checkbox_value = "";

        if(isset($_POST["io-include-featured"]))
        {
            $meta_box_checkbox_value = $_POST["io-include-featured"];
        }
        update_post_meta($post_id, "io-include-featured", $meta_box_checkbox_value);
    }

#region IO-27771 Improved Reviews II
    function enqueue_review_styles($hook)
    {
        if ($hook === 'inflatableoffice_page_io_reviews')
        {
            wp_enqueue_style('bootstrap-css', 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css');
            wp_enqueue_script('popper-js', 'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js', array('jquery'), null, true);
            wp_enqueue_script('bootstrap-js', 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js', array('jquery'), null, true);
            wp_enqueue_style('font-awesome', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css');
        }
    }
    add_action('admin_enqueue_scripts', 'enqueue_review_styles');

    function register_io_reviews_widget()
    {
        require_once( __DIR__ . '/widget-reviews.php' );
    }
    add_action( 'elementor/widgets/widgets_registered', 'register_io_reviews_widget' );

    function enqueue_slick_carousel()
    {
        wp_enqueue_style( 'slick-carousel-css', 'https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.css' );
        wp_enqueue_style( 'slick-carousel-theme-css', 'https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick-theme.min.css' );
        wp_enqueue_script( 'slick-carousel-js', 'https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.js', [ 'jquery' ], '1.8.1', true );
    }
    add_action( 'wp_enqueue_scripts', 'enqueue_slick_carousel' );


    function enqueue_dashicons()
    {
        wp_enqueue_style('dashicons');
    }
    add_action('wp_enqueue_scripts', 'enqueue_dashicons');

    function schedule_import_google_reviews_cron()
    {
        if ( ! wp_next_scheduled( 'import_new_google_reviews_hook' ) )
        {
            wp_schedule_event( time(), 'hourly', 'import_new_google_reviews_hook' );
        }
    }
    add_action( 'wp_loaded', 'schedule_import_google_reviews_cron' );

    function import_google_reviews_cron()
    {
        $last_run = get_option('io_reviews_last_import_run', 0);
        $current_time = time();
        $one_day = 24 * 60 * 60; // 24 hours in seconds

        if (($current_time - $last_run) < $one_day)
        {
            return; // Exit early if less than 24 hours since last run
        }

        $controller_file_path = plugin_dir_path( __FILE__ ) . 'reviews/controller.php';

        if ( file_exists( $controller_file_path ) )
        {
            require_once $controller_file_path;

            if (class_exists('IO_Reviews_Admin_Page'))
            {
                $admin_page = new IO_Reviews_Admin_Page();
                if (method_exists($admin_page, 'check_reviews'))
                {
                    $admin_page->check_reviews();
                }
            }
        }
    }
    add_action( 'import_new_google_reviews_hook', 'import_google_reviews_cron' );

#endregion IO-27771


    add_filter('autoptimize_filter_noptimize','stop_autoptimize_on_quote_page',10,1);
    function stop_autoptimize_on_quote_page($flag) {
        if (strpos($_SERVER['REQUEST_URI'],'io_')!== false) {
            return true;
        } else {
            return $flag;
        }
    }


    add_filter( 'sgs_whitelist_wp_content' , 'whitelist_filter_file_in_wp_content' );
    function whitelist_filter_file_in_wp_content( $whitelist ) {
        $whitelist[] = 'remove_orphan_pages.php';
        $whitelist[] = 'website_filter.php';
        $whitelist[] = 'TentCalcSubmit.php';
        $whitelist[] = 'login.php';
        return $whitelist;
    }

    function io_get_variable($atts){
        return $_GET[$atts['name']];
    }
    add_shortcode( 'io_get_variable', 'io_get_variable');

    function get_media_url_by_name($file_name)
    {
        global $wpdb;

// Remove the file extension
        $file_name_without_extension = pathinfo($file_name, PATHINFO_FILENAME);

        $query = $wpdb->prepare("
        SELECT ID
        FROM {$wpdb->prefix}posts
        WHERE post_type = 'attachment'
        AND post_mime_type LIKE 'image/%'
        AND post_title = %s
        LIMIT 1
    ", $file_name_without_extension);

        $attachment_id = $wpdb->get_var($query);

        if ($attachment_id)
        {
            return wp_get_attachment_url($attachment_id);
        }
        else
        {
            return false;
        }
    }
}