<?php

// Exit if accessed directly
if ( !defined( 'ABSPATH' ) ) {
    exit;
}
//----------------------------------------------------------------------------------------
// Load translations
//----------------------------------------------------------------------------------------
add_action( 'plugins_loaded', 'teoai_load_plugin_textdomain' );
function teoai_load_plugin_textdomain() {
    load_plugin_textdomain( 'events-optimizer', false, plugin_basename( dirname( __FILE__ ) ) . '/languages/' );
}

if ( !function_exists( 'teoai_user_has_access' ) ) {
    function teoai_user_has_access() {
        if ( current_user_can( 'administrator' ) ) {
            return true;
        }
        $allowed_option = get_option( 'teoai_allowed_role', array() );
        $allowed_roles = array();
        if ( is_array( $allowed_option ) ) {
            $allowed_roles = $allowed_option;
        } elseif ( !empty( $allowed_option ) ) {
            $allowed_roles = array($allowed_option);
        }
        foreach ( $allowed_roles as $role ) {
            if ( current_user_can( sanitize_key( $role ) ) ) {
                return true;
            }
        }
        return false;
    }

}
//----------------------------------------------------------------------------------------
// Initialize menu and settings
//----------------------------------------------------------------------------------------
require_once plugin_dir_path( __FILE__ ) . 'settings-page.php';
// Add Optimizer menu in WordPress dashboard (as child of Freemius top-level)
add_action( 'admin_menu', 'teoai_initialize_menu' );
add_action( 'admin_menu', 'teoai_add_settings_submenu', 20 );
add_filter( 'custom_menu_order', 'teoai_menu_order' );
add_filter( 'menu_order', 'teoai_menu_order' );
function teoai_initialize_menu() {
    // Check if the user has the necessary permissions
    if ( ( function_exists( 'teoai_user_has_access' ) ? teoai_user_has_access() : current_user_can( 'administrator' ) ) ) {
        // Add the menu to the WordPress Dashboard (top-level label) and primary page title.
        $my_page = add_menu_page(
            'Check & Clean Data',
            'Events Optimizer',
            'read',
            'events_optimizer',
            'teoai_events_optimizer_menu',
            'dashicons-calendar'
        );
        add_submenu_page(
            'events_optimizer',
            esc_html__( 'Check & Clean Data', 'events-optimizer' ),
            esc_html__( 'Check & Clean Data', 'events-optimizer' ),
            'read',
            'events_optimizer',
            'teoai_events_optimizer_menu'
        );
        $import_events_page = add_submenu_page(
            'events_optimizer',
            esc_html__( 'Manually Import Events', 'events-optimizer' ),
            esc_html__( 'Manually Import Events', 'events-optimizer' ),
            'read',
            'events_optimizer_import_events',
            'teoai_import_events_submenu_page'
        );
        // Call register settings function
        add_action( 'admin_init', 'teoai_register_settings' );
        // Load the JS conditionally (see next function below)
        add_action( 'load-' . $my_page, 'teoai_load_admin_js' );
        add_action( 'load-' . $import_events_page, 'teoai_load_admin_js' );
    }
}

function teoai_add_settings_submenu() {
    if ( !(( function_exists( 'teoai_user_has_access' ) ? teoai_user_has_access() : current_user_can( 'administrator' ) )) ) {
        return;
    }
    $settings_page = add_submenu_page(
        'events_optimizer',
        esc_html__( 'Settings', 'events-optimizer' ),
        esc_html__( 'Settings', 'events-optimizer' ),
        'read',
        'events_optimizer_settings',
        'teoai_settings_submenu_page'
    );
    add_action( 'load-' . $settings_page, 'teoai_load_admin_js' );
}

// Function to adjust menu order so that Events Optimizer appears below The Events Calendar
function teoai_menu_order(  $menu_order  ) {
    if ( !$menu_order ) {
        return true;
    }
    $events_calendar_slug = 'edit.php?post_type=tribe_events';
    $events_optimizer_slug = 'events_optimizer';
    $events_position = array_search( $events_calendar_slug, $menu_order, true );
    $optimizer_position = array_search( $events_optimizer_slug, $menu_order, true );
    if ( $events_position === false || $optimizer_position === false ) {
        return $menu_order;
    }
    unset($menu_order[$optimizer_position]);
    array_splice(
        $menu_order,
        $events_position + 1,
        0,
        $events_optimizer_slug
    );
    return array_values( $menu_order );
}

// Function to render the Events Optimizer settings tabs
function teoai_settings_submenu_page() {
    $nonce = wp_create_nonce( 'events-optimizer-nonce' );
    ?>
		<div class='wrap'>
			<h1 class="wp-heading-inline"><?php 
    esc_html_e( 'Settings', 'events-optimizer' );
    ?></h1>
			<?php 
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- tab selection is read-only and sanitized.
    $active_tab = ( isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : 'tab-general' );
    if ( !in_array( $active_tab, array(
        'tab-ignored-fields-objects',
        'tab-api-credentials',
        'tab-general',
        'tab-google-places',
        'tab-google-images',
        'tab-google-events',
        'tab-ai-content-generation',
        'tab-security'
    ), true ) ) {
        $active_tab = 'tab-general';
    }
    ?>
			<div class="nav-tab-wrapper">
				<a href="<?php 
    echo esc_url( admin_url( 'admin.php?page=events_optimizer_settings&tab=tab-general' ) );
    ?>" class="nav-tab<?php 
    echo ( $active_tab === 'tab-general' ? ' nav-tab-active' : '' );
    ?>" data-slug='tab-general'><?php 
    esc_html_e( 'General', 'events-optimizer' );
    ?></a>
				<a href="<?php 
    echo esc_url( admin_url( 'admin.php?page=events_optimizer_settings&tab=tab-ai-content-generation' ) );
    ?>" class="nav-tab<?php 
    echo ( $active_tab === 'tab-ai-content-generation' ? ' nav-tab-active' : '' );
    ?>" data-slug='tab-ai-content-generation'><?php 
    esc_html_e( 'AI Content Generation', 'events-optimizer' );
    ?></a>
				<a href="<?php 
    echo esc_url( admin_url( 'admin.php?page=events_optimizer_settings&tab=tab-api-credentials' ) );
    ?>" class="nav-tab<?php 
    echo ( $active_tab === 'tab-api-credentials' ? ' nav-tab-active' : '' );
    ?>" data-slug='tab-api-credentials'><?php 
    esc_html_e( 'API Credentials', 'events-optimizer' );
    ?></a>
				<a href="<?php 
    echo esc_url( admin_url( 'admin.php?page=events_optimizer_settings&tab=tab-google-places' ) );
    ?>" class="nav-tab<?php 
    echo ( $active_tab === 'tab-google-places' ? ' nav-tab-active' : '' );
    ?>" data-slug='tab-google-places'><?php 
    esc_html_e( 'Google Places', 'events-optimizer' );
    ?></a>
				<a href="<?php 
    echo esc_url( admin_url( 'admin.php?page=events_optimizer_settings&tab=tab-google-images' ) );
    ?>" class="nav-tab<?php 
    echo ( $active_tab === 'tab-google-images' ? ' nav-tab-active' : '' );
    ?>" data-slug='tab-google-images'><?php 
    esc_html_e( 'Google Images', 'events-optimizer' );
    ?></a>
				<a href="<?php 
    echo esc_url( admin_url( 'admin.php?page=events_optimizer_settings&tab=tab-google-events' ) );
    ?>" class="nav-tab<?php 
    echo ( $active_tab === 'tab-google-events' ? ' nav-tab-active' : '' );
    ?>" data-slug='tab-google-events'><?php 
    esc_html_e( 'Google Events', 'events-optimizer' );
    ?></a>
				<a href="<?php 
    echo esc_url( admin_url( 'admin.php?page=events_optimizer_settings&tab=tab-ignored-fields-objects' ) );
    ?>" class="nav-tab<?php 
    echo ( $active_tab === 'tab-ignored-fields-objects' ? ' nav-tab-active' : '' );
    ?>" data-slug='tab-ignored-fields-objects'><?php 
    esc_html_e( 'Ignored Fields & Objects', 'events-optimizer' );
    ?></a>
				<a href="<?php 
    echo esc_url( admin_url( 'admin.php?page=events_optimizer_settings&tab=tab-security' ) );
    ?>" class="nav-tab<?php 
    echo ( $active_tab === 'tab-security' ? ' nav-tab-active' : '' );
    ?>" data-slug='tab-security'><?php 
    esc_html_e( 'Security', 'events-optimizer' );
    ?></a>
			</div>
			<?php 
    teoai_render_settings_page( $nonce, $active_tab );
    ?>
		</div>
		<?php 
}

//----------------------------------------------------------------------------------------
// This function is only called when the Event Optimizers page is loaded
// https://wordpress.stackexchange.com/questions/41207/how-do-i-enqueue-styles-scripts-on-certain-wp-admin-pages
//----------------------------------------------------------------------------------------
function teoai_load_admin_js() {
    // Register against the proper action hook
    add_action( 'admin_enqueue_scripts', 'teoai_enqueue_admin_js' );
}

//----------------------------------------------------------------------------------------
// Include CSS and JavaScript files only when the Event Optimizer page is loaded
//----------------------------------------------------------------------------------------
function teoai_enqueue_admin_js() {
    // Plugin assets.
    // Load the scripts that have been registered above
    wp_enqueue_script(
        'teoai-tabs',
        plugin_dir_url( __FILE__ ) . 'assets/js/tabs.js',
        array(),
        '2.0.0',
        true
    );
    wp_enqueue_style(
        'teoai-style',
        plugin_dir_url( __FILE__ ) . 'assets/css/style.css',
        array(),
        '2.0.0'
    );
    // Select2 (bundled) for searchable selects on settings page.
    wp_enqueue_script(
        'teoai-select2',
        plugin_dir_url( __FILE__ ) . 'assets/vendor/select2/js/select2.min.js',
        array('jquery'),
        '4.1.0',
        true
    );
    wp_enqueue_style(
        'teoai-select2',
        plugin_dir_url( __FILE__ ) . 'assets/vendor/select2/css/select2.min.css',
        array(),
        '4.1.0'
    );
}

// Class for creating a standard WordPress table with pagination
if ( !class_exists( 'WP_List_Table' ) ) {
    require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
//----------------------------------------------------------------------------------------
// Sanitize allowed roles option (array of role slugs).
// @param mixed $value Submitted value.
// @return array Sanitized role slugs.
//----------------------------------------------------------------------------------------
function teoai_sanitize_allowed_roles(  $value  ) {
    $roles = ( is_array( $value ) ? $value : (array) $value );
    return array_filter( array_map( 'sanitize_key', $roles ) );
}

//----------------------------------------------------------------------------------------
// Register settings
//----------------------------------------------------------------------------------------
function teoai_register_settings() {
    // Abort early if The Events Calendar functions are unavailable.
    if ( !function_exists( 'tribe_get_option' ) ) {
        return;
    }
    // Basic settings for free version
    register_setting( 'events-optimizer-settings', 'teoai_max_results_per_page', array(
        'type'              => 'integer',
        'sanitize_callback' => 'intval',
        'default'           => 5,
    ) );
    //register_setting( 'events-optimizer-settings', 'teoai_remove_settings' );
    // Set default values
    if ( !get_option( 'teoai_max_results_per_page' ) ) {
        update_option( 'teoai_max_results_per_page', 5 );
    }
    //if ( ! get_option( 'teoai_remove_settings' ) ) update_option( 'teoai_remove_settings', 0 );
    // Get language ISO Code from Wordpress to prefill Google Places API / DataForSEO language field
    $lang = explode( '-', get_bloginfo( 'language' ) )[0];
    if ( !get_option( 'teoai_google_places_language' ) ) {
        update_option( 'teoai_google_places_language', $lang );
    }
    if ( !get_option( 'teoai_dataforseo_language_code' ) ) {
        update_option( 'teoai_dataforseo_language_code', $lang );
    }
    // Get Google Maps API key from The Events Calendar to prefill Google Places API key field
    $google_maps_api_key = tribe_get_option( 'google_maps_js_api_key' );
    if ( !get_option( 'teoai_google_places_api_key' ) ) {
        update_option( 'teoai_google_places_api_key', $google_maps_api_key );
    }
    // Activate only for Pro version
    //if ( teoai_fs()->can_use_premium_code__premium_only() ) {
    register_setting( 'events-optimizer-settings', 'teoai_duplicate_organizers_levenshtein', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_duplicate_venues_levenshtein', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_element_id', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_google_places_language', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_google_places_api_key', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_dataforseo_keyword', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_dataforseo_depth', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_dataforseo_api_login', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_dataforseo_api_password', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_dataforseo_location_code', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_dataforseo_location_label', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_dataforseo_language_code', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_dataforseo_date_range', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    //		register_setting( 'events-optimizer-settings', 'teoai_dataforseo_task_id' );
    register_setting( 'events-optimizer-settings', 'teoai_dataforseo_task', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_cleanup_completed_runs_after_days', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_cleanup_problem_runs_after_days', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_prefill_currency_symbol', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_max_images', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_openai_api_key', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_openai_model', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_openai_max_tokens', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_openai_language', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_openai_prompt_tone', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_openai_prompt_headings', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_openai_prompt_faq', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_openai_prompt_html', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_openai_prompt_emojis', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_openai_prompt_use_website', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_openai_replace_content', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_openai_hide_generate_description_buttons', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_google_safe_browsing', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_validate_url', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_phone_number_format', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_address_format', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_preselection', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_objects', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_show_ignored_objects', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_and_added_objects', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_show_added_objects', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_venue_description', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_venue_address', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_venue_zip', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_venue_city', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_venue_province', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_venue_state', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_venue_country', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_venue_phone', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_venue_website', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_venue_business_status', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_organizer_description', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_organizer_phone', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_organizer_website', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_organizer_mail', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_organizer_business_status', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_event_description', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_event_start', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_event_end', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_event_website', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_event_cost', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_event_currency_symbol', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_event_venue', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_field_event_organizer', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_ignored_objects', array(
        'sanitize_callback' => 'sanitize_text_field',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_show_ignored_objects', array(
        'sanitize_callback' => 'rest_sanitize_boolean',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_show_added_objects', array(
        'sanitize_callback' => 'rest_sanitize_boolean',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_allowed_role', array(
        'sanitize_callback' => 'teoai_sanitize_allowed_roles',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_notice_plugin_activated', array(
        'sanitize_callback' => 'rest_sanitize_boolean',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_notice_plugin_updated', array(
        'sanitize_callback' => 'rest_sanitize_boolean',
    ) );
    register_setting( 'events-optimizer-settings', 'teoai_notice_menu_moved', array(
        'sanitize_callback' => 'rest_sanitize_boolean',
    ) );
    // Set default values
    if ( !get_option( 'teoai_duplicate_organizers_levenshtein' ) ) {
        update_option( 'teoai_duplicate_organizers_levenshtein', 0.3 );
    }
    if ( !get_option( 'teoai_duplicate_venues_levenshtein' ) ) {
        update_option( 'teoai_duplicate_venues_levenshtein', 0.35 );
    }
    if ( !get_option( 'teoai_phone_number_format' ) ) {
        update_option( 'teoai_phone_number_format', 'international_phone_number' );
    }
    if ( !get_option( 'teoai_address_format' ) ) {
        update_option( 'teoai_address_format', 'street_number' );
    }
    if ( !get_option( 'teoai_preselection' ) ) {
        update_option( 'teoai_preselection', 'auto_completion' );
    }
    if ( !get_option( 'teoai_dataforseo_keyword' ) ) {
        update_option( 'teoai_dataforseo_keyword', '' );
    }
    if ( !get_option( 'teoai_dataforseo_depth' ) ) {
        update_option( 'teoai_dataforseo_depth', 10 );
    }
    if ( !get_option( 'teoai_cleanup_completed_runs_after_days' ) ) {
        update_option( 'teoai_cleanup_completed_runs_after_days', 30 );
    }
    if ( !get_option( 'teoai_cleanup_problem_runs_after_days' ) ) {
        update_option( 'teoai_cleanup_problem_runs_after_days', 60 );
    }
    if ( !get_option( 'teoai_prefill_currency_symbol' ) ) {
        update_option( 'teoai_prefill_currency_symbol', 'true' );
    }
    if ( !get_option( 'teoai_max_images' ) ) {
        update_option( 'teoai_max_images', 10 );
    }
    if ( !get_option( 'teoai_openai_model' ) ) {
        update_option( 'teoai_openai_model', 'gpt-4.1-mini' );
    }
    if ( !get_option( 'teoai_openai_max_tokens' ) ) {
        update_option( 'teoai_openai_max_tokens', 2048 );
    }
    if ( !get_option( 'teoai_openai_language' ) ) {
        update_option( 'teoai_openai_language', 'English, United States' );
    }
    if ( !get_option( 'teoai_openai_prompt_tone' ) ) {
        update_option( 'teoai_openai_prompt_tone', '- no specific tone -' );
    }
    if ( !get_option( 'teoai_openai_prompt_headings' ) ) {
        update_option( 'teoai_openai_prompt_headings', 'true' );
    }
    if ( !get_option( 'teoai_openai_prompt_faq' ) ) {
        update_option( 'teoai_openai_prompt_faq', 'true' );
    }
    if ( !get_option( 'teoai_openai_prompt_html' ) ) {
        update_option( 'teoai_openai_prompt_html', 'true' );
    }
    if ( !get_option( 'teoai_openai_prompt_use_website' ) ) {
        update_option( 'teoai_openai_prompt_use_website', 'false' );
    }
    if ( !get_option( 'teoai_openai_replace_content' ) ) {
        update_option( 'teoai_openai_replace_content', 'false' );
    }
    if ( !get_option( 'teoai_openai_hide_generate_description_buttons' ) ) {
        update_option( 'teoai_openai_hide_generate_description_buttons', 'false' );
    }
    if ( !get_option( 'teoai_google_safe_browsing' ) ) {
        update_option( 'teoai_google_safe_browsing', 'true' );
    }
    if ( !get_option( 'teoai_validate_url_https' ) ) {
        update_option( 'teoai_validate_url_https', 'true' );
    }
    if ( !get_option( 'teoai_validate_url_redirected_moved' ) ) {
        update_option( 'teoai_validate_url_redirected_moved', 'true' );
    }
    if ( !get_option( 'teoai_validate_url' ) ) {
        update_option( 'teoai_validate_url', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_venue_description' ) ) {
        update_option( 'teoai_ignored_field_venue_description', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_venue_address' ) ) {
        update_option( 'teoai_ignored_field_venue_address', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_venue_zip' ) ) {
        update_option( 'teoai_ignored_field_venue_zip', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_venue_city' ) ) {
        update_option( 'teoai_ignored_field_venue_city', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_venue_province' ) ) {
        update_option( 'teoai_ignored_field_venue_province', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_venue_state' ) ) {
        update_option( 'teoai_ignored_field_venue_state', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_venue_country' ) ) {
        update_option( 'teoai_ignored_field_venue_country', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_venue_phone' ) ) {
        update_option( 'teoai_ignored_field_venue_phone', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_venue_website' ) ) {
        update_option( 'teoai_ignored_field_venue_website', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_venue_business_status' ) ) {
        update_option( 'teoai_ignored_field_venue_business_status', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_organizer_description' ) ) {
        update_option( 'teoai_ignored_field_organizer_description', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_organizer_phone' ) ) {
        update_option( 'teoai_ignored_field_organizer_phone', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_organizer_website' ) ) {
        update_option( 'teoai_ignored_field_organizer_website', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_organizer_mail' ) ) {
        update_option( 'teoai_ignored_field_organizer_mail', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_organizer_business_status' ) ) {
        update_option( 'teoai_ignored_field_organizer_business_status', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_event_description' ) ) {
        update_option( 'teoai_ignored_field_event_description', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_event_start' ) ) {
        update_option( 'teoai_ignored_field_event_start', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_event_end' ) ) {
        update_option( 'teoai_ignored_field_event_end', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_event_venue' ) ) {
        update_option( 'teoai_ignored_field_event_venue', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_event_organizer' ) ) {
        update_option( 'teoai_ignored_field_event_organizer', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_event_website' ) ) {
        update_option( 'teoai_ignored_field_event_website', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_event_currency_symbol' ) ) {
        update_option( 'teoai_ignored_field_event_currency_symbol', 'false' );
    }
    if ( !get_option( 'teoai_ignored_field_event_cost' ) ) {
        update_option( 'teoai_ignored_field_event_cost', 'false' );
    }
    if ( !get_option( 'teoai_show_ignored_objects' ) ) {
        update_option( 'teoai_show_ignored_objects', 'false' );
    }
    if ( !get_option( 'teoai_show_added_objects' ) ) {
        update_option( 'teoai_show_added_objects', 'false' );
    }
    if ( !get_option( 'teoai_allowed_role' ) ) {
        update_option( 'teoai_allowed_role', array() );
    }
    if ( !get_option( 'teoai_notice_plugin_activated' ) ) {
        update_option( 'teoai_notice_plugin_activated', false );
    }
    if ( !get_option( 'teoai_notice_plugin_updated' ) ) {
        update_option( 'teoai_notice_plugin_updated', false );
    }
    // teoai_notice_menu_moved is not allowed to have a default value here, otherwise the notice won't show up when needed.
    // Just to test update notices in the WordPress dashboard
    // update_option( 'teoai_notice_plugin_activated', true );
    // update_option( 'teoai_notice_plugin_updated', true );
    // update_option( 'teoai_notice_menu_moved', true );
    //}
}

//----------------------------------------------------------------------------------------
// Register and enque scripts for admin notices
//----------------------------------------------------------------------------------------
add_action( 'admin_enqueue_scripts', 'teoai_add_scripts' );
function teoai_add_scripts(  $hook  ) {
    // Safety check: only load in admin area, not during AJAX calls
    if ( !is_admin() || wp_doing_ajax() ) {
        return;
    }
    // Optional: only load on Events Optimizer pages and Dashboard & Plugins pages
    if ( strpos( $hook, 'events_optimizer' ) === false && $hook !== 'index.php' && $hook !== 'plugins.php' ) {
        return;
    }
    // Scripts are automatically registered when they are enqueued
    wp_enqueue_script(
        'teoai-sanitize',
        plugin_dir_url( __FILE__ ) . 'assets/js/sanitize.js',
        array(),
        '1.0',
        true
    );
    wp_enqueue_script(
        'teoai-admin-notices',
        plugin_dir_url( __FILE__ ) . 'assets/js/admin-notices.js',
        array('jquery'),
        '1.3',
        true
    );
    wp_localize_script( 'teoai-admin-notices', 'notice_params', array(
        'ajaxurl' => admin_url( 'admin-ajax.php' ),
    ) );
}

//----------------------------------------------------------------------------------------
// After plugin has been activated or updated show notices in WordPress Dashboard
//----------------------------------------------------------------------------------------
// Use main plugin file for activation hook so it triggers when the plugin is activated.
register_activation_hook( plugin_dir_path( __FILE__ ) . 'events-optimizer.php', 'teoai_show_notice_plugin_activated' );
function teoai_show_notice_plugin_activated() {
    update_option( 'teoai_notice_plugin_activated', 'true' );
}

add_action(
    'upgrader_process_complete',
    'teoai_show_notice_plugin_updated',
    10,
    2
);
function teoai_show_notice_plugin_updated(  $upgrader_object, $options  ) {
    if ( empty( $options['action'] ) || $options['action'] !== 'update' || empty( $options['type'] ) || $options['type'] !== 'plugin' || empty( $options['plugins'] ) || !is_array( $options['plugins'] ) ) {
        return;
    }
    $current_plugin = plugin_basename( __FILE__ );
    foreach ( $options['plugins'] as $plugin ) {
        if ( $plugin === $current_plugin ) {
            update_option( 'teoai_notice_plugin_updated', 'true' );
            break;
        }
    }
}

//----------------------------------------------------------------------------------------
// Messages to show for admin in WordPress Dashboard
//----------------------------------------------------------------------------------------
add_action( 'admin_notices', 'teoai_admin_notices' );
function teoai_admin_notices() {
    // Safety & capability checks
    if ( !is_admin() || wp_doing_ajax() ) {
        return;
    }
    if ( !current_user_can( 'manage_options' ) ) {
        return;
    }
    if ( !function_exists( 'is_plugin_active' ) ) {
        require_once ABSPATH . 'wp-admin/includes/plugin.php';
    }
    if ( !function_exists( 'teoai_fs' ) ) {
        return;
    }
    // ------------------------------------------------------------------
    // Notice only for version 2.0.0 – menu moved and settings overhauled
    // ------------------------------------------------------------------
    // Detect version change ONCE and set notice flag
    if ( !function_exists( 'get_plugin_data' ) ) {
        require_once ABSPATH . 'wp-admin/includes/plugin.php';
    }
    $plugin_data = get_plugin_data( plugin_dir_path( __FILE__ ) . 'events-optimizer.php' );
    $current_version = $plugin_data['Version'] ?? '';
    $last_seen_version = get_option( 'teoai_last_seen_version', '' );
    // Show the "menu moved" notice only once for version 2.0.0; keep it until dismissed.
    $menu_notice = get_option( 'teoai_notice_menu_moved', null );
    if ( $current_version && version_compare( $current_version, '2.0.0', '=' ) && is_null( $menu_notice ) ) {
        update_option( 'teoai_notice_menu_moved', true );
    }
    // Track last seen version for other uses.
    if ( $current_version && version_compare( $current_version, $last_seen_version, '>' ) ) {
        update_option( 'teoai_last_seen_version', $current_version );
    }
    // Show the "menu moved" notice
    if ( filter_var( get_option( 'teoai_notice_menu_moved', false ), FILTER_VALIDATE_BOOLEAN ) ) {
        $settings_url = esc_url( admin_url( 'admin.php?page=events_optimizer_settings' ) );
        printf( '<div class="notice notice-success is-dismissible teoai-notice-menu-moved" data-teoai-dismiss="menu_moved">
					<p>%s</p>
				</div>', wp_kses( sprintf(
            '%s <a href="%s">%s</a> %s',
            esc_html__( 'Events Optimizer has a new home - you will find it directly in the Dashboard now.', 'events-optimizer' ),
            $settings_url,
            esc_html__( 'Please review the settings', 'events-optimizer' ),
            esc_html__( '— they have been completely overhauled.', 'events-optimizer' )
        ), [
            'a' => [
                'href' => [],
            ],
        ] ) );
    }
    // ------------------------------------------------------------------
    // First activation notice
    // ------------------------------------------------------------------
    if ( filter_var( get_option( 'teoai_notice_plugin_activated', false ), FILTER_VALIDATE_BOOLEAN ) ) {
        $settings_url = esc_url( admin_url( 'admin.php?page=events_optimizer_settings&tab=tab-api-credentials' ) );
        printf( '<div class="notice notice-success is-dismissible teoai-notice-plugin-activated" data-teoai-dismiss="plugin_activated">
					<p>%s</p>
				</div>', wp_kses( sprintf(
            '%s <a href="%s">%s</a>',
            esc_html__( 'Events Optimizer was installed successfully!', 'events-optimizer' ),
            $settings_url,
            esc_html__( 'Set up your API credentials now and review the settings.', 'events-optimizer' )
        ), [
            'a' => [
                'href' => [],
            ],
        ] ) );
    }
    // ------------------------------------------------------------------
    // Dependency notice: The Events Calendar missing
    // ------------------------------------------------------------------
    if ( !is_plugin_active( 'the-events-calendar/the-events-calendar.php' ) ) {
        $tec_url = esc_url( admin_url( 'plugin-install.php?tab=plugin-information&plugin=the-events-calendar&TB_iframe=true&width=772&height=778' ) );
        printf( '<div class="notice notice-error is-dismissible"><p>%s</p></div>', wp_kses( sprintf(
            '%s <a href="%s" class="thickbox">%s</a> %s',
            esc_html__( 'The Events Calendar plugin is not activated!', 'events-optimizer' ),
            $tec_url,
            esc_html__( 'Please install and activate it', 'events-optimizer' ),
            esc_html__( 'before using Events Optimizer.', 'events-optimizer' )
        ), [
            'a' => [
                'href'  => [],
                'class' => [],
            ],
        ] ) );
    }
}

//----------------------------------------------------------------------------------------
// If notices are dismissed don't show it again:
// use AJAX to dismiss the notice ( => admin-notices.js)
//----------------------------------------------------------------------------------------
add_action( 'wp_ajax_teoai_dismiss_notice_plugin_activated', function () {
    update_option( 'teoai_notice_plugin_activated', false );
    wp_send_json_success();
} );
add_action( 'wp_ajax_teoai_dismiss_notice_plugin_updated', function () {
    update_option( 'teoai_notice_plugin_updated', false );
    wp_send_json_success();
} );
add_action( 'wp_ajax_teoai_dismiss_notice_menu_moved', function () {
    update_option( 'teoai_notice_menu_moved', false );
    wp_send_json_success();
} );
//----------------------------------------------------------------------------------------
// Create tabs for the submenu
//----------------------------------------------------------------------------------------
function teoai_events_optimizer_menu() {
    // Check if the user has the necessary permissions
    if ( !teoai_user_has_access() ) {
        wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'events-optimizer' ) );
    }
    // Get settings
    $max_results_per_page = intval( get_option( 'teoai_max_results_per_page', 5 ) );
    $phone_number_format = sanitize_text_field( get_option( 'teoai_phone_number_format' ) );
    $address_format = sanitize_text_field( get_option( 'teoai_address_format' ) );
    $preselection = sanitize_text_field( get_option( 'teoai_preselection' ) );
    $nonce = wp_create_nonce( 'events-optimizer-nonce' );
    // Create submenu
    ?>
		<div class='wrap'>	
			<h1 class="wp-heading-inline"><?php 
    esc_html_e( 'Check & Clean Data', 'events-optimizer' );
    ?></h1>
		
			<?php 
    if ( version_compare( phpversion(), '8.0', '>=' ) ) {
        // PHP 8.0 and above
        $active_tab = filter_input( INPUT_GET, 'tab', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
    } else {
        // PHP 7.4 and below
        $active_tab = filter_input( INPUT_GET, 'tab', FILTER_SANITIZE_STRING );
    }
    if ( !in_array( $active_tab, ['tab-venues', 'tab-organizers', 'tab-events'] ) ) {
        $active_tab = 'tab-venues';
    }
    ?>

			<!-- Setup Tabs -->
			<!-- // https://epiph.yt/blog/2018/einfache-javascript-tabs-im-wordpress-backend/ -->
			<h2 class="nav-tab-wrapper">
				<a href="edit.php?page=events_optimizer&tab=tab-venues" class="nav-tab<?php 
    echo ( $active_tab === 'tab-venues' || empty( $active_tab ) ? ' nav-tab-active' : '' );
    ?>" data-slug='tab-venues'><?php 
    esc_html_e( 'Venues', 'events-optimizer' );
    ?></a>
				<a href="edit.php?page=events_optimizer&tab=tab-organizers" class="nav-tab<?php 
    echo ( $active_tab === 'tab-organizers' ? ' nav-tab-active' : '' );
    ?>" data-slug='tab-organizers'><?php 
    esc_html_e( 'Organizers', 'events-optimizer' );
    ?></a>
				<a href="edit.php?page=events_optimizer&tab=tab-events" class="nav-tab<?php 
    echo ( $active_tab === 'tab-events' ? ' nav-tab-active' : '' );
    ?>" data-slug='tab-events'><?php 
    esc_html_e( 'Events', 'events-optimizer' );
    ?></a>
			</h2>
			

			<!-- Add Venues content to tabs -->
			<div class="nav-tab-content<?php 
    echo ( $active_tab === 'tab-venues' || empty( $active_tab ) ? ' nav-tab-content-active' : '' );
    ?>" id="nav-tab-content-tab-venues">
				<p><?php 
    esc_html_e( 'Find and fix common problems in your venue data.', 'events-optimizer' );
    ?></p>

				<div class='wrap'>
					<form action='' method='POST' id='venues_form'>                
						<input type='button' name='action' class='button' id='venues_with_invalid_data' value='<?php 
    esc_attr_e( 'Missing or incorrect data', 'events-optimizer' );
    ?>' />&nbsp;&nbsp;&nbsp;
						<input type='button' name='action' class='button' id='duplicate_venues' value='<?php 
    esc_attr_e( 'Duplicate venues', 'events-optimizer' );
    ?>' <?php 
    disabled( !teoai_fs()->can_use_premium_code__premium_only() );
    ?>  />&nbsp;&nbsp;&nbsp; 
						<input type='button' name='action' class='button' id='venues_google_places_optimization' value='<?php 
    esc_attr_e( 'Validate & update with Google Places', 'events-optimizer' );
    ?>' <?php 
    disabled( !teoai_fs()->can_use_premium_code__premium_only() );
    ?>/>&nbsp;&nbsp;&nbsp;  
						<input type='button' name='action' class='button' id='venues_with_inactive_business_operation' value='<?php 
    esc_attr_e( 'Closed venues', 'events-optimizer' );
    ?>' <?php 
    disabled( !teoai_fs()->can_use_premium_code__premium_only() );
    ?>/>&nbsp;&nbsp;&nbsp;  
					</form>
					<p>
					<div id='show_results_venues'></div>
					<div id='loading_tab_venues'><?php 
    esc_html_e( 'ANALYZING', 'events-optimizer' );
    ?></div>
					</p>
				</div>          
			</div>
			

			<!-- Add Organizers content to tabs -->
			<div class="nav-tab-content<?php 
    echo ( $active_tab === 'tab-organizers' ? ' nav-tab-content-active' : '' );
    ?>" id="nav-tab-content-tab-organizers">
				<p><?php 
    esc_html_e( 'Find and fix common problems in your organizer data.', 'events-optimizer' );
    ?></p>

				<div class='wrap'>
					<form action='' method='POST' id='organizers_form'>
						<input type='button' name='action' class='button' id='organizers_with_invalid_data' value='<?php 
    esc_attr_e( 'Missing or incorrect data', 'events-optimizer' );
    ?>' />&nbsp;&nbsp;&nbsp;
						<input type='button' name='action' class='button' id='duplicate_organizers' value='<?php 
    esc_attr_e( 'Duplicate organizers', 'events-optimizer' );
    ?>' <?php 
    disabled( !teoai_fs()->can_use_premium_code__premium_only() );
    ?>  />&nbsp;&nbsp;&nbsp; 
						<input type='button' name='action' class='button' id='organizers_google_places_optimization' value='<?php 
    esc_attr_e( 'Validate & update with Google Places', 'events-optimizer' );
    ?>' <?php 
    disabled( !teoai_fs()->can_use_premium_code__premium_only() );
    ?> />&nbsp;&nbsp;&nbsp;  
					</form>
					<p>
					<div id='show_results_organizers'></div>
					<div id='loading_tab_organizers'><?php 
    esc_html_e( 'ANALYZING', 'events-optimizer' );
    ?></div>
					</p>
				</div>          
			</div>
			
			
			<!-- Add Events content to tabs -->
			<div class="nav-tab-content<?php 
    echo ( $active_tab === 'tab-events' ? ' nav-tab-content-active' : '' );
    ?>" id="nav-tab-content-tab-events">
				<p><?php 
    esc_html_e( 'Find and fix common problems in your event data.', 'events-optimizer' );
    ?></p>

				<div class='wrap'>
					<form action='' method='POST' id='events_form'>
						<input type='button' name='action' class='button' id='events_with_invalid_data' value='<?php 
    esc_attr_e( 'Missing or incorrect data', 'events-optimizer' );
    ?>'/>
					</form>
					<p>
					<div id='show_results_events'></div>
					<div id='loading_tab_events'><?php 
    esc_html_e( 'ANALYZING', 'events-optimizer' );
    ?></div>
					</p>
				</div>          
			</div>
			

			<!-- jQuery: Fade in/out buttons and call php functions to analyse data -->	
			<script type='text/javascript'>
			
				// Wait until the whole document has fully loaded
				jQuery(document).ready(function(){	
					
					// Show venues with invalid data
					jQuery('#venues_with_invalid_data').on('click', function()  { // Execute function when button is clicked
						jQuery("#venues_with_invalid_data").attr("disabled", true); // Disable button while analyzing
						jQuery.ajax({
							type: "POST",
							url: "<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>",
							data: { 
								action: 'venues_wid', // call function "Venues with invalid data"
								_ajax_nonce: '<?php 
    echo esc_attr( $nonce );
    ?>'
							},
							beforeSend: function() {
								jQuery("#loading_tab_venues").fadeIn('fast'); // Fade in loading icon and "analyzing" text
								jQuery("#show_results_venues").fadeOut("fast"); // Hide results otherwise they are show on the other tabs!
							},
							success: function(html){ // Function is called and if data is retrieved, store it in variable "html"
								jQuery("#loading_tab_venues").fadeOut('slow'); // Fade out loading icon and "analyzing" text
								jQuery("#show_results_venues").html( html ); // Show the html inside "show_results_venues" div
								jQuery("#show_results_venues").fadeIn("fast"); // Fade in the results
								jQuery("#venues_with_invalid_data").attr("disabled", false); // Enable button after analyzing
							}
						}); //close jQuery.ajax
						return false;
					});	

					// Show duplicate venues
					jQuery('#duplicate_venues').on('click', function()  {
						jQuery("#duplicate_venues").attr("disabled", true);		
						jQuery.ajax({
							type: "POST",
							url: "<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>",
							data: { 
								action: 'duplicate_ven', // call function "Duplicate Venues"
								_ajax_nonce: '<?php 
    echo esc_attr( $nonce );
    ?>'
							},
							beforeSend: function() {
								jQuery("#loading_tab_venues").fadeIn('fast');
								jQuery("#show_results_venues").fadeOut("fast");
							},
							success: function(html){
								jQuery("#loading_tab_venues").fadeOut('slow');
								jQuery("#show_results_venues").html( html );
								jQuery("#show_results_venues").fadeIn("fast");
								jQuery("#duplicate_venues").attr("disabled", false);
							}
						});
						return false;					
					});
					
					// Optimize venues with Google Places data
					jQuery('#venues_google_places_optimization').on('click', function()  {
						jQuery("#venues_google_places_optimization").attr("disabled", true);			
						jQuery.ajax({
							type: "POST",
							url: "<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>",
							data: { 
								action: 'venues_optimization_wgp', // call function "Venues optimization with Google Places"
								_ajax_nonce: '<?php 
    echo esc_attr( $nonce );
    ?>'
							},
							beforeSend: function() {
								jQuery("#loading_tab_venues").fadeIn('fast');
								jQuery("#show_results_venues").fadeOut("fast");
							},
							success: function(html){
								jQuery("#loading_tab_venues").fadeOut('slow');
								jQuery("#show_results_venues").html( html );
								jQuery("#show_results_venues").fadeIn("fast");
								jQuery("#venues_google_places_optimization").attr("disabled", false);						
							}
						});
						return false;					
					});
					
					// Show venues with inactive business operation
					jQuery('#venues_with_inactive_business_operation').on('click', function()  {
						jQuery("#venues_with_inactive_business_operation").attr("disabled", true);	
						jQuery.ajax({
							type: "POST",
							url: "<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>",
							data: { 
								action: 'venues_with_inactive_bo', // call function "Venues with inactive business operation"
								_ajax_nonce: '<?php 
    echo esc_attr( $nonce );
    ?>'
							},
							beforeSend: function() {
								jQuery("#loading_tab_venues").fadeIn('fast');
								jQuery("#show_results_venues").fadeOut("fast");
							},
							success: function(html){
								jQuery("#loading_tab_venues").fadeOut('slow');
								jQuery("#show_results_venues").html( html );
								jQuery("#show_results_venues").fadeIn("fast");
								jQuery("#venues_with_inactive_business_operation").attr("disabled", false);						
							}
						});
						return false;					
					});

					// Process the bulk actions	for venues with inactive business operation	
					jQuery(document).on('click', '#doaction, #doaction2', function() {	
						var bulk_action_top = jQuery('#bulk-action-selector-top').val();
						var bulk_action_bottom = jQuery('#bulk-action-selector-bottom').val();
						var bulk_action = bulk_action_top !== '-1' ? bulk_action_top : bulk_action_bottom;

						var ids = [];
						jQuery('.check-column input:checked').each(function() {
							ids.push(jQuery(this).val());
						});	

						jQuery.ajax({
							type: "POST",
							url: "<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>",
							data: { 
								action: 'venues_with_inactive_bo', // call function "Venues with inactive business operation"
								_ajax_nonce: '<?php 
    echo esc_attr( $nonce );
    ?>',
								bulk_action: bulk_action,
								ids: ids
							},
							beforeSend: function() {
							},
							success: function(html){
								jQuery("#show_results_venues").html( html );					
							}
						});
						return false;					
					});

					// Navigate through pages in venues with inactive business operation
					jQuery(document).on('click', '.tablenav-pages a', function() {
						var pageHref = jQuery(this).attr('href');
						var pageNumber = pageHref.split('paged=')[1]; // Extract page number from URL

						if (!pageNumber) pageNumber = 1; // Set pageNumber to 1 if page number is not found

						jQuery.ajax({
							type: "POST",
							url: "<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>",
							data: { 
								action: 'venues_with_inactive_bo', // call function "Venues with inactive business operation"
								_ajax_nonce: '<?php 
    echo esc_attr( $nonce );
    ?>',
								paged: pageNumber
							},
							beforeSend: function() {
							},
							success: function(html){
								jQuery("#show_results_venues").html( html );
							}
						});
						return false;					
					});

					// Show organizers with invalid data
					jQuery('#organizers_with_invalid_data').on('click', function()  {
						jQuery("#organizers_with_invalid_data").attr("disabled", true);
						jQuery.ajax({
							type: "POST",
							url: "<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>",
							data: { 
								action: 'organizers_wid', // call function "Organizers with invalid data"
								_ajax_nonce: '<?php 
    echo esc_attr( $nonce );
    ?>'
							},
							beforeSend: function() {
								jQuery("#loading_tab_organizers").fadeIn('fast');
								jQuery("#show_results_organizers").fadeOut("fast");
							},
							success: function(html){
								jQuery("#loading_tab_organizers").fadeOut('slow');
								jQuery("#show_results_organizers").html( html );
								jQuery("#show_results_organizers").fadeIn("fast");
								jQuery("#organizers_with_invalid_data").attr("disabled", false);
							}
						});
						return false;
					});	
		
					// Show duplicate organizers
					jQuery('#duplicate_organizers').on('click', function()  {
						jQuery("#duplicate_organizers").attr("disabled", true);		
						jQuery.ajax({
							type: "POST",
							url: "<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>",
							data: { 
								action: 'duplicate_org',  // call function "Duplicate Organizers"
								_ajax_nonce: '<?php 
    echo esc_attr( $nonce );
    ?>' 
							},
							beforeSend: function() {
								jQuery("#loading_tab_organizers").fadeIn('fast');
								jQuery("#show_results_organizers").fadeOut("fast");
							},
							success: function(html){
								jQuery("#loading_tab_organizers").fadeOut('slow');
								jQuery("#show_results_organizers").html( html );
								jQuery("#show_results_organizers").fadeIn("fast");
								jQuery("#duplicate_organizers").attr("disabled", false);
							}
						});
						return false;					
					});	

					// Optimize organizers with Google Places data
					jQuery('#organizers_google_places_optimization').on('click', function()  {
						jQuery("#organizers_google_places_optimization").attr("disabled", true);
						jQuery.ajax({
							type: "POST",
							url: "<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>",
							data: { 
								action: 'organizers_optimization_wgp', // call function "Organizers optimization with Google Places"
								_ajax_nonce: '<?php 
    echo esc_attr( $nonce );
    ?>' 
							},
							beforeSend: function() {
								jQuery("#loading_tab_organizers").fadeIn('fast');
								jQuery("#show_results_organizers").fadeOut("fast");
							},
							success: function(html){
								jQuery("#loading_tab_organizers").fadeOut('slow');
								jQuery("#show_results_organizers").html( html );
								jQuery("#show_results_organizers").fadeIn("fast");
								jQuery("#organizers_google_places_optimization").attr("disabled", false);
							}
						});
						return false;					
					})		

					// Show events with invalid data
					jQuery('#events_with_invalid_data').on('click', function()  {
						jQuery("#events_with_invalid_data").attr("disabled", true);		
						jQuery.ajax({
							type: "POST",
							url: "<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>",
							data: { 
								action: 'events_wid', // call function "Events with invalid data"
								_ajax_nonce: '<?php 
    echo esc_attr( $nonce );
    ?>' 
							},
							beforeSend: function() {
								jQuery("#loading_tab_events").fadeIn('fast');
								jQuery("#show_results_events").fadeOut("fast");
							},
							success: function(html){
								jQuery("#loading_tab_events").fadeOut('slow');
								jQuery("#show_results_events").html( html );
								jQuery("#show_results_events").fadeIn("fast");
								jQuery("#events_with_invalid_data").attr("disabled", false);
							}
						});
						return false;					
					});	

					// Search events with Google data
					// Search/add events UI moved to Import Events submenu.

				}); //close document.ready

			</script>
			
		<?php 
}

//----------------------------------------------------------------------------------------
// Manually Import Events submenu (moved from Events tab)
//----------------------------------------------------------------------------------------
function teoai_import_events_submenu_page() {
    // Check permissions.
    if ( !(( function_exists( 'teoai_user_has_access' ) ? teoai_user_has_access() : current_user_can( 'administrator' ) )) ) {
        wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'events-optimizer' ) );
    }
    $nonce = wp_create_nonce( 'events-optimizer-nonce' );
    // Location select defaults.
    $current_location_code = get_option( 'teoai_dataforseo_location_code', '' );
    $current_location_label = get_option( 'teoai_dataforseo_location_label', '' );
    if ( !$current_location_label && function_exists( 'teoai_find_dataforseo_location_label' ) ) {
        $current_location_label = teoai_find_dataforseo_location_label( $current_location_code );
    }
    $location_options = '';
    if ( $current_location_code && $current_location_label ) {
        $location_options = '<option value="' . esc_attr( $current_location_code ) . '" selected>' . esc_html( $current_location_label ) . '</option>';
    }
    // Enqueue Select2 assets for location picker.
    $base_file = dirname( __FILE__ ) . '/events-optimizer.php';
    if ( !wp_script_is( 'teoai-select2', 'registered' ) ) {
        wp_register_script(
            'teoai-select2',
            plugins_url( 'assets/vendor/select2/js/select2.min.js', $base_file ),
            array('jquery'),
            '4.1.0',
            true
        );
    }
    if ( !wp_style_is( 'teoai-select2', 'registered' ) ) {
        wp_register_style(
            'teoai-select2',
            plugins_url( 'assets/vendor/select2/css/select2.min.css', $base_file ),
            array(),
            '4.1.0'
        );
    }
    wp_enqueue_script( 'teoai-select2' );
    wp_enqueue_style( 'teoai-select2' );
    ?>
		<style type="text/css">
			#dataforseo_keyword::placeholder { color: #999; }
			#dataforseo_keyword:-ms-input-placeholder { color: #999; }
			#dataforseo_keyword::-ms-input-placeholder { color: #999; }
		</style>
		<div class='wrap'>
			<h1 class="wp-heading-inline"><?php 
    esc_html_e( 'Manually Import Events', 'events-optimizer' );
    ?></h1>
			<p><?php 
    esc_html_e( 'Search for events you want to add from Google Events.', 'events-optimizer' );
    ?></p>

				<div class='wrap'>
					<form action='' method='POST' id='import_events_form' style="display:flex; flex-wrap:wrap; gap:12px; align-items:center;">
						<label for="dataforseo_keyword"><?php 
    esc_html_e( 'Keyword', 'events-optimizer' );
    ?></label>
						<input type="text" name="dataforseo_keyword" id="dataforseo_keyword" size="14" value="<?php 
    echo esc_attr( get_option( 'teoai_dataforseo_keyword' ) );
    ?>" placeholder="<?php 
    esc_attr_e( 'e.g. jazz london', 'events-optimizer' );
    ?>" <?php 
    disabled( !teoai_fs()->can_use_premium_code__premium_only() );
    ?> />

						<label for="dataforseo_location_select"><?php 
    esc_html_e( 'Location', 'events-optimizer' );
    ?></label>
						<select id="dataforseo_location_select" name="dataforseo_location_select" class="teoai-location-select" style="width:300px; min-width:300px; max-width:300px;" data-current="<?php 
    echo esc_attr( $current_location_code );
    ?>" data-current-label="<?php 
    echo esc_attr( $current_location_label );
    ?>" <?php 
    disabled( !teoai_fs()->can_use_premium_code__premium_only() );
    ?>>
							<?php 
    echo $location_options;
    // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    ?>
						</select>
						<input type="hidden" name="dataforseo_location_label" id="dataforseo_location_label" value="<?php 
    echo esc_attr( $current_location_label );
    ?>" />

						<label for="dataforseo_depth"><?php 
    esc_html_e( 'Max. results', 'events-optimizer' );
    ?></label>
						<input type="number" name="dataforseo_depth" id="dataforseo_depth" size="2" value="<?php 
    echo esc_attr( get_option( 'teoai_dataforseo_depth' ) );
    ?>" min="10" max="100" step="10"  <?php 
    disabled( !teoai_fs()->can_use_premium_code__premium_only() );
    ?> />

						<input type='button' name='action' class='button' id='search_events_with_google_data' value='<?php 
    esc_attr_e( 'Search for events', 'events-optimizer' );
    ?>' <?php 
    disabled( !teoai_fs()->can_use_premium_code__premium_only() );
    ?>/>
						<span aria-hidden="true" style="font-size:18px; line-height:1; padding:0 4px;">&#8594;</span>
						<input type='button' name='action' class='button' id='add_events_with_google_data' value='<?php 
    esc_attr_e( 'Show results of last search', 'events-optimizer' );
    ?>' <?php 
    disabled( !teoai_fs()->can_use_premium_code__premium_only() );
    ?>/>
					</form>
					<p>
				<div id='show_results_events'></div>
				<div id='loading_tab_events'><?php 
    esc_html_e( 'RETRIEVING EVENTS', 'events-optimizer' );
    ?></div>
				</p>
			</div>

				<script type='text/javascript'>
					jQuery(document).ready(function(){

						// Keyword placeholder handling.
						(function(){
							var $keyword = jQuery('#dataforseo_keyword');
							var keywordPlaceholder = '<?php 
    echo esc_js( __( 'e.g. jazz london', 'events-optimizer' ) );
    ?>';
							if ( !$keyword.length ) { return; }
							if ( ! $keyword.val() ) {
								$keyword.attr('placeholder', keywordPlaceholder);
							}
							$keyword.on('focus', function(){
								jQuery(this).attr('placeholder', '');
							});
							$keyword.on('blur', function(){
								var $self = jQuery(this);
								if ( ! $self.val() ) {
									$self.attr('placeholder', keywordPlaceholder);
								}
							});
						})();

						// Location select (Select2 + remote search).
						(function(){
							var $sel = jQuery('#dataforseo_location_select');
							if (!$sel.length || typeof $sel.select2 !== 'function') { return; }
							var currentVal = $sel.data('current') || $sel.val();
							var currentLabel = $sel.data('current-label');
							if (currentVal && currentLabel && !$sel.find('option[value="'+currentVal+'"]').length) {
								var opt = new Option(currentLabel, currentVal, true, true);
								$sel.append(opt);
							}

							var syncLocationLabel = function() {
								var label = '';
								if ( typeof $sel.select2 === 'function' && $sel.data('select2') ) {
									var data = $sel.select2('data');
									if ( data && data.length ) {
										label = data[0].text || '';
									}
								}
								if ( ! label ) {
									label = $sel.find('option:selected').text();
								}
								jQuery('#dataforseo_location_label').val( label );
							};

							$sel.select2({
								placeholder: '<?php 
    echo esc_js( __( 'Type to search locations…', 'events-optimizer' ) );
    ?>',
								allowClear: true,
								width: 'resolve',
								ajax: {
									url: '<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>',
									dataType: 'json',
									delay: 250,
									cache: true,
									data: function(params){
										return {
											action: 'teoai_search_dataforseo_locations',
											term: params.term || '',
											limit: 50,
											_ajax_nonce: '<?php 
    echo esc_js( $nonce );
    ?>'
										};
									},
									processResults: function(resp){
										if (resp && resp.success && resp.data && resp.data.items){
											return {
												results: resp.data.items.map(function(item){
													return { id: item.code, text: item.label || item.code };
												})
											};
										}
										return { results: [] };
									}
								}
							});

							if (currentVal) {
								$sel.val(currentVal).trigger('change');
							}
							syncLocationLabel();

							$sel.on('change', syncLocationLabel);
						})();

						// Search events with Google data
						jQuery('#search_events_with_google_data').on('click', function()  {
							jQuery("#search_events_with_google_data").attr("disabled", true);
						jQuery.ajax({
							type: "POST",
							url: "<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>",
							data: { 
								action: 'search_events_wgd', // call function "Search events with Google data"
								dataforseo_keyword:	jQuery( '#dataforseo_keyword' ).val(),
								dataforseo_location_code: jQuery( '#dataforseo_location_select' ).val() || jQuery( '#dataforseo_location_select' ).data('current') || '',
								dataforseo_depth:	jQuery( '#dataforseo_depth' ).val(),							
								_ajax_nonce: '<?php 
    echo esc_attr( $nonce );
    ?>' 
							},
							beforeSend: function() {
								jQuery("#loading_tab_events").fadeIn('fast');
								jQuery("#show_results_events").fadeOut("fast");
							},
							success: function(html){
								jQuery("#loading_tab_events").fadeOut('slow');
								jQuery("#show_results_events").html( html );
								jQuery("#show_results_events").fadeIn("fast");
								jQuery("#search_events_with_google_data").attr("disabled", false);
							}
						});
						return false;					
					});	
					
					// Add events with Google data
					jQuery('#add_events_with_google_data').on('click', function()  {
						jQuery("#add_events_with_google_data").attr("disabled", true);		
						jQuery.ajax({
							type: "POST",
							url: "<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>",
							data: { 
								action: 'add_events_wgd', // call function "Add events from Google data"
								_ajax_nonce: '<?php 
    echo esc_attr( $nonce );
    ?>' 
							},
							beforeSend: function() {
								jQuery("#loading_tab_events").fadeIn('fast');
								jQuery("#show_results_events").fadeOut("fast");
							},
							success: function(html){
								jQuery("#loading_tab_events").fadeOut('slow');
								jQuery("#show_results_events").html( html );
								jQuery("#show_results_events").fadeIn("fast");
								jQuery("#add_events_with_google_data").attr("disabled", false);
							}
						});
						return false;					
					});

				});
			</script>
		</div>
		<?php 
}

//----------------------------------------------------------------------------------------
// Venues with invalid data
//----------------------------------------------------------------------------------------
add_action( 'wp_ajax_venues_wid', 'teoai_venues_with_invalid_data' );
function teoai_venues_with_invalid_data() {
    // Check the nonce
    if ( !check_ajax_referer( 'events-optimizer-nonce', '_wpnonce', false ) ) {
        wp_die( 'Invalid nonce' );
    }
    // Maximum number of results to display per page
    $max_results_per_page = intval( get_option( 'teoai_max_results_per_page', 5 ) );
    // Objects to be ignored while searching for invalid data
    $ignored_and_added_objects = maybe_unserialize( get_option( 'teoai_ignored_and_added_objects' ) );
    if ( empty( $ignored_and_added_objects ) ) {
        $ignored_and_added_objects = array();
    } else {
        $ignored_and_added_objects = teoai_sanitize_multi_dimensional_array( $ignored_and_added_objects );
    }
    // Whether ignored/added objects should be shown or not
    $show_ignored_objects = filter_var( get_option( 'teoai_show_ignored_objects' ), FILTER_VALIDATE_BOOLEAN );
    $show_added_objects = filter_var( get_option( 'teoai_show_added_objects' ), FILTER_VALIDATE_BOOLEAN );
    // Fields to be ignored while searching for invalid data
    $ignored_field_venue_description = get_option( 'teoai_ignored_field_venue_description' );
    $ignored_field_venue_address = get_option( 'teoai_ignored_field_venue_address' );
    $ignored_field_venue_zip = get_option( 'teoai_ignored_field_venue_zip' );
    $ignored_field_venue_city = get_option( 'teoai_ignored_field_venue_city' );
    $ignored_field_venue_province = get_option( 'teoai_ignored_field_venue_province' );
    $ignored_field_venue_state = get_option( 'teoai_ignored_field_venue_state' );
    $ignored_field_venue_country = get_option( 'teoai_ignored_field_venue_country' );
    $ignored_field_venue_phone = get_option( 'teoai_ignored_field_venue_phone' );
    $ignored_field_venue_website = get_option( 'teoai_ignored_field_venue_website' );
    // Custom countries from Events Calendar Options
    $options = get_option( 'tribe_events_calendar_options', '' );
    if ( !empty( $options['tribe_events_calendar_options'] ) ) {
        $countries = explode( PHP_EOL, $options['tribeEventsCountries'] );
    } else {
        $countries = array();
    }
    foreach ( $countries as $j => $country ) {
        $country = sanitize_text_field( $country );
        if ( !empty( trim( substr( $country, strpos( $country, ' ' ) + 1 ) ) ) ) {
            $countries_arr[$j] = trim( substr( $country, strpos( $country, ' ' ) + 1 ) );
        }
    }
    $fields_arr = array(
        'ID'             => esc_html__( 'ID', 'events-optimizer' ),
        'post_title'     => esc_html__( 'Name', 'events-optimizer' ),
        'post_content'   => esc_html__( 'Description', 'events-optimizer' ),
        '_VenueAddress'  => esc_html__( 'Address', 'events-optimizer' ),
        '_VenueZip'      => esc_html__( 'ZIP', 'events-optimizer' ),
        '_VenueCity'     => esc_html__( 'City', 'events-optimizer' ),
        '_VenueProvince' => esc_html__( 'Province', 'events-optimizer' ),
        '_VenueState'    => esc_html__( 'State', 'events-optimizer' ),
        '_VenueCountry'  => esc_html__( 'Country', 'events-optimizer' ),
        '_VenuePhone'    => esc_html__( 'Phone', 'events-optimizer' ),
        '_VenueURL'      => esc_html__( 'Website', 'events-optimizer' ),
    );
    // Get the next index of the venue if function is called by "Show more" button
    $next_result = ( filter_input( INPUT_POST, 'next_result', FILTER_SANITIZE_NUMBER_INT ) ?: 0 );
    // Set index to the next upcoming venue
    $k = $next_result;
    $venue = tribe_get_venues();
    $c = count( $venue );
    // Maximum amount of venues
    $i = 0;
    // Index to count for maximum results per page
    // Check if not all venues have been shown yet and maximum results has not been reached
    while ( $k < $c and $i < $max_results_per_page ) {
        // Hide venues that have no errors
        $found_error = false;
        $venue_details = get_post_meta( $venue[$k]->ID ) + array(
            'ID'           => $venue[$k]->ID,
            'post_title'   => sanitize_text_field( $venue[$k]->post_title ),
            'post_content' => sanitize_text_field( $venue[$k]->post_content ),
        );
        // If venue isn't part of the ignored or added objects list show it
        if ( array_search( $venue[$k]->ID, array_column( $ignored_and_added_objects, 'post_id' ) ) === false || $show_ignored_objects || $show_added_objects ) {
            echo '<form action="" method="POST" id="save_venue_wid_form_' . esc_attr( $k ) . '"><br>
				<table class="widefat fixed striped">
				<thead>
				<tr>
				<th>' . esc_html__( 'Field', 'events-optimizer' ) . '</th>
				<th>' . esc_html__( 'Value', 'events-optimizer' ) . '</th>
				<th>' . esc_html__( 'Status', 'events-optimizer' ) . '</th>
				</tr>
				</thead>
				<tbody>';
            foreach ( $fields_arr as $field => $fieldname ) {
                // Get value of Events Calendar field
                // It should always an string but somehow sometimes it is an array
                if ( isset( $venue_details[$field] ) ) {
                    if ( is_array( $venue_details[$field] ) ) {
                        // Convert the array to a string
                        $value = implode( ', ', $venue_details[$field] );
                    } else {
                        $value = sanitize_text_field( (string) $venue_details[$field] );
                    }
                } else {
                    $value = '';
                }
                switch ( $field ) {
                    case 'ID':
                        if ( isset( $venue[$k] ) && isset( $venue[$k]->ID ) ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><input type="hidden" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '"/><td><a href="' . esc_url( '/wp-admin/post.php?post=' . esc_attr( $venue[$k]->ID ) . '&action=edit' ) . '" target="_blank" rel="noopener noreferrer">' . esc_attr( $value ) . ' <img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/external-link.png' ) . '" class="external-link-icon" alt="External Link"/></a></td><td>--</td></tr>';
                        }
                        break;
                    case 'post_title':
                        if ( isset( $venue[$k] ) && isset( $venue[$k]->post_title ) && isset( $venue[$k]->_VenueCity ) ) {
                            if ( empty( $value ) ) {
                                echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="https://www.google.com/search?q=' . urlencode( sanitize_text_field( $venue[$k]->post_title ) . ' ' . sanitize_text_field( $venue[$k]->_VenueCity ) ) . '" target="_blank" rel="noopener noreferrer"><img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                                $found_error = true;
                            } else {
                                echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="https://www.google.com/search?q=' . urlencode( sanitize_text_field( $venue[$k]->post_title ) . ' ' . sanitize_text_field( $venue[$k]->_VenueCity ) ) . '" target="_blank" rel="noopener noreferrer"><img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td></td></tr>';
                            }
                            break;
                        }
                    case 'post_content':
                        if ( empty( $value ) ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><textarea name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" rows="6" cols="30"></textarea></td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                            if ( $ignored_field_venue_description === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><textarea name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" rows="6" cols="30">' . esc_textarea( $value ) . '</textarea></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                        break;
                    case '_VenueZip':
                        if ( empty( $value ) ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                            if ( $ignored_field_venue_zip === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                        break;
                    // Only for Non-USA countries: set the province (= Bundesland)
                    case '_VenueProvince':
                        if ( isset( $venue_details['_VenueCountry'][0] ) and sanitize_text_field( $venue_details['_VenueCountry'][0] ) != 'United States' ) {
                            if ( empty( $value ) ) {
                                echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                                if ( $ignored_field_venue_province === 'false' ) {
                                    $found_error = true;
                                }
                            } else {
                                echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                            }
                        }
                        break;
                    // Only for USA - set abbreviation of state, e.g. AZ for Arizona)
                    case '_VenueState':
                        if ( isset( $venue_details['_VenueCountry'][0] ) and $venue_details['_VenueCountry'][0] === 'United States' ) {
                            if ( empty( $value ) ) {
                                echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                                if ( $ignored_field_venue_state === 'false' ) {
                                    $found_error = true;
                                }
                            } else {
                                echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                            }
                        }
                        break;
                    case '_VenueCountry':
                        if ( empty( $value ) ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                            if ( $ignored_field_venue_country === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            // Custom countries available?
                            if ( !empty( $countries_arr ) ) {
                                $value = sanitize_text_field( $value );
                                if ( !in_array( $value, $countries_arr ) ) {
                                    echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-error">' . esc_html__( 'Country not in custom country list', 'events-optimizer' ) . '</span></td></tr>';
                                    if ( $ignored_field_venue_country === 'false' ) {
                                        $found_error = true;
                                    }
                                } else {
                                    echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                                }
                            } else {
                                echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                            }
                        }
                        break;
                    // Check if country is in custom country list
                    case '_VenueCountry':
                        if ( empty( $value ) ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                            if ( $ignored_field_venue_country === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            // Custom countries available?
                            if ( !empty( $countries_arr ) ) {
                                if ( !in_array( $value, $countries_arr ) ) {
                                    echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-error">' . esc_html__( 'Country not in custom country list', 'events-optimizer' ) . '</span></td></tr>';
                                    if ( $ignored_field_venue_country === 'false' ) {
                                        $found_error = true;
                                    }
                                } else {
                                    echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                                }
                            } else {
                                echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                            }
                        }
                        break;
                    case '_VenuePhone':
                        $valid = teoai_phone_number_valid( $value );
                        if ( $valid != '' ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="' . esc_url( 'https://www.google.com/search?q=' . urlencode( sanitize_text_field( $venue[$k]->post_title ) . ' ' . sanitize_text_field( $venue[$k]->_VenueCity ) ) . ' phone' ) . '" target="_blank" rel="noopener noreferrer"> <img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-error">' . esc_html( $valid ) . '</span></td></tr>';
                            if ( $ignored_field_venue_phone === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="' . esc_url( 'https://www.google.de/search?q=' . urlencode( sanitize_text_field( $venue[$k]->post_title ) . ' phone' ) ) . '" target="_blank" rel="noopener noreferrer"> <img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                        break;
                    case '_VenueURL':
                        $valid = teoai_url_valid( $value );
                        if ( $valid['status'] != 'OK' ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="' . esc_url( 'https://www.google.com/search?q=' . urlencode( sanitize_text_field( $venue[$k]->post_title ) . ' ' . sanitize_text_field( $venue[$k]->_VenueCity ) ) ) . '" target="_blank" rel="noopener noreferrer"><img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-error">' . esc_html( $valid['error_message'] ?? '' ) . '</span></td></tr>';
                            if ( $ignored_field_venue_website === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="' . esc_url( $value ) . '" target="_blank" rel="noopener noreferrer"><img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/external-link.png' ) . '" class="external-link-icon" alt="External Link"/></a></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                        break;
                    default:
                        if ( empty( $value ) ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                            if ( $field === 'post_title' ) {
                                $found_error = true;
                            }
                            if ( $field === '_VenueAddress' and $ignored_field_venue_address === 'false' ) {
                                $found_error = true;
                            }
                            if ( $field === '_VenueCity' and $ignored_field_venue_city === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                }
                // end switch
            }
            // end foreach
            echo '</tbody>
					</table>
					<p><input type="button" name="action" class="button button-primary" id="save_venue_wid_button_' . esc_attr( $k ) . '" value="' . esc_html__( 'Save changes', 'events-optimizer' ) . '" onclick="save_form(' . "'" . esc_attr( $k ) . "'" . ');" />
					&nbsp;&nbsp;&nbsp;<input type="button" name="action" class="button delete" id="ignore_object_button_' . esc_attr( $k ) . '" value="' . esc_html__( 'Ignore', 'events-optimizer' ) . '" onclick="ignore_object(' . "'" . esc_attr( $k ) . "'" . ');"';
            disabled( !teoai_fs()->can_use_premium_code__premium_only() );
            echo '/>
					</p><div id="status_save_venue_wid_' . esc_attr( $k ) . '">' . esc_html__( 'SAVING', 'events-optimizer' ) . '</div></p><br>
					</form>';
        }
        // end if array_search(
        $nonce = wp_create_nonce( 'events-optimizer-nonce' );
        // Location select defaults.
        $current_location_code = get_option( 'teoai_dataforseo_location_code', '' );
        $current_location_label = ( function_exists( 'teoai_find_dataforseo_location_label' ) ? teoai_find_dataforseo_location_label( $current_location_code ) : '' );
        $location_options = '';
        if ( $current_location_code && $current_location_label ) {
            $location_options = '<option value="' . esc_attr( $current_location_code ) . '" selected>' . esc_html( $current_location_label ) . '</option>';
        }
        // Enqueue Select2 for location picker.
        if ( !wp_script_is( 'teoai-select2', 'enqueued' ) ) {
            $base_file = dirname( __FILE__ ) . '/events-optimizer.php';
            wp_register_script(
                'teoai-select2',
                plugins_url( 'assets/vendor/select2/js/select2.min.js', $base_file ),
                array('jquery'),
                '4.1.0',
                true
            );
            wp_register_style(
                'teoai-select2',
                plugins_url( 'assets/vendor/select2/css/select2.min.css', $base_file ),
                array(),
                '4.1.0'
            );
        }
        wp_enqueue_script( 'teoai-select2' );
        wp_enqueue_style( 'teoai-select2' );
        ?>	
			
			<script  type='text/javascript'>
		
				function save_form(form_id){
					var datastring = jQuery("#save_venue_wid_form_"+form_id).serialize();
					jQuery("#save_venue_wid_button_"+form_id).attr("disabled", true); // Disable button while saving
					jQuery.ajax({
						type: "POST",
						url: "<?php 
        echo esc_url( admin_url( 'admin-ajax.php' ) );
        ?>",
						data: { 
							action: 'save_ven',
							_ajax_nonce: '<?php 
        echo esc_attr( $nonce );
        ?>',
							data: datastring,
						},
						beforeSend: function() {
							jQuery("#status_save_venue_wid_"+form_id).fadeIn('fast');  // Fade in status when button is clicked
						},
						success: function(html) {
							jQuery("#status_save_venue_wid_"+form_id).fadeOut('slow');	// Fade out status after data is saved
							jQuery("#save_venue_wid_button_"+form_id).attr("disabled", false); // Enable button after saving
							jQuery("#save_venue_wid_form_"+form_id).slideUp(); // Disable venue form after saving							
						}
					}); //close jQuery.ajax
					return false;	
				}
				function ignore_object(form_id){	
					var datastring = jQuery("#save_venue_wid_form_"+form_id).serialize() + '&type=tribe_venue&status=ignored';
					jQuery("#ignore_object_button_"+form_id).attr("disabled", true); // Disable button while ignoring
					jQuery.ajax({
						type: "POST",
						url: "<?php 
        echo esc_url( admin_url( 'admin-ajax.php' ) );
        ?>",
						data: { 
							action: 'add_obj',
							_ajax_nonce: '<?php 
        echo esc_attr( $nonce );
        ?>',
							data: datastring,
						},
						beforeSend: function() {
						},
						success: function(html) {
							jQuery("#status_save_venue_wid_"+form_id).fadeOut('slow');	// Fade out status after data is ignored
							jQuery("#ignore_object_button_"+form_id).attr("disabled", false); // Enable button after ignoring
							jQuery("#save_venue_wid_form_"+form_id).slideUp(); // Slide venue form away after ignoring							
						}
					}); //close jQuery.ajax
					return false;	
				}
			</script>	

			<style type='text/css'>
				#status_save_venue_wid_<?php 
        echo esc_attr( $k );
        ?> { 
					display: none;
					clear: both;
					background: url(<?php 
        echo esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/loading.gif' );
        ?>) left top no-repeat; 
					text-align: left;
					vertical-align: center;	
					padding-left: 25px;
				}
				<?php 
        if ( $found_error === false ) {
            echo "#save_venue_wid_form_" . esc_attr( $k ) . ", #save_venue_wid_button_" . esc_attr( $k ) . " { display: none; }";
        }
        ?>
			</style>

			<?php 
        // if invalid data is found increase counter for maximum results per page
        if ( $found_error === true ) {
            $i++;
        }
        $k++;
    }
    // end while
    if ( $k < $c ) {
        echo '<div id="additional_results_venues_wid_' . esc_attr( $k ) . '"><p><strong>' . esc_html__( 'Additional results available.', 'events-optimizer' ) . '</strong></p></div>';
        echo '<p><input type="submit" name="action" class="button button-primary" id="show_more_venues_wid_button_' . esc_attr( $k ) . '" value="' . esc_html__( 'Show more', 'events-optimizer' ) . '" onclick="show_more(' . "'" . esc_attr( $k ) . "'" . ');" /></p>';
        echo '<div id="show_more_venues_wid"></div>';
        echo '<div id="status_show_more_venues_wid_' . esc_attr( $k ) . '">' . esc_html__( 'ANALYZING', 'events-optimizer' ) . '</div>';
    }
    if ( $next_result + $max_results_per_page >= $c ) {
        echo '<span class="field-status-ok">' . esc_html__( 'No (more) results found!', 'events-optimizer' ) . '</span>';
    }
    $nonce = wp_create_nonce( 'events-optimizer-nonce' );
    ?>	
			
		<script  type='text/javascript'>
		
			function show_more(form_id){
				jQuery("#show_more_venues_wid_button_"+form_id).fadeOut('slow'); // Hide button after  		
				jQuery("#show_more_venues_wid_button_"+form_id).attr("disabled", true); // Disable button while retrieving more results
				jQuery.ajax({
					type: "POST",
					url: "<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>",
					data: { 
						action: 'venues_wid',
						next_result: form_id,
						_ajax_nonce: '<?php 
    echo esc_attr( $nonce );
    ?>' 
					},
					beforeSend: function() {
						jQuery("#status_show_more_venues_wid_"+form_id).fadeIn('fast');  // Fade in status when button is clicked
						jQuery("#additional_results_venues_wid_"+form_id).fadeOut('slow');	// Fade out text "Additional results ..." after data is saved
					},
					success: function(html) {
						jQuery("#show_more_venues_wid_button_"+form_id).attr("disabled", false); // Enable button after
						jQuery("#status_show_more_venues_wid_"+form_id).fadeOut('slow');	// Fade out status after data is saved
						jQuery("#show_more_venues_wid").append(html); // Add the additional results to page
					}
				}); //close jQuery.ajax
				return false;	
			}	
		</script>

		<style type='text/css'>
			#status_show_more_venues_wid_<?php 
    echo esc_attr( $k );
    ?> { 
				display: none;
				clear: both;
				background: url(<?php 
    echo esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/loading.gif' );
    ?>) left top no-repeat; 
				text-align: left;
				vertical-align: center;	
				padding-left: 25px;
			}
		</style>

		<?php 
    wp_die();
}

//----------------------------------------------------------------------------------------
// Save venue data (for invalid data and Google Places optimization)
//----------------------------------------------------------------------------------------
add_action( 'wp_ajax_save_ven', 'teoai_save_venue' );
function teoai_save_venue() {
    // Check the nonce
    if ( !check_ajax_referer( 'events-optimizer-nonce', '_wpnonce', false ) ) {
        wp_die( 'Nonce check failed', '', 403 );
    }
    // Add capability check
    if ( !current_user_can( 'edit_posts' ) ) {
        wp_die( 'Unauthorized', '', 403 );
    }
    // Use wp_unslash and wp_parse_str for safer data processing
    wp_parse_str( wp_unslash( $_POST['data'] ), $venue );
    // Title and description can't be updated directly with the TEC API (empty fields gets ignored - bug?) and therefore it needs to be updated seperatly
    $venue_post_arr = array(
        'ID'           => sanitize_text_field( $venue['ID'] ),
        'post_title'   => sanitize_text_field( $venue['post_title'] ),
        'post_content' => wp_kses_post( $venue['post_content'] ),
    );
    wp_update_post( $venue_post_arr );
    // Check if state and province are set
    if ( !isset( $venue['_VenueState'] ) ) {
        $venue['_VenueState'] = '';
    }
    if ( !isset( $venue['_VenueProvince'] ) ) {
        $venue['_VenueProvince'] = '';
    }
    // Update venues with values
    $venue_arr = array(
        'Address'       => sanitize_text_field( $venue['_VenueAddress'] ),
        'GeoAddress'    => sanitize_text_field( $venue['_VenueAddress'] ) . ' ' . sanitize_text_field( $venue['_VenueZip'] ) . ' ' . sanitize_text_field( $venue['_VenueCity'] ) . ' ' . sanitize_text_field( $venue['_VenueCountry'] ),
        'Zip'           => sanitize_text_field( $venue['_VenueZip'] ),
        'City'          => sanitize_text_field( $venue['_VenueCity'] ),
        'State'         => sanitize_text_field( $venue['_VenueState'] ),
        'Province'      => sanitize_text_field( $venue['_VenueProvince'] ),
        'StateProvince' => sanitize_text_field( $venue['_VenueProvince'] ),
        'Country'       => sanitize_text_field( $venue['_VenueCountry'] ),
        'Phone'         => sanitize_text_field( $venue['_VenuePhone'] ),
        'URL'           => esc_url( $venue['_VenueURL'] ),
    );
    tribe_update_venue( $venue['ID'], $venue_arr );
    wp_die();
}

//----------------------------------------------------------------------------------------
// Organizers with invalid data
//----------------------------------------------------------------------------------------
add_action( 'wp_ajax_organizers_wid', 'teoai_organizers_with_invalid_data' );
function teoai_organizers_with_invalid_data() {
    // Check the nonce
    if ( !check_ajax_referer( 'events-optimizer-nonce', '_wpnonce', false ) ) {
        wp_die( 'Invalid nonce' );
    }
    // Maximum number of results to display per page
    $max_results_per_page = intval( get_option( 'teoai_max_results_per_page', 5 ) );
    // Objects to be ignored while searching for invalid data
    $ignored_and_added_objects = maybe_unserialize( get_option( 'teoai_ignored_and_added_objects' ) );
    if ( empty( $ignored_and_added_objects ) ) {
        $ignored_and_added_objects = array();
    }
    // Whether ignored/added objects should be shown or not
    $show_ignored_objects = filter_var( get_option( 'teoai_show_ignored_objects' ), FILTER_VALIDATE_BOOLEAN );
    $show_added_objects = filter_var( get_option( 'teoai_show_added_objects' ), FILTER_VALIDATE_BOOLEAN );
    // Fields to be ignored while searching for invalid data
    $ignored_field_organizer_description = get_option( 'teoai_ignored_field_organizer_description' );
    $ignored_field_organizer_phone = get_option( 'teoai_ignored_field_organizer_phone' );
    $ignored_field_organizer_website = get_option( 'teoai_ignored_field_organizer_website' );
    $ignored_field_organizer_mail = get_option( 'teoai_ignored_field_organizer_mail' );
    $fields_arr = array(
        'ID'                => esc_html__( 'ID', 'events-optimizer' ),
        'post_title'        => esc_html__( 'Name', 'events-optimizer' ),
        'post_content'      => esc_html__( 'Description', 'events-optimizer' ),
        '_OrganizerPhone'   => esc_html__( 'Phone', 'events-optimizer' ),
        '_OrganizerWebsite' => esc_html__( 'Website', 'events-optimizer' ),
        '_OrganizerEmail'   => esc_html__( 'Mail', 'events-optimizer' ),
    );
    // Get the next index of the venue if function is called by "Show more" button
    $next_result = ( filter_input( INPUT_POST, 'next_result', FILTER_SANITIZE_NUMBER_INT ) ?: 0 );
    // Set index to the next upcoming venue
    $k = $next_result;
    $organizer = tribe_get_organizers();
    $c = count( $organizer );
    // Maximum amount of organizers
    $i = 0;
    // Index to count for maximum results per page
    // Check if not all organizers have been shown yet and maximum results has not been reached
    while ( $k < $c and $i < $max_results_per_page ) {
        // Hide organizers that have no errors
        $found_error = false;
        $organizer_details = get_post_meta( $organizer[$k]->ID ) + array(
            'ID'           => array($organizer[$k]->ID),
            'post_title'   => array($organizer[$k]->post_title),
            'post_content' => array($organizer[$k]->post_content),
        );
        // If organizer isn't part of the ignored or added objects list show it
        if ( array_search( $organizer[$k]->ID, array_column( $ignored_and_added_objects, 'post_id' ) ) === false || $show_ignored_objects || $show_added_objects ) {
            echo '<form action="" method="POST" id="save_organizer_wid_form_' . esc_attr( $k ) . '">
				<br>		
				<table class="widefat fixed striped">
				<thead>
				<tr>
				<th>' . esc_html__( 'Field', 'events-optimizer' ) . '</th>
				<th>' . esc_html__( 'Value', 'events-optimizer' ) . '</th>
				<th>' . esc_html__( 'Status', 'events-optimizer' ) . '</th>
				</tr>
				</thead>
				<tbody>';
            foreach ( $fields_arr as $field => $fieldname ) {
                if ( isset( $organizer_details[$field][0] ) ) {
                    $value = $organizer_details[$field][0];
                } else {
                    $value = '';
                }
                echo '<input type="hidden" name="index" id="index" value="' . esc_attr( $k ) . '"/>';
                switch ( $field ) {
                    case 'ID':
                        echo '<tr><td>' . esc_attr( $fieldname ) . '</td><input type="hidden" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '"/><td><a href="/wp-admin/post.php?post=' . esc_attr( $organizer[$k]->ID ) . '&action=edit" target="_blank" rel="noopener noreferrer">' . esc_attr( $value ) . ' <img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/external-link.png' ) . '" class="external-link-icon" alt="External Link"/></a></td><td>--</td></tr>';
                        break;
                    case 'post_title':
                        if ( empty( $value ) ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="https://www.google.com/search?q=' . urlencode( $organizer[$k]->post_title ) . '" target="_blank" rel="noopener noreferrer"><img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="https://www.google.com/search?q=' . urlencode( $organizer[$k]->post_title ) . '" target="_blank" rel="noopener noreferrer"><img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                        break;
                    case 'post_content':
                        if ( empty( $value ) ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><textarea name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" rows="6" cols="30"></textarea></td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                            if ( $ignored_field_organizer_description === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><textarea name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" rows="6" cols="30">' . esc_textarea( $value ) . '</textarea></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                        break;
                    case '_OrganizerPhone':
                        $valid = teoai_phone_number_valid( $value );
                        if ( $valid != '' ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="https://www.google.com/search?q=' . urlencode( $organizer[$k]->post_title . ' phone' ) . '" target="_blank" rel="noopener noreferrer"><img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-error">' . esc_attr( $valid ?? '' ) . '</td></tr>';
                            if ( $ignored_field_organizer_phone === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="https://www.google.de/search?q=' . urlencode( $organizer[$k]->post_title ) . ' phone" target="_blank" rel="noopener noreferrer"><img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                        break;
                    case '_OrganizerWebsite':
                        $valid = teoai_url_valid( $value );
                        if ( $valid['status'] != 'OK' ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="https://www.google.com/search?q=' . urlencode( $organizer[$k]->post_title ) . '" target="_blank" rel="noopener noreferrer"><img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-error">' . esc_attr( $valid['error_message'] ?? '' ) . '</td></tr>';
                            if ( $ignored_field_organizer_website === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="' . urlencode( $value ) . '" target="_blank" rel="noopener noreferrer"> <img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/external-link.png' ) . '" class="external-link-icon" alt="External Link"/></a></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                        break;
                    // Check if mail is valid
                    case '_OrganizerEmail':
                        $valid = teoai_mail_valid( $value );
                        if ( $valid != '' ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="https://www.google.de/search?q=' . urlencode( $organizer[$k]->post_title . ' mail' ) . '" target="_blank" rel="noopener noreferrer"><img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-error">' . esc_attr( $valid ?? '' ) . '</td></tr>';
                            if ( $ignored_field_organizer_mail === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="https://www.google.de/search?q=' . urlencode( $organizer[$k]->post_title . ' mail' ) . '" target="_blank" rel="noopener noreferrer"><img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                        break;
                    default:
                        if ( empty( $value ) ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="https://www.google.com/search?q=' . urlencode( $organizer[$k]->post_title ) . '" target="_blank" rel="noopener noreferrer"><img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                }
                // end switch
            }
            // end foreach
            echo '</tbody>
					</table>	
					<p><input type="button" name="action" class="button button-primary" id="save_organizer_wid_button_' . esc_attr( $k ) . '" value="' . esc_html__( 'Save changes', 'events-optimizer' ) . '" onclick="save_form(' . "'" . esc_attr( $k ) . "'" . ');" />
					&nbsp;&nbsp;&nbsp;<input type="button" name="action" class="button delete" id="ignore_object_button_' . esc_attr( $k ) . '" value="' . esc_html__( 'Ignore', 'events-optimizer' ) . '" onclick="ignore_object(' . "'" . esc_attr( $k ) . "'" . ');"';
            disabled( !teoai_fs()->can_use_premium_code__premium_only() );
            echo '/>
					</p><div id="status_save_organizer_wid_' . esc_attr( $k ) . '">' . esc_html__( 'SAVING', 'events-optimizer' ) . '</div></p><br>
					</form>';
        }
        // end if array_search(
        $nonce = wp_create_nonce( 'events-optimizer-nonce' );
        ?>	

			<script  type='text/javascript'>
		
				function save_form(form_id){
					var datastring = jQuery("#save_organizer_wid_form_"+form_id).serialize(); 
					jQuery("#save_organizer_wid_button_"+form_id).attr("disabled", true); // Disable button while saving
					jQuery.ajax({
						type: "POST",
						url: "<?php 
        echo esc_url( admin_url( 'admin-ajax.php' ) );
        ?>",
						data: { 
							action: 'save_org',
							_ajax_nonce: '<?php 
        echo esc_attr( $nonce );
        ?>',
							data: datastring,
							},
						beforeSend: function() {
							jQuery("#status_save_organizer_wid_"+form_id).fadeIn('fast');  // Fade in status when button is clicked
							},
						success: function(html) {
							jQuery("#status_save_organizer_wid_"+form_id).fadeOut('slow');	// Fade out status after data is saved
							jQuery("#save_organizer_wid_button_"+form_id).attr("disabled", false); // Enable button after saving
							jQuery("#save_organizer_wid_form_"+form_id).slideUp(); // Slide organizer form away after saving				
						}
					}); //close jQuery.ajax
					return false;	
				}
				function ignore_object(form_id){
					var datastring = jQuery("#save_organizer_wid_form_"+form_id).serialize() + '&type=tribe_organizer&status=ignored';
					jQuery("#ignore_object_button_"+form_id).attr("disabled", true); // Disable button while ignoring
					jQuery.ajax({
						type: "POST",
						url: "<?php 
        echo esc_url( admin_url( 'admin-ajax.php' ) );
        ?>",
						data: { 
							action: 'add_obj',
							_ajax_nonce: '<?php 
        echo esc_attr( $nonce );
        ?>',
							data: datastring,
						},
						beforeSend: function() {
						},
						success: function(html) {
							jQuery("#status_save_organizer_wid_"+form_id).fadeOut('slow');	// Fade out status after data is ignored
							jQuery("#ignore_object_button_"+form_id).attr("disabled", false); // Enable button after ignoring
							jQuery("#save_organizer_wid_form_"+form_id).slideUp(); // Slide organizer form away after ignoring							
						}
					}); //close jQuery.ajax
					return false;	
				}
			</script>	
			
			<style type='text/css'>
				#status_save_organizer_wid_<?php 
        echo esc_attr( $k );
        ?> { 
					display: none;
					clear: both;
					background: url(<?php 
        echo esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/loading.gif' );
        ?>) left top no-repeat; 
					text-align: left;
					vertical-align: center;	
					padding-left: 25px;
				}
				<?php 
        if ( $found_error === false ) {
            echo "#save_organizer_wid_form_" . esc_attr( $k ) . ", #save_organizer_wid_button_" . esc_attr( $k ) . " { display: none; }";
        }
        ?>
			</style>

			<?php 
        // if invalid data is found increase counter for maximum results per page
        if ( $found_error === true ) {
            $i++;
        }
        $k++;
    }
    // end while
    if ( $k < $c ) {
        echo '<div id="additional_results_organizers_wid_' . esc_attr( $k ) . '"><p><strong>' . esc_html__( 'Additional results available.', 'events-optimizer' ) . '</strong></p></div>';
        echo '<p><input type="submit" name="action" class="button button-primary" id="show_more_organizers_wid_button_' . esc_attr( $k ) . '" value="' . esc_html__( 'Show more', 'events-optimizer' ) . '" onclick="show_more(' . "'" . esc_attr( $k ) . "'" . ');" /></p>';
        echo '<div id="show_more_organizers_wid"></div>';
        echo '<div id="status_show_more_organizers_wid_' . esc_attr( $k ) . '">' . esc_html__( 'ANALYZING', 'events-optimizer' ) . '</div>';
    }
    if ( $next_result + $max_results_per_page >= $c ) {
        echo '<span class="field-status-ok">' . esc_html__( 'No (more) results found!', 'events-optimizer' ) . '</span>';
    }
    $nonce = wp_create_nonce( 'events-optimizer-nonce' );
    ?>	
			
		<script  type='text/javascript'>
		
			function show_more(form_id){
				jQuery("#show_more_organizers_wid_button_"+form_id).fadeOut('slow'); // Hide button after  		
				jQuery("#show_more_organizers_wid_button_"+form_id).attr("disabled", true); // Disable button while retrieving more results
				jQuery.ajax({
					type: "POST",
					url: "<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>",
					data: { 
						action: 'organizers_wid',
						next_result: form_id,
						_ajax_nonce: '<?php 
    echo esc_attr( $nonce );
    ?>' 
					},
					beforeSend: function() {
						jQuery("#status_show_more_organizers_wid_"+form_id).fadeIn('fast');  // Fade in status when button is clicked
						jQuery("#additional_results_organizers_wid_"+form_id).fadeOut('slow');	// Fade out text "Additional results ..." after data is saved
					},
					success: function(html) {
						jQuery("#show_more_organizers_button_"+form_id).attr("disabled", false); // Enable button after
						jQuery("#status_show_more_organizers_wid_"+form_id).fadeOut('slow');	// Fade out status after data is saved
						jQuery("#show_more_organizers_wid").append(html); // Add the additional results to page
					}
				}); //close jQuery.ajax
				return false;	
			}	
		</script>

		<style type='text/css'>
			#status_show_more_organizers_wid_<?php 
    echo esc_attr( $k );
    ?> { 
				display: none;
				clear: both;
				background: url(<?php 
    echo esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/loading.gif' );
    ?>) left top no-repeat; 
				text-align: left;
				vertical-align: center;	
				padding-left: 25px;
			}
		</style>

		<?php 
    wp_die();
}

//----------------------------------------------------------------------------------------
// Save organizer data (for invalid data and Optimization with Google Places)
//----------------------------------------------------------------------------------------
add_action( 'wp_ajax_save_org', 'teoai_save_organizer' );
function teoai_save_organizer() {
    // Check the nonce
    if ( !check_ajax_referer( 'events-optimizer-nonce', '_wpnonce', false ) ) {
        wp_die( 'Nonce check failed', '', 403 );
    }
    // Add capability check
    if ( !current_user_can( 'edit_posts' ) ) {
        wp_die( 'Unauthorized', '', 403 );
    }
    // Use wp_unslash and wp_parse_str for safer data processing
    wp_parse_str( wp_unslash( $_POST['data'] ), $organizer );
    // Sanitize each value in the array
    foreach ( $organizer as $key => $value ) {
        $organizer[$key] = sanitize_text_field( $value );
    }
    // Title and description are not part of the post_meta therefore they need to be updated seperatly
    $organizer_post_arr = array(
        'ID'           => sanitize_text_field( $organizer['ID'] ),
        'post_title'   => sanitize_text_field( $organizer['post_title'] ),
        'post_content' => wp_kses_post( $organizer['post_content'] ),
    );
    wp_update_post( $organizer_post_arr );
    // Update organizer with values
    $organizer_arr = array(
        'Phone'   => sanitize_text_field( $organizer['_OrganizerPhone'] ),
        'Website' => sanitize_text_field( $organizer['_OrganizerWebsite'] ),
        'Email'   => sanitize_email( $organizer['_OrganizerEmail'] ),
    );
    tribe_update_organizer( $organizer['ID'], $organizer_arr );
    wp_die();
}

//----------------------------------------------------------------------------------------
// Events with invalid data
//----------------------------------------------------------------------------------------
add_action( 'wp_ajax_events_wid', 'teoai_events_with_invalid_data' );
function teoai_events_with_invalid_data() {
    // Check the nonce
    if ( !check_ajax_referer( 'events-optimizer-nonce', '_wpnonce', false ) ) {
        wp_die( 'Invalid nonce' );
    }
    // Maximum number of results to display per page
    $max_results_per_page = intval( get_option( 'teoai_max_results_per_page', 5 ) );
    // Objects to be ignored while searching for invalid data
    $ignored_and_added_objects = maybe_unserialize( get_option( 'teoai_ignored_and_added_objects' ) );
    if ( empty( $ignored_and_added_objects ) ) {
        $ignored_and_added_objects = array();
    }
    // Whether ignored/added objects should be shown or not
    $show_ignored_objects = filter_var( get_option( 'teoai_show_ignored_objects' ), FILTER_VALIDATE_BOOLEAN );
    $show_added_objects = filter_var( get_option( 'teoai_show_added_objects' ), FILTER_VALIDATE_BOOLEAN );
    // Fields to be ignored while searching for invalid data
    $ignored_field_event_description = get_option( 'teoai_ignored_field_event_description' );
    $ignored_field_event_start = get_option( 'teoai_ignored_field_event_start' );
    $ignored_field_event_end = get_option( 'teoai_ignored_field_event_end' );
    $ignored_field_event_venue = get_option( 'teoai_ignored_field_event_venue' );
    $ignored_field_event_organizer = get_option( 'teoai_ignored_field_event_organizer' );
    $ignored_field_event_website = get_option( 'teoai_ignored_field_event_website' );
    $ignored_field_event_currency_symbol = get_option( 'teoai_ignored_field_event_currency_symbol' );
    $ignored_field_event_cost = get_option( 'teoai_ignored_field_event_cost' );
    // Get custom currency symbols from Events Calendar Options
    $options = get_option( 'tribe_events_calendar_options', '' );
    if ( !empty( $options['tribe_ext_ce_cost_currency_symbols'] ) ) {
        $currency_symbols_arr = explode( '|', $options['tribe_ext_ce_cost_currency_symbols'] );
    } else {
        $currency_symbols_arr = array();
    }
    foreach ( $currency_symbols_arr as $i => $symbol ) {
        $currency_symbols_arr[$i] = sanitize_text_field( $symbol );
    }
    if ( empty( array_filter( $currency_symbols_arr ) ) ) {
        if ( !empty( $options['defaultCurrencySymbol'] ) ) {
            $currency_symbols_arr[0] = sanitize_text_field( $options['defaultCurrencySymbol'] );
        }
    }
    // Get existing venues from Events Calendar and create sorted array for dropdown list
    $venues_arr = array();
    $organizers_arr = array();
    $venues_unordered_arr = tribe_get_venues();
    foreach ( $venues_unordered_arr as $venue ) {
        $venues_arr[] = array(
            'ID'   => intval( $venue->ID ),
            'Name' => sanitize_text_field( $venue->post_title ),
        );
    }
    setlocale( LC_COLLATE, get_locale() );
    $name_arr = array_column( $venues_arr, 'Name' );
    array_multisort(
        $name_arr,
        SORT_ASC,
        SORT_LOCALE_STRING,
        $venues_arr
    );
    // Get existing organizers from Events Calendar and create sorted array for dropdown list
    $organizers_unordered_arr = tribe_get_organizers();
    foreach ( $organizers_unordered_arr as $organizer ) {
        $organizers_arr[] = array(
            'ID'   => intval( $organizer->ID ),
            'Name' => sanitize_text_field( $organizer->post_title ),
        );
    }
    unset($name_arr);
    unset($name_lowercase_arr);
    $name_arr = array_column( $organizers_arr, 'Name' );
    array_multisort(
        $name_arr,
        SORT_ASC,
        SORT_LOCALE_STRING,
        $organizers_arr
    );
    $fields_arr = array(
        'ID'                   => esc_html__( 'ID', 'events-optimizer' ),
        'post_title'           => esc_html__( 'Name', 'events-optimizer' ),
        'post_content'         => esc_html__( 'Description', 'events-optimizer' ),
        '_EventStartDate'      => esc_html__( 'Start', 'events-optimizer' ),
        '_EventEndDate'        => esc_html__( 'End', 'events-optimizer' ),
        '_EventVenueID'        => esc_html__( 'Venue', 'events-optimizer' ),
        '_EventOrganizerID'    => esc_html__( 'Organizer', 'events-optimizer' ),
        '_EventURL'            => esc_html__( 'Website', 'events-optimizer' ),
        '_EventCost'           => esc_html__( 'Cost', 'events-optimizer' ),
        '_EventCurrencySymbol' => esc_html__( 'Currency Symbol', 'events-optimizer' ),
    );
    // Get the next index of the venue if function is called by "Show more" button
    $next_result = ( intval( filter_input( INPUT_POST, 'next_result', FILTER_SANITIZE_NUMBER_INT ) ) ?: 0 );
    $k = $next_result;
    // Set index to the next upcoming venue
    $i = 0;
    // Counter for maximum results per page
    $events_offset = teoai_array_count_key( $ignored_and_added_objects, 'tribe_events' );
    $event = tribe_get_events( [
        'posts_per_page' => $next_result + $events_offset + 3 * $max_results_per_page,
    ] );
    $max_events = wp_count_posts( 'tribe_events' )->publish;
    // Allowed HTML tags for select and option fields to create dropdown lists of venues and organizers
    $allowed_html = array(
        'select' => array(
            'name' => array(),
        ),
        'option' => array(
            'value'    => array(),
            'selected' => array(),
        ),
    );
    // Check if not all venues have been shown yet and maximum results has not been reached
    while ( $k < $max_events and $i < $max_results_per_page ) {
        // Hide venues that have no errors
        $found_error = false;
        $event_details = get_post_meta( $event[$k]->ID ) + array(
            'ID'                => array($event[$k]->ID),
            'post_title'        => array($event[$k]->post_title),
            'post_content'      => array($event[$k]->post_content),
            '_EventVenueID'     => array($event[$k]->_EventVenueID),
            '_EventOrganizerID' => array($event[$k]->_EventOrganizerID),
        );
        // If event isn't part of the ignored or added objects list show it
        if ( array_search( $event[$k]->ID, array_column( $ignored_and_added_objects, 'post_id' ) ) === false || $show_ignored_objects || $show_added_objects ) {
            echo '<form action="" method="POST" id="save_event_wid_form_' . esc_attr( $k ) . '">
				<br>
				<table class="widefat fixed striped" >
				<thead>
				<tr>
				<th>' . esc_html__( 'Field', 'events-optimizer' ) . '</th>
				<th>' . esc_html__( 'Value', 'events-optimizer' ) . '</th>
				<th>' . esc_html__( 'Status', 'events-optimizer' ) . '</th>
				</tr>
				</thead>
				<tbody>';
            foreach ( $fields_arr as $field => $fieldname ) {
                if ( isset( $event_details[$field][0] ) ) {
                    $value = $event_details[$field][0];
                } else {
                    $value = '';
                }
                switch ( $field ) {
                    case 'ID':
                        echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="hidden" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '"/><a href="/wp-admin/post.php?post=' . esc_attr( $event[$k]->ID ) . '&action=edit" target="_blank" rel="noopener noreferrer">' . esc_attr( $value ) . ' <img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/external-link.png' ) . '" class="external-link-icon" alt="External Link"/></a></td><td>--</td></tr>';
                        break;
                    case 'post_title':
                        if ( empty( $value ) ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="https://www.google.de/search?q=' . urlencode( $event_details['post_title'][0] ) . '" target="_blank" rel="noopener noreferrer"> <img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-error">' . esc_attr( $valid ) . '</td></tr>';
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="https://www.google.de/search?q=' . urlencode( $event_details['post_title'][0] ) . '" target="_blank" rel="noopener noreferrer"> <img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                        break;
                    case 'post_content':
                        if ( empty( $value ) ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><textarea name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" rows="8" cols="30"></textarea></td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                            if ( $ignored_field_event_description === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><textarea name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" rows="8" cols="30">' . esc_textarea( $value ) . '</textarea></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                        break;
                    case '_EventStartDate':
                    case '_EventEndDate':
                        $display_format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
                        $tz_display = new DateTimeZone('UTC');
                        // treat as floating time; no timezone conversion
                        $display_value = $value;
                        if ( $value ) {
                            // Normalize ISO with "T" to space for parsing.
                            $raw = str_replace( 'T', ' ', (string) $value );
                            $dt = DateTimeImmutable::createFromFormat( 'Y-m-d H:i:s', $raw, $tz_display );
                            if ( $dt ) {
                                $display_value = $dt->format( $display_format );
                            }
                        }
                        if ( $field === '_EventEndDate' and $value === '' ) {
                            $value = $event_details['_EventStartDate'][0];
                            $display_value = $value;
                            if ( $value ) {
                                $raw = str_replace( 'T', ' ', (string) $value );
                                $dt = DateTimeImmutable::createFromFormat( 'Y-m-d H:i:s', $raw, $tz_display );
                                if ( $dt ) {
                                    $display_value = $dt->format( $display_format );
                                }
                            }
                        }
                        if ( $field === '_EventEndDate' and $value === $event_details['_EventStartDate'][0] ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $display_value ) . '" class="flexible-textfield"/></td><td><span class="field-status-warning">' . esc_html__( 'End is equal with start. Please check!', 'events-optimizer' ) . '</span></td></tr>';
                            break;
                        }
                        if ( empty( $value ) ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $display_value ) . '" class="flexible-textfield"/></td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                            if ( $field === '_EventStartDate' and $ignored_field_event_start === 'false' ) {
                                $found_error = true;
                            }
                            if ( $field === '_EventEndDate' and $ignored_field_event_end === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $display_value ) . '" class="flexible-textfield"/></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                        break;
                    case '_EventVenueID':
                        $venues_list = '<select name="_EventVenueID">';
                        $venue_found = false;
                        foreach ( $venues_arr as $venue ) {
                            if ( intval( $value ) === intval( $venue['ID'] ) ) {
                                $venues_list .= '<option value="' . esc_attr( $venue['ID'] ) . '" selected>' . esc_attr( $venue['Name'] ) . '</option>';
                                $venue_found = true;
                            } else {
                                $venues_list .= '<option value="' . esc_attr( $venue['ID'] ) . '">' . esc_attr( $venue['Name'] ) . '</option>';
                            }
                        }
                        if ( $venue_found ) {
                            $venues_list .= '</select>';
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td>' . wp_kses( $venues_list, $allowed_html ) . '</td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        } else {
                            $venues_list .= '<option value="" selected>--</option>';
                            $venues_list .= '</select>';
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td>' . wp_kses( $venues_list, $allowed_html ) . '</td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                            if ( $ignored_field_event_venue === 'false' ) {
                                $found_error = true;
                            }
                        }
                        break;
                    case '_EventOrganizerID':
                        $organizers_list = '<select name="_EventOrganizerID">';
                        $organizer_found = false;
                        foreach ( $organizers_arr as $organizer ) {
                            if ( intval( $value ) === intval( $organizer['ID'] ) ) {
                                $organizers_list .= '<option value="' . esc_attr( $organizer['ID'] ) . '" selected>' . esc_attr( $organizer['Name'] ) . '</option>';
                                $organizer_found = true;
                            } else {
                                $organizers_list .= '<option value="' . esc_attr( $organizer['ID'] ) . '">' . esc_attr( $organizer['Name'] ) . '</option>';
                            }
                        }
                        if ( $organizer_found ) {
                            $organizers_list .= '</select>';
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td>' . wp_kses( $organizers_list, $allowed_html ) . '</td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        } else {
                            $organizers_list .= '<option value="" selected>--</option>';
                            $organizers_list .= '</select>';
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td>' . wp_kses( $organizers_list, $allowed_html ) . '</td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                            if ( $ignored_field_event_organizer === 'false' ) {
                                $found_error = true;
                            }
                        }
                        break;
                    case '_EventURL':
                        $valid = teoai_url_valid( $value );
                        if ( $valid['status'] != 'OK' ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="https://www.google.de/search?q=' . urlencode( $event_details['post_title'][0] ) . '" target="_blank" rel="noopener noreferrer"> <img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-error">' . esc_attr( $valid['error_message'] ?? '' ) . '</td></tr>';
                            if ( $ignored_field_event_website === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="' . esc_url( $value ) . '" target="_blank" rel="noopener noreferrer"><img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/external-link.png' ) . '" class="external-link-icon" alt="External Link"/></a></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                        break;
                    // Check if currency symbol is in custom currency symbol list
                    case '_EventCurrencySymbol':
                        if ( empty( $value ) ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                            if ( $ignored_field_event_currency_symbol === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            // Custom currency symbols available?
                            if ( !empty( $currency_symbols_arr ) ) {
                                if ( !in_array( $value, $currency_symbols_arr ) ) {
                                    echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-error">' . esc_html__( 'Currency symbol is not in custom currency symbol list', 'events-optimizer' ) . '</span></td></tr>';
                                    if ( $ignored_field_event_currency_symbol === 'false' ) {
                                        $found_error = true;
                                    }
                                } else {
                                    echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                                }
                            } else {
                                echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                            }
                        }
                        break;
                    case '_EventCost':
                        if ( !is_numeric( $value ) ) {
                            // set the local language for the date from the wordpress settings
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/> <a href="https://www.google.de/search?q=' . urlencode( $event_details['post_title'][0] . ' ' . tribe_get_venue( $event[$k]->ID ) . ' ' . date_i18n( get_option( 'date_format' ), strtotime( $event_details['_EventStartDate'][0] ) ) . ' ' . esc_html__( 'Cost', 'events-optimizer' ) ) . '" target="_blank" rel="noopener noreferrer"> <img src="' . esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/search.svg' ) . '" class="search-icon" alt="Search"/></a></td><td><span class="field-status-error">' . esc_html__( 'Field contains invalid characters or is empty', 'events-optimizer' ) . '</span></td></tr>';
                            if ( $ignored_field_event_cost === 'false' ) {
                                $found_error = true;
                            }
                        } else {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                        }
                        break;
                    default:
                        if ( empty( $value ) ) {
                            echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-error">' . esc_html__( 'Field is empty', 'events-optimizer' ) . '</span></td></tr>';
                            if ( $field === 'post_title' ) {
                                $found_error = true;
                            }
                        } else {
                            if ( strlen( $value ) <= 4 ) {
                                echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-warning">' . esc_html__( 'Field content is very short', 'events-optimizer' ) . '</span></td></tr>';
                                if ( $field === 'post_title' ) {
                                    $found_error = true;
                                }
                            } else {
                                echo '<tr><td>' . esc_attr( $fieldname ) . '</td><td><input type="text" name="' . esc_attr( $field ) . '" id="' . esc_attr( $field ) . '" value="' . esc_attr( $value ) . '" class="flexible-textfield"/></td><td><span class="field-status-ok">' . esc_html__( 'OK', 'events-optimizer' ) . '</span></td></tr>';
                            }
                        }
                }
                // end switch
            }
            // end foreach
            echo '</tbody>
					</table>	
					<p><input type="button" name="action" class="button button-primary" id="save_event_wid_button_' . esc_attr( $k ) . '" value="' . esc_html__( 'Save changes', 'events-optimizer' ) . '" onclick="save_form(' . "'" . esc_attr( $k ) . "'" . ');" />
					&nbsp;&nbsp;&nbsp;<input type="button" name="action" class="button delete" id="ignore_object_wid_button_' . esc_attr( $k ) . '" value="' . esc_html__( 'Ignore', 'events-optimizer' ) . '" onclick="ignore_object(' . "'" . esc_attr( $k ) . "'" . ');"';
            disabled( !teoai_fs()->can_use_premium_code__premium_only() );
            echo '/>
					</p><div id="status_save_event_wid_' . esc_attr( $k ) . '">' . esc_html__( 'SAVING', 'events-optimizer' ) . '</div></p><br>
					</form>';
        }
        // end if array_search(
        $nonce = wp_create_nonce( 'events-optimizer-nonce' );
        ?>	

			<script  type='text/javascript'>
				function save_form(form_id){
					var datastring = jQuery("#save_event_wid_form_"+form_id).serialize(); 
					jQuery("#save_event_wid_button_"+form_id).attr("disabled", true); // Disable button while saving
					jQuery.ajax({
						type: "POST",
						url: "<?php 
        echo esc_url( admin_url( 'admin-ajax.php' ) );
        ?>",
						data: { 
							action: 'save_eve',
							_ajax_nonce: '<?php 
        echo esc_attr( $nonce );
        ?>',
							data: datastring,
						},
						beforeSend: function() {
							jQuery("#status_save_event_wid_"+form_id).fadeIn('fast');  // Fade in status when button is clicked
						},
						success: function(html) {
							jQuery("#status_save_event_wid_"+form_id).fadeOut('slow');	// Fade out status after data is saved
							jQuery("#save_event_wid_button_"+form_id).attr("disabled", false); // Enable button after saving
							jQuery("#save_event_wid_form_"+form_id).slideUp(); // Slide organizer form away after saving									
						}
					}); //close jQuery.ajax
					return false;	
				}
				function ignore_object(form_id){
					var datastring = jQuery("#save_event_wid_form_"+form_id).serialize() + '&type=tribe_events&status=ignored';
					jQuery("#ignore_object_wid_button_"+form_id).attr("disabled", true); // Disable button while ignoring
					jQuery.ajax({
						type: "POST",
						url: "<?php 
        echo esc_url( admin_url( 'admin-ajax.php' ) );
        ?>",
						data: { 
							action: 'add_obj',
							_ajax_nonce: '<?php 
        echo esc_attr( $nonce );
        ?>',
							data: datastring,
						},
						beforeSend: function() {
						},
						success: function(html) {
							jQuery("#status_save_event_wid_"+form_id).fadeOut('slow');	// Fade out status after data is ignored
							jQuery("#ignore_object_wid_button_"+form_id).attr("disabled", false); // Enable button after ignoring
							jQuery("#save_event_wid_form_"+form_id).slideUp(); // Slide venue form away after ignoring							
						}
					}); //close jQuery.ajax
					return false;	
				}						
			</script>	

			<style type='text/css'>
				#status_save_event_wid_<?php 
        echo esc_attr( $k );
        ?> { 
					display: none;
					clear: both;
					background: url(<?php 
        echo esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/loading.gif' );
        ?>) left top no-repeat; 
					text-align: left;
					vertical-align: center;	
					padding-left: 25px;
				}
				<?php 
        if ( $found_error === false ) {
            echo "#save_event_wid_form_" . esc_attr( $k ) . ", #save_event_wid_button_" . esc_attr( $k ) . " { display: none; }";
        }
        ?>	
			</style>

			<?php 
        // if invalid data is found increase counter for maximum results per page
        if ( $found_error === true ) {
            $i++;
        }
        $k++;
    }
    // end while
    if ( $k < $max_events ) {
        echo '<div id="additional_results_events_wid_' . esc_attr( $k ) . '"><p><strong>' . esc_html__( 'Additional results available.', 'events-optimizer' ) . '</strong></p></div>';
        echo '<p><input type="submit" name="action" class="button button-primary" id="show_more_events_wid_button_' . esc_attr( $k ) . '" value="' . esc_html__( 'Show more', 'events-optimizer' ) . '" onclick="show_more(' . "'" . esc_attr( $k ) . "'" . ');" /></p>';
        echo '<div id="show_more_events_wid"></div>';
        echo '<div id="status_show_more_events_wid_' . esc_attr( $k ) . '">' . esc_html__( 'ANALYZING', 'events-optimizer' ) . '</div>';
    } else {
        echo '<span class="field-status-ok">' . esc_html__( 'No (more) results found!', 'events-optimizer' ) . '</span>';
    }
    $nonce = wp_create_nonce( 'events-optimizer-nonce' );
    ?>	
			
		<script  type='text/javascript'>
		
			function show_more(form_id){
				jQuery("#show_more_events_wid_button_"+form_id).fadeOut('slow'); // Hide button after  		
				jQuery("#show_more_events_wid_button_"+form_id).attr("disabled", true); // Disable button while retrieving more results
				jQuery.ajax({
					type: "POST",
					url: "<?php 
    echo esc_url( admin_url( 'admin-ajax.php' ) );
    ?>",
					data: { 
						action: 'events_wid',
						next_result: form_id,
						_ajax_nonce: '<?php 
    echo esc_attr( $nonce );
    ?>' 
					},
					beforeSend: function() {
						jQuery("#status_show_more_events_wid_"+form_id).fadeIn('fast');  // Fade in status when button is clicked
						jQuery("#additional_results_events_wid_"+form_id).fadeOut('slow');	// Fade out text "Additional results ..." after data is saved
					},
					success: function(html) {
						jQuery("#show_more_events_wid_button_"+form_id).attr("disabled", false); // Enable button after
						jQuery("#status_show_more_events_wid_"+form_id).fadeOut('slow');	// Fade out status after data is saved
						jQuery("#show_more_events_wid").append(html); // Add the additional results to page
					}
				}); //close jQuery.ajax
				return false;	
			}	
		</script>

		<style type='text/css'>
			#status_show_more_events_wid_<?php 
    echo esc_attr( $k );
    ?> { 
				display: none;
				clear: both;
				background: url(<?php 
    echo esc_url( plugin_dir_url( __FILE__ ) . 'assets/images/loading.gif' );
    ?>) left top no-repeat; 
				text-align: left;
				vertical-align: center;	
				padding-left: 25px;
			}
		</style>

		<?php 
    wp_die();
}

//----------------------------------------------------------------------------------------
// Save event data (for events with invalid data)
//----------------------------------------------------------------------------------------
add_action( 'wp_ajax_save_eve', 'teoai_save_event' );
function teoai_save_event() {
    // Check the nonce
    if ( !check_ajax_referer( 'events-optimizer-nonce', '_wpnonce', false ) ) {
        wp_die( 'Nonce check failed', '', 403 );
    }
    // Add capability check
    if ( !current_user_can( 'edit_posts' ) ) {
        wp_die( 'Unauthorized', '', 403 );
    }
    // Use wp_unslash and wp_parse_str for safer data processing
    wp_parse_str( wp_unslash( $_POST['data'] ), $event );
    // Sanitize each value in the array
    foreach ( $event as $key => $value ) {
        $event[$key] = sanitize_text_field( $value );
    }
    // Helper to parse date/time from the localized display format, treating the value as "floating" (no timezone conversion).
    $floating_tz = new DateTimeZone('UTC');
    $display_format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
    $parse_datetime = function ( string $raw ) use($display_format, $floating_tz) {
        $raw = trim( $raw );
        if ( '' === $raw ) {
            return null;
        }
        $dt = DateTimeImmutable::createFromFormat( $display_format, $raw, $floating_tz );
        if ( $dt instanceof DateTimeImmutable ) {
            return $dt;
        }
        $raw_iso = str_replace( 'T', ' ', $raw );
        $dt = DateTimeImmutable::createFromFormat( 'Y-m-d H:i:s', $raw_iso, $floating_tz );
        if ( $dt instanceof DateTimeImmutable ) {
            return $dt;
        }
        return null;
    };
    $start_raw = ( isset( $event['_EventStartDate'] ) ? $event['_EventStartDate'] : '' );
    $end_raw = ( isset( $event['_EventEndDate'] ) ? $event['_EventEndDate'] : '' );
    $start_dt = $parse_datetime( $start_raw );
    $end_dt = $parse_datetime( $end_raw );
    // Only fall back to start when end is truly empty.
    if ( '' === trim( $end_raw ) && $start_dt ) {
        $end_dt = $start_dt;
    }
    // Fallback to substr if parsing fails (legacy format). Keep entered values as-is (no timezone conversion).
    $start_date = ( $start_dt ? $start_dt->format( 'Y-m-d' ) : (( $start_raw ? substr( $start_raw, 0, 10 ) : '' )) );
    $end_date = ( $end_dt ? $end_dt->format( 'Y-m-d' ) : (( $end_raw ? substr( $end_raw, 0, 10 ) : '' )) );
    $start_time = ( $start_dt ? $start_dt->format( 'H:i' ) : (( $start_raw ? substr( $start_raw, 11, 5 ) : '' )) );
    $end_time = ( $end_dt ? $end_dt->format( 'H:i' ) : (( $end_raw ? substr( $end_raw, 11, 5 ) : '' )) );
    // Title and description can't be updated directly with the TEC API (empty fields gets ignored - bug?) and therefore it needs to be updated seperatly
    $event_post_arr = array(
        'ID'           => $event['ID'],
        'post_title'   => sanitize_text_field( $event['post_title'] ),
        'post_content' => wp_kses_post( $event['post_content'] ),
    );
    wp_update_post( $event_post_arr );
    // Update event with additional values
    $event_arr = array(
        'EventStartDate'      => $start_date,
        'EventEndDate'        => $end_date,
        'EventStartHour'      => substr( $start_time, 0, 2 ),
        'EventEndHour'        => substr( $end_time, 0, 2 ),
        'EventStartMinute'    => substr( $start_time, 3, 2 ),
        'EventEndMinute'      => substr( $end_time, 3, 2 ),
        'Venue'               => array(
            'VenueID' => sanitize_text_field( $event['_EventVenueID'] ),
        ),
        'Organizer'           => array(
            'OrganizerID' => sanitize_text_field( $event['_EventOrganizerID'] ),
        ),
        'EventURL'            => sanitize_text_field( $event['_EventURL'] ),
        'EventCost'           => sanitize_text_field( $event['_EventCost'] ),
        'EventCurrencySymbol' => sanitize_text_field( $event['_EventCurrencySymbol'] ),
    );
    //	'FeaturedImage'			=> sanitize_text_field( $event[ '_thumbnail_id' ] )
    tribe_update_event( $event['ID'], $event_arr );
    wp_die();
}

//----------------------------------------------------------------------------------------
// Save settings
//----------------------------------------------------------------------------------------
add_action( 'wp_ajax_save_set', 'teoai_save_settings' );
function teoai_save_settings() {
    // Check the nonce
    if ( !check_ajax_referer( 'events-optimizer-nonce', '_wpnonce', false ) ) {
        wp_die( 'Nonce check failed', '', 403 );
    }
    if ( !current_user_can( 'manage_options' ) ) {
        wp_die( 'Unauthorized', '', 403 );
    }
    // Max results per page (limit to 20)
    $max_results_per_page = min( 20, intval( wp_unslash( $_POST['max_results_per_page'] ) ) );
    update_option( 'teoai_max_results_per_page', $max_results_per_page );
    // Duplicate detection thresholds are available in all versions
    if ( isset( $_POST['duplicate_organizers_levenshtein'] ) ) {
        update_option( 'teoai_duplicate_organizers_levenshtein', floatval( $_POST['duplicate_organizers_levenshtein'] ) );
    }
    if ( isset( $_POST['duplicate_venues_levenshtein'] ) ) {
        update_option( 'teoai_duplicate_venues_levenshtein', floatval( $_POST['duplicate_venues_levenshtein'] ) );
    }
    wp_die();
}

//----------------------------------------------------------------------------------------
// DataForSEO locations cache (download on demand via settings)
//----------------------------------------------------------------------------------------
function teoai_dataforseo_locations_cache_path() {
    $upload_dir = wp_upload_dir();
    if ( empty( $upload_dir['basedir'] ) ) {
        return new WP_Error('teoai_upload_dir_unavailable', esc_html__( 'Upload directory is not available.', 'events-optimizer' ));
    }
    $cache_dir = trailingslashit( $upload_dir['basedir'] ) . 'events-optimizer';
    if ( !wp_mkdir_p( $cache_dir ) ) {
        return new WP_Error('teoai_cannot_create_cache_dir', esc_html__( 'Unable to create cache directory for locations.', 'events-optimizer' ));
    }
    return trailingslashit( $cache_dir ) . 'google-locations.json';
}

function teoai_get_dataforseo_locations_meta() {
    $meta = get_option( 'teoai_dataforseo_locations_meta', array() );
    if ( !is_array( $meta ) ) {
        $meta = array();
    }
    return wp_parse_args( $meta, array(
        'last_updated' => null,
        'count'        => 0,
        'hash'         => '',
        'size'         => 0,
    ) );
}

function teoai_save_dataforseo_locations_cache(  $raw_body  ) {
    $cache_path = teoai_dataforseo_locations_cache_path();
    if ( is_wp_error( $cache_path ) ) {
        return $cache_path;
    }
    if ( false === file_put_contents( $cache_path, $raw_body ) ) {
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
        return new WP_Error('teoai_cannot_write_cache', esc_html__( 'Could not write the locations cache file.', 'events-optimizer' ));
    }
    $decoded = json_decode( $raw_body, true );
    $locations = array();
    if ( isset( $decoded['tasks'][0]['result'][0]['items'] ) && is_array( $decoded['tasks'][0]['result'][0]['items'] ) ) {
        $locations = $decoded['tasks'][0]['result'][0]['items'];
    } elseif ( isset( $decoded['tasks'][0]['result'] ) && is_array( $decoded['tasks'][0]['result'] ) ) {
        $locations = $decoded['tasks'][0]['result'];
    } elseif ( isset( $decoded['items'] ) && is_array( $decoded['items'] ) ) {
        $locations = $decoded['items'];
    }
    $meta = array(
        'last_updated' => current_time( 'timestamp' ),
        'count'        => ( is_array( $locations ) ? count( $locations ) : 0 ),
        'hash'         => md5( $raw_body ),
        'size'         => ( file_exists( $cache_path ) ? filesize( $cache_path ) : 0 ),
    );
    update_option( 'teoai_dataforseo_locations_meta', $meta );
    return array(
        'path' => $cache_path,
        'meta' => $meta,
    );
}

function teoai_read_dataforseo_locations_cache() {
    // Prefer uploaded/updated file, but fall back to bundled JSON if uploads are unavailable.
    $cache_path = teoai_dataforseo_locations_cache_path();
    // Large file: raise memory limit for admin context to avoid fatal errors when decoding.
    if ( function_exists( 'wp_raise_memory_limit' ) ) {
        wp_raise_memory_limit( 'admin' );
    } elseif ( function_exists( 'ini_set' ) ) {
        // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_ini_set -- fallback if wp_raise_memory_limit() is unavailable.
        @ini_set( 'memory_limit', '512M' );
    }
    $contents = '';
    $bundled = plugin_dir_path( __FILE__ ) . 'assets/data/google-locations.json';
    $used_cache = false;
    if ( !is_wp_error( $cache_path ) && file_exists( $cache_path ) ) {
        $contents = file_get_contents( $cache_path );
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_get_contents
        $used_cache = true;
        // If cache is empty/corrupt, try the bundled file immediately.
        if ( empty( $contents ) && file_exists( $bundled ) ) {
            $contents = file_get_contents( $bundled );
            // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_get_contents
            $used_cache = false;
        }
    } elseif ( file_exists( $bundled ) ) {
        $contents = file_get_contents( $bundled );
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_get_contents
        // Copy bundled file to uploads for consistent path.
        if ( !is_wp_error( $cache_path ) ) {
            // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
            @file_put_contents( $cache_path, $contents );
        }
    }
    if ( empty( $contents ) ) {
        return new WP_Error('teoai_locations_cache_missing', esc_html__( 'No cached locations available. Please update the list first.', 'events-optimizer' ));
    }
    $raw_contents = $contents;
    $data = json_decode( $contents, true );
    // If the cache was used but parsing failed, retry with the bundled file before failing.
    if ( (null === $data || !is_array( $data )) && $used_cache && file_exists( $bundled ) ) {
        $contents = file_get_contents( $bundled );
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_get_contents
        $raw_contents = $contents;
        $data = json_decode( $contents, true );
        $used_cache = false;
    }
    if ( null === $data || !is_array( $data ) ) {
        // Try to parse TSV/CSV fallback (header line assumed).
        $lines = preg_split( '/\\r\\n|\\r|\\n/', $raw_contents );
        $lines = array_filter( $lines, 'strlen' );
        if ( !empty( $lines ) ) {
            $headers = str_getcsv( array_shift( $lines ), "\t" );
            $rows = array();
            foreach ( $lines as $line ) {
                $cols = str_getcsv( $line, "\t" );
                if ( empty( $cols ) ) {
                    continue;
                }
                $row = array();
                foreach ( $headers as $idx => $header ) {
                    $key = trim( $header );
                    $row[$key] = ( isset( $cols[$idx] ) ? $cols[$idx] : '' );
                }
                if ( isset( $row['location_code'] ) ) {
                    $rows[] = $row;
                }
            }
            if ( !empty( $rows ) ) {
                $data = $rows;
            }
        }
    }
    if ( null === $data || !is_array( $data ) ) {
        return new WP_Error('teoai_locations_cache_invalid', esc_html__( 'Cached locations file is invalid. Please refresh the list.', 'events-optimizer' ));
    }
    if ( isset( $data['tasks'][0]['result'][0]['items'] ) && is_array( $data['tasks'][0]['result'][0]['items'] ) ) {
        $data = $data['tasks'][0]['result'][0]['items'];
    } elseif ( isset( $data['tasks'][0]['result'] ) && is_array( $data['tasks'][0]['result'] ) ) {
        $data = $data['tasks'][0]['result'];
    } elseif ( isset( $data['items'] ) && is_array( $data['items'] ) ) {
        $data = $data['items'];
    } elseif ( !is_array( $data ) ) {
        return new WP_Error('teoai_locations_cache_invalid', esc_html__( 'Cached locations file is invalid. Please refresh the list.', 'events-optimizer' ));
    }
    // Normalize.
    $locations = array_map( function ( $item ) {
        return array(
            'location_code' => ( isset( $item['location_code'] ) ? $item['location_code'] : null ),
            'location_name' => ( isset( $item['location_name'] ) ? $item['location_name'] : '' ),
            'location_type' => ( isset( $item['location_type'] ) ? $item['location_type'] : '' ),
        );
    }, $data );
    unset($data);
    return $locations;
}

function teoai_format_dataforseo_location_label(  $location  ) {
    if ( !is_array( $location ) ) {
        return '';
    }
    $name = ( isset( $location['location_name'] ) ? $location['location_name'] : '' );
    $type = ( isset( $location['location_type'] ) ? $location['location_type'] : '' );
    $label = $name;
    if ( $type !== '' ) {
        $label .= ' (' . $type . ')';
    }
    return trim( $label );
}

function teoai_find_dataforseo_location_label(  $location_code  ) {
    $location_code = intval( $location_code );
    if ( !$location_code ) {
        return '';
    }
    static $cached_locations = null;
    if ( null === $cached_locations ) {
        $cached_locations = teoai_read_dataforseo_locations_cache();
    }
    $locations = $cached_locations;
    if ( is_wp_error( $locations ) ) {
        return '';
    }
    foreach ( $locations as $location ) {
        if ( isset( $location['location_code'] ) && intval( $location['location_code'] ) === $location_code ) {
            return teoai_format_dataforseo_location_label( $location );
        }
    }
    return '';
}

function teoai_download_dataforseo_locations(  $login, $password  ) {
    $response = wp_remote_get( 'https://api.dataforseo.com/v3/serp/google/events/locations', array(
        'headers' => array(
            'Authorization' => 'Basic ' . base64_encode( $login . ':' . $password ),
        ),
        'timeout' => 120,
    ) );
    if ( is_wp_error( $response ) ) {
        return $response;
    }
    $code = wp_remote_retrieve_response_code( $response );
    if ( 200 !== $code ) {
        return new WP_Error('teoai_locations_http_error', esc_html__( 'Could not update locations. Please check credentials and try again.', 'events-optimizer' ), array(
            'status' => $code,
        ));
    }
    $body = wp_remote_retrieve_body( $response );
    $data = json_decode( $body, true );
    if ( null === $data ) {
        return new WP_Error('teoai_locations_decode_error', esc_html__( 'Could not decode locations response.', 'events-optimizer' ));
    }
    $locations = array();
    if ( isset( $data['tasks'][0]['result'][0]['items'] ) && is_array( $data['tasks'][0]['result'][0]['items'] ) ) {
        $locations = $data['tasks'][0]['result'][0]['items'];
    } elseif ( isset( $data['items'] ) && is_array( $data['items'] ) ) {
        $locations = $data['items'];
    } elseif ( is_array( $data ) ) {
        $locations = $data;
    }
    if ( empty( $locations ) ) {
        return new WP_Error('teoai_locations_empty', esc_html__( 'Locations response did not include any items.', 'events-optimizer' ));
    }
    // Keep only the essential fields to reduce size.
    $locations = array_map( function ( $item ) {
        return array(
            'location_code' => ( isset( $item['location_code'] ) ? $item['location_code'] : null ),
            'location_name' => ( isset( $item['location_name'] ) ? $item['location_name'] : '' ),
            'location_type' => ( isset( $item['location_type'] ) ? $item['location_type'] : '' ),
        );
    }, $locations );
    return array(
        'locations' => $locations,
        'raw_body'  => $body,
    );
}

//----------------------------------------------------------------------------------------
// DataForSEO languages cache helpers (upload path + fallback to bundled file)
//----------------------------------------------------------------------------------------
function teoai_dataforseo_languages_cache_path() {
    $upload_dir = wp_upload_dir();
    if ( empty( $upload_dir['basedir'] ) ) {
        return new WP_Error('teoai_upload_dir_unavailable', esc_html__( 'Upload directory is not available.', 'events-optimizer' ));
    }
    $cache_dir = trailingslashit( $upload_dir['basedir'] ) . 'events-optimizer';
    if ( !wp_mkdir_p( $cache_dir ) ) {
        return new WP_Error('teoai_cannot_create_cache_dir', esc_html__( 'Unable to create cache directory for languages.', 'events-optimizer' ));
    }
    return trailingslashit( $cache_dir ) . 'google-languages.json';
}

function teoai_read_dataforseo_languages_cache() {
    // Prefer uploaded/updated file.
    $cache_path = teoai_dataforseo_languages_cache_path();
    $contents = '';
    $bundled = plugin_dir_path( __FILE__ ) . 'assets/data/google-languages.json';
    $used_cache = false;
    if ( !is_wp_error( $cache_path ) && file_exists( $cache_path ) ) {
        $contents = file_get_contents( $cache_path );
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_get_contents
        $used_cache = true;
        // If the cached file is empty/corrupted, fall back to the bundled file.
        if ( empty( $contents ) && file_exists( $bundled ) ) {
            $contents = file_get_contents( $bundled );
            // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_get_contents
            $used_cache = false;
        }
    } elseif ( file_exists( $bundled ) ) {
        $contents = file_get_contents( $bundled );
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_get_contents
        if ( !is_wp_error( $cache_path ) ) {
            // Copy bundled file to uploads for consistent path.
            // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
            @file_put_contents( $cache_path, $contents );
        }
    }
    if ( empty( $contents ) ) {
        return new WP_Error('teoai_languages_cache_missing', esc_html__( 'No cached languages available. Please update the list first.', 'events-optimizer' ));
    }
    $data = json_decode( $contents, true );
    unset($contents);
    // If the cache file was read but is invalid, try the bundled fallback before erroring out.
    if ( null === $data && $used_cache && file_exists( $bundled ) ) {
        $contents = file_get_contents( $bundled );
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_get_contents
        $data = json_decode( $contents, true );
        unset($contents);
        $used_cache = false;
    }
    if ( null === $data ) {
        return new WP_Error('teoai_languages_cache_invalid', esc_html__( 'Cached languages file is invalid. Please refresh the list.', 'events-optimizer' ));
    }
    // Extract items list.
    if ( isset( $data['tasks'][0]['result'][0]['items'] ) && is_array( $data['tasks'][0]['result'][0]['items'] ) ) {
        $data = $data['tasks'][0]['result'][0]['items'];
    } elseif ( isset( $data['tasks'][0]['result'] ) && is_array( $data['tasks'][0]['result'] ) ) {
        $data = $data['tasks'][0]['result'];
    } elseif ( isset( $data['items'] ) && is_array( $data['items'] ) ) {
        $data = $data['items'];
    } elseif ( !is_array( $data ) ) {
        return new WP_Error('teoai_languages_cache_invalid', esc_html__( 'Cached languages file is invalid. Please refresh the list.', 'events-optimizer' ));
    }
    // Normalize.
    $languages = array_map( function ( $item ) {
        return array(
            'language_name' => ( isset( $item['language_name'] ) ? $item['language_name'] : '' ),
            'language_code' => ( isset( $item['language_code'] ) ? $item['language_code'] : '' ),
        );
    }, $data );
    unset($data);
    return $languages;
}

// Download languages (DataForSEO App Data Google languages endpoint).
function teoai_download_dataforseo_languages(  $login, $password  ) {
    $response = wp_remote_get( 'https://api.dataforseo.com/v3/app_data/google/languages', array(
        'headers' => array(
            'Authorization' => 'Basic ' . base64_encode( $login . ':' . $password ),
        ),
        'timeout' => 120,
    ) );
    if ( is_wp_error( $response ) ) {
        return $response;
    }
    $code = wp_remote_retrieve_response_code( $response );
    if ( 200 !== $code ) {
        return new WP_Error('teoai_languages_http_error', esc_html__( 'Could not update languages. Please check credentials and try again.', 'events-optimizer' ), array(
            'status' => $code,
        ));
    }
    $body = wp_remote_retrieve_body( $response );
    $data = json_decode( $body, true );
    if ( null === $data ) {
        return new WP_Error('teoai_languages_decode_error', esc_html__( 'Could not decode languages response. Please refresh and try again.', 'events-optimizer' ));
    }
    $languages = array();
    if ( isset( $data['tasks'][0]['result'][0]['items'] ) && is_array( $data['tasks'][0]['result'][0]['items'] ) ) {
        $languages = $data['tasks'][0]['result'][0]['items'];
    } elseif ( isset( $data['items'] ) && is_array( $data['items'] ) ) {
        $languages = $data['items'];
    } elseif ( is_array( $data ) ) {
        $languages = $data;
    }
    if ( empty( $languages ) ) {
        return new WP_Error('teoai_languages_empty', esc_html__( 'Languages response did not include any items.', 'events-optimizer' ));
    }
    return array(
        'languages' => $languages,
        'raw_body'  => $body,
    );
}

function teoai_get_dataforseo_languages_meta() {
    $meta = get_option( 'teoai_dataforseo_languages_meta', array() );
    if ( !is_array( $meta ) ) {
        $meta = array();
    }
    return wp_parse_args( $meta, array(
        'last_updated' => null,
        'count'        => 0,
        'size'         => 0,
        'hash'         => '',
    ) );
}

//----------------------------------------------------------------------------------------
// Google Translation API languages cache (Google Places language dropdown)
//----------------------------------------------------------------------------------------
function teoai_google_translation_languages_cache_path() {
    $upload_dir = wp_upload_dir();
    if ( empty( $upload_dir['basedir'] ) ) {
        return new WP_Error('teoai_upload_dir_unavailable', esc_html__( 'Upload directory is not available.', 'events-optimizer' ));
    }
    $cache_dir = trailingslashit( $upload_dir['basedir'] ) . 'events-optimizer';
    if ( !wp_mkdir_p( $cache_dir ) ) {
        return new WP_Error('teoai_cannot_create_cache_dir', esc_html__( 'Unable to create cache directory for languages.', 'events-optimizer' ));
    }
    return trailingslashit( $cache_dir ) . 'google-translation-languages.json';
}

function teoai_get_google_translation_languages_meta() {
    $meta = get_option( 'teoai_google_translation_languages_meta', array() );
    if ( !is_array( $meta ) ) {
        $meta = array();
    }
    return wp_parse_args( $meta, array(
        'last_updated' => null,
        'count'        => 0,
        'size'         => 0,
        'hash'         => '',
    ) );
}

function teoai_save_google_translation_languages_cache(  $raw_body  ) {
    $cache_path = teoai_google_translation_languages_cache_path();
    if ( is_wp_error( $cache_path ) ) {
        return $cache_path;
    }
    if ( false === file_put_contents( $cache_path, $raw_body ) ) {
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
        return new WP_Error('teoai_cannot_write_cache', esc_html__( 'Could not write the languages cache file.', 'events-optimizer' ));
    }
    $decoded = json_decode( $raw_body, true );
    $languages = array();
    if ( isset( $decoded['data']['languages'] ) && is_array( $decoded['data']['languages'] ) ) {
        $languages = $decoded['data']['languages'];
    } elseif ( isset( $decoded['languages'] ) && is_array( $decoded['languages'] ) ) {
        $languages = $decoded['languages'];
    }
    $meta = array(
        'last_updated' => current_time( 'timestamp' ),
        'count'        => ( is_array( $languages ) ? count( $languages ) : 0 ),
        'size'         => ( file_exists( $cache_path ) ? filesize( $cache_path ) : 0 ),
        'hash'         => md5( $raw_body ),
    );
    update_option( 'teoai_google_translation_languages_meta', $meta );
    return array(
        'path' => $cache_path,
        'meta' => $meta,
    );
}

function teoai_read_google_translation_languages_cache() {
    $cache_path = teoai_google_translation_languages_cache_path();
    $contents = '';
    if ( !is_wp_error( $cache_path ) && file_exists( $cache_path ) ) {
        $contents = file_get_contents( $cache_path );
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_get_contents
    } else {
        $bundled = plugin_dir_path( __FILE__ ) . 'assets/data/google-translation-languages.json';
        if ( file_exists( $bundled ) ) {
            $contents = file_get_contents( $bundled );
            // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_get_contents
        }
    }
    if ( empty( $contents ) ) {
        return new WP_Error('teoai_translation_languages_cache_missing', esc_html__( 'No cached languages available. Please update the list first.', 'events-optimizer' ));
    }
    $data = json_decode( $contents, true );
    unset($contents);
    if ( null === $data ) {
        return new WP_Error('teoai_translation_languages_cache_invalid', esc_html__( 'Cached languages file is invalid. Please refresh the list.', 'events-optimizer' ));
    }
    if ( isset( $data['data']['languages'] ) && is_array( $data['data']['languages'] ) ) {
        $data = $data['data']['languages'];
    } elseif ( isset( $data['languages'] ) && is_array( $data['languages'] ) ) {
        $data = $data['languages'];
    }
    if ( !is_array( $data ) ) {
        return new WP_Error('teoai_translation_languages_cache_invalid', esc_html__( 'Cached languages file is invalid. Please refresh the list.', 'events-optimizer' ));
    }
    $languages = array_map( function ( $item ) {
        return array(
            'language_code' => ( isset( $item['language'] ) ? $item['language'] : (( isset( $item['language_code'] ) ? $item['language_code'] : '' )) ),
            'language_name' => ( isset( $item['name'] ) ? $item['name'] : (( isset( $item['language_name'] ) ? $item['language_name'] : '' )) ),
        );
    }, $data );
    // Deduplicate: first by language_code (case-insensitive), then by language_name to avoid duplicate labels (e.g., Chinese Simplified twice).
    $unique = array();
    $labels = array();
    foreach ( $languages as $lang ) {
        $code = ( isset( $lang['language_code'] ) ? trim( $lang['language_code'] ) : '' );
        $label = ( isset( $lang['language_name'] ) ? trim( $lang['language_name'] ) : '' );
        $code_key = strtolower( $code );
        $label_key = strtolower( $label );
        if ( $code_key && isset( $unique[$code_key] ) ) {
            continue;
        }
        if ( $label_key && isset( $labels[$label_key] ) ) {
            continue;
        }
        if ( $code_key ) {
            $unique[$code_key] = $lang;
        } else {
            $unique[] = $lang;
        }
        if ( $label_key ) {
            $labels[$label_key] = true;
        }
    }
    unset($data);
    // If codes were used as keys, drop keys.
    return array_values( $unique );
}

function teoai_download_google_translation_languages(  $api_key  ) {
    $url = add_query_arg( array(
        'target' => 'en',
        'key'    => $api_key,
    ), 'https://translation.googleapis.com/language/translate/v2/languages' );
    $response = wp_remote_get( $url, array(
        'timeout' => 45,
    ) );
    if ( is_wp_error( $response ) ) {
        return $response;
    }
    $code = wp_remote_retrieve_response_code( $response );
    if ( 200 !== $code ) {
        return new WP_Error('teoai_translation_languages_http_error', esc_html__( 'Languages request failed.', 'events-optimizer' ), array(
            'status' => $code,
        ));
    }
    $body = wp_remote_retrieve_body( $response );
    $data = json_decode( $body, true );
    if ( null === $data ) {
        return new WP_Error('teoai_translation_languages_decode_error', esc_html__( 'Could not decode translation languages response.', 'events-optimizer' ));
    }
    $languages = array();
    if ( isset( $data['data']['languages'] ) && is_array( $data['data']['languages'] ) ) {
        $languages = $data['data']['languages'];
    } elseif ( isset( $data['languages'] ) && is_array( $data['languages'] ) ) {
        $languages = $data['languages'];
    }
    if ( empty( $languages ) ) {
        return new WP_Error('teoai_translation_languages_empty', esc_html__( 'Languages response did not include any items.', 'events-optimizer' ));
    }
    return array(
        'languages' => $languages,
        'raw_body'  => $body,
    );
}

add_action( 'wp_ajax_teoai_refresh_dataforseo_locations', 'teoai_refresh_dataforseo_locations' );
function teoai_refresh_dataforseo_locations() {
    // Raise limits for large location payloads.
    if ( function_exists( 'wp_raise_memory_limit' ) ) {
        wp_raise_memory_limit( 'admin' );
    } elseif ( function_exists( 'ini_set' ) ) {
        @ini_set( 'memory_limit', '512M' );
        // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_ini_set
    }
    if ( function_exists( 'set_time_limit' ) ) {
        @set_time_limit( 120 );
        // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
    }
    if ( !check_ajax_referer( 'events-optimizer-nonce', '_ajax_nonce', false ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Invalid nonce', 'events-optimizer' ),
        ), 403 );
    }
    if ( !current_user_can( 'manage_options' ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Unauthorized', 'events-optimizer' ),
        ), 403 );
    }
    wp_send_json_error( array(
        'message' => esc_html__( 'This feature is available in the Pro version.', 'events-optimizer' ),
    ), 403 );
    $login = get_option( 'teoai_dataforseo_api_login', '' );
    $password = get_option( 'teoai_dataforseo_api_password', '' );
    if ( empty( $login ) || empty( $password ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Please add DataForSEO credentials first.', 'events-optimizer' ),
        ), 400 );
    }
    $download = teoai_download_dataforseo_locations( $login, $password );
    if ( is_wp_error( $download ) ) {
        wp_send_json_error( array(
            'message' => $download->get_error_message(),
        ), 500 );
    }
    // Save full response to uploads file.
    $written = teoai_save_dataforseo_locations_cache( $download['raw_body'] );
    if ( is_wp_error( $written ) ) {
        wp_send_json_error( array(
            'message' => $written->get_error_message(),
        ), 500 );
    }
    wp_send_json_success( array(
        'meta' => $written['meta'],
    ) );
}

add_action( 'wp_ajax_teoai_search_dataforseo_locations', 'teoai_search_dataforseo_locations' );
function teoai_search_dataforseo_locations() {
    if ( !check_ajax_referer( 'events-optimizer-nonce', '_ajax_nonce', false ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Invalid nonce', 'events-optimizer' ),
        ), 403 );
    }
    if ( !current_user_can( 'manage_options' ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Unauthorized', 'events-optimizer' ),
        ), 403 );
    }
    $search = '';
    if ( isset( $_REQUEST['term'] ) ) {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $search = sanitize_text_field( wp_unslash( $_REQUEST['term'] ) );
    } elseif ( isset( $_REQUEST['search'] ) ) {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $search = sanitize_text_field( wp_unslash( $_REQUEST['search'] ) );
    }
    $limit = ( isset( $_REQUEST['limit'] ) ? absint( $_REQUEST['limit'] ) : 200 );
    if ( $limit <= 0 ) {
        $limit = 200;
    } elseif ( $limit > 500 ) {
        $limit = 500;
    }
    $locations = teoai_read_dataforseo_locations_cache();
    if ( is_wp_error( $locations ) ) {
        wp_send_json_error( array(
            'message' => $locations->get_error_message(),
        ) );
    }
    $search_lower = strtolower( $search );
    $matches = array();
    foreach ( $locations as $location ) {
        if ( !isset( $location['location_code'] ) ) {
            continue;
        }
        $label = teoai_format_dataforseo_location_label( $location );
        if ( '' === $search_lower || false !== strpos( strtolower( $label ), $search_lower ) ) {
            $matches[] = array(
                'code'  => $location['location_code'],
                'label' => $label,
            );
            if ( count( $matches ) >= $limit ) {
                break;
            }
        }
    }
    $meta = teoai_get_dataforseo_locations_meta();
    wp_send_json_success( array(
        'items' => $matches,
        'meta'  => $meta,
    ) );
}

// Update languages list (manual trigger via admin).
add_action( 'wp_ajax_teoai_update_dataforseo_languages', 'teoai_update_dataforseo_languages' );
function teoai_update_dataforseo_languages() {
    // Raise limits; response can still be sizeable on constrained hosts.
    if ( function_exists( 'wp_raise_memory_limit' ) ) {
        wp_raise_memory_limit( 'admin' );
    } elseif ( function_exists( 'ini_set' ) ) {
        @ini_set( 'memory_limit', '512M' );
        // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_ini_set
    }
    if ( function_exists( 'set_time_limit' ) ) {
        @set_time_limit( 120 );
        // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
    }
    if ( !check_ajax_referer( 'events-optimizer-nonce', '_ajax_nonce', false ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Invalid nonce', 'events-optimizer' ),
        ), 403 );
    }
    if ( !current_user_can( 'manage_options' ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Unauthorized', 'events-optimizer' ),
        ), 403 );
    }
    wp_send_json_error( array(
        'message' => esc_html__( 'This feature is available in the Pro version.', 'events-optimizer' ),
    ), 403 );
    $login = get_option( 'teoai_dataforseo_api_login', '' );
    $password = get_option( 'teoai_dataforseo_api_password', '' );
    if ( empty( $login ) || empty( $password ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Please add DataForSEO credentials first.', 'events-optimizer' ),
        ), 400 );
    }
    $download = teoai_download_dataforseo_languages( $login, $password );
    if ( is_wp_error( $download ) ) {
        wp_send_json_error( array(
            'message' => $download->get_error_message(),
        ), 500 );
    }
    // Save full response to uploads file.
    $cache_path = teoai_dataforseo_languages_cache_path();
    if ( is_wp_error( $cache_path ) ) {
        wp_send_json_error( array(
            'message' => $cache_path->get_error_message(),
        ), 500 );
    }
    if ( false === file_put_contents( $cache_path, $download['raw_body'] ) ) {
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
        wp_send_json_error( array(
            'message' => esc_html__( 'Could not write the languages cache file.', 'events-optimizer' ),
        ), 500 );
    }
    $meta = array(
        'last_updated' => current_time( 'timestamp' ),
        'count'        => ( is_array( $download['languages'] ) ? count( $download['languages'] ) : 0 ),
        'size'         => ( file_exists( $cache_path ) ? filesize( $cache_path ) : 0 ),
        'hash'         => md5( $download['raw_body'] ),
    );
    update_option( 'teoai_dataforseo_languages_meta', $meta );
    wp_send_json_success( array(
        'meta' => $meta,
    ) );
}

// Update Google Translation languages (manual trigger via admin).
add_action( 'wp_ajax_teoai_update_google_translation_languages', 'teoai_update_google_translation_languages' );
function teoai_update_google_translation_languages() {
    if ( !check_ajax_referer( 'events-optimizer-nonce', '_ajax_nonce', false ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Invalid nonce', 'events-optimizer' ),
        ), 403 );
    }
    if ( !current_user_can( 'manage_options' ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Unauthorized', 'events-optimizer' ),
        ), 403 );
    }
    wp_send_json_error( array(
        'message' => esc_html__( 'This feature is available in the Pro version.', 'events-optimizer' ),
    ), 403 );
    $api_key = get_option( 'teoai_google_places_api_key', '' );
    if ( empty( $api_key ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Please add a Google Cloud API key first.', 'events-optimizer' ),
        ), 400 );
    }
    $download = teoai_download_google_translation_languages( $api_key );
    if ( is_wp_error( $download ) ) {
        wp_send_json_error( array(
            'message' => $download->get_error_message(),
        ), 500 );
    }
    // Save full response to uploads file.
    $written = teoai_save_google_translation_languages_cache( $download['raw_body'] );
    if ( is_wp_error( $written ) ) {
        wp_send_json_error( array(
            'message' => $written->get_error_message(),
        ), 500 );
    }
    wp_send_json_success( array(
        'meta' => $written['meta'],
    ) );
}

//----------------------------------------------------------------------------------------
// Check if URL is valid and reachable
//----------------------------------------------------------------------------------------
function teoai_url_valid(  $url  ) {
    // Check URLs with Google Safe Browsing
    $google_safe_browsing = sanitize_text_field( get_option( 'teoai_google_safe_browsing', 'false' ) );
    $validate_url_https = sanitize_text_field( get_option( 'teoai_validate_url_https', 'false' ) );
    $validate_url_redirected_moved = sanitize_text_field( get_option( 'teoai_validate_url_redirected_moved', 'false' ) );
    // If URL is empty give back error
    if ( empty( $url ) ) {
        return array(
            'status'        => 'URL_EMPTY',
            'error_message' => esc_html__( 'URL is empty', 'events-optimizer' ),
        );
    }
    // Is URL syntax valid? Accept as ok, even when http:// or https:// or www is missing
    $url = filter_var( $url, FILTER_SANITIZE_URL );
    // Check on missing https / http and create array with possibly valid URLs
    if ( $validate_url_https === 'false' ) {
        $valid_urls = array($url, 'http://' . $url, 'https://' . $url);
    } else {
        $valid_urls = array($url, 'http://www' . $url, 'https://www' . $url);
    }
    // Check each URL if it is valid and reachable
    foreach ( $valid_urls as $valid_url ) {
        // Check if URL syntax is valid
        if ( filter_var( $valid_url, FILTER_VALIDATE_URL ) ) {
            // Get the headers of the URL
            unset($file_headers);
            $file_headers = @get_headers( $valid_url );
            // Check if URL is redirected or permanently moved
            if ( teoai_fs()->can_use_premium_code__premium_only() and $validate_url_redirected_moved === 'true' ) {
                if ( isset( $file_headers[0] ) ) {
                    if ( strpos( $file_headers[0], '301' ) > 0 ) {
                        return array(
                            'status'        => 'URL_MOVED_PERMANENTLY',
                            'error_message' => esc_html__( 'URL is moved permanently', 'events-optimizer' ),
                        );
                    } elseif ( strpos( $file_headers[0], '302' ) > 0 ) {
                        return array(
                            'status'        => 'URL_TEMPORARILY_REDIRECTED',
                            'error_message' => esc_html__( 'URL is temporarily redirected', 'events-optimizer' ),
                        );
                    }
                }
            }
            // Check if URL is reachable (status code <> 200)
            if ( isset( $file_headers[0] ) and (bool) preg_match( '/^HTTP\\/\\d\\.\\d\\s+2\\d{2}\\s+/', $file_headers[0] ) ) {
                // Activate only for Pro version
                if ( teoai_fs()->can_use_premium_code__premium_only() and $google_safe_browsing === 'true' ) {
                    // Check if URL is marked as suspicious by Google Safe Browsing
                    $return = teoai_url_safe( $valid_url );
                    if ( $return['status'] === 'OK' ) {
                        // URL is valid
                        return array(
                            'status'        => 'OK',
                            'error_message' => esc_html__( 'URL is valid', 'events-optimizer' ),
                        );
                    } else {
                        if ( isset( $return['error_message'] ) ) {
                            return array(
                                'status'        => $return['status'],
                                'error_message' => $return['error_message'],
                            );
                        }
                    }
                } else {
                    // URL is valid
                    return array(
                        'status'        => 'OK',
                        'error_message' => esc_html__( 'URL is valid', 'events-optimizer' ),
                    );
                }
            } else {
                return array(
                    'status'        => 'URL_NOT_REACHABLE',
                    'error_message' => esc_html__( 'URL is not reachable', 'events-optimizer' ),
                );
            }
        } else {
            return array(
                'status'        => 'INVALID_URL_SYNTAX',
                'error_message' => esc_html__( 'URL syntax is not valid', 'events-optimizer' ),
            );
        }
    }
    // end foreach
}

//----------------------------------------------------------------------------------------
// Check if mail address is valid
//----------------------------------------------------------------------------------------
function teoai_mail_valid(  $mail = true  ) {
    // Check if mail is empty
    if ( empty( $mail ) ) {
        return esc_html__( 'Mail is empty!', 'events-optimizer' );
    }
    // Check if mail syntax is valid
    if ( !filter_var( $mail, FILTER_VALIDATE_EMAIL ) ) {
        return esc_html__( 'Mail is not valid', 'events-optimizer' );
    }
    // Check if domain exists and is accepting emails
    /* Is not working reliable
    		list( , $domain) = explode('@', $email);
    		if (! checkdnsrr( $domain, 'MX' ) ) {
    			return esc_html__( 'Domain does not exist or accepting mails.', 'events-optimizer' );
    		}
    		*/
}

//----------------------------------------------------------------------------------------
// Check if phone number is valid
// https://uibakery.io/regex-library/phone-number-php
//----------------------------------------------------------------------------------------
function teoai_phone_number_valid(  $number = true  ) {
    // Check if phone number is empty
    if ( empty( $number ) ) {
        return esc_html__( 'Phone number is empty', 'events-optimizer' );
    }
    // Define the regular expression pattern to match a valid international phone number format
    $pattern = '/^\\+?\\d{1,4}?[-.\\s]?\\(?\\d{1,3}?\\)?[-.\\s]?\\d{1,4}[-.\\s]?\\d{1,4}[-.\\s]?\\d{1,9}$/';
    // Check if the given phone number matches the pattern
    if ( preg_match( $pattern, $number ) != 1 ) {
        return esc_html__( 'Phone number is not valid', 'events-optimizer' );
    }
}

//----------------------------------------------------------------------------------------
// Create clean URL for SEO (e.g. to create a SEO optimized event image file name)
// https://stackoverflow.com/questions/4783802/converting-string-into-web-safe-uri
//----------------------------------------------------------------------------------------
function teoai_get_clean_url(  $str, $replace = array(), $delimiter = '-'  ) {
    if ( !is_string( $str ) ) {
        return '';
    }
    setlocale( LC_ALL, 'en_US.UTF8' );
    if ( !empty( $replace ) ) {
        $str = str_replace( (array) $replace, ' ', $str );
    }
    $clean = preg_replace( array(
        '/Ä/',
        '/Ö/',
        '/Ü/',
        '/ä/',
        '/ö/',
        '/ü/'
    ), array(
        'Ae',
        'Oe',
        'Ue',
        'ae',
        'oe',
        'ue'
    ), $str );
    $clean = iconv( 'UTF-8', 'ASCII//TRANSLIT', $clean );
    $clean = preg_replace( "/[^a-zA-Z0-9\\/_|+ -]/", '', $clean );
    $clean = strtolower( trim( $clean, '-' ) );
    $clean = preg_replace( "/[\\/_|+ -]+/", $delimiter, $clean );
    return $clean;
}

//----------------------------------------------------------------------------------------
// Count elements in array with specific key
// https://stackoverflow.com/questions/11558397/count-specific-values-in-multidimensional-array/11558780
//----------------------------------------------------------------------------------------
function teoai_array_count_key(  $array, $find  ) {
    $i = 0;
    foreach ( $array as $key => $value ) {
        if ( isset( $value['type'] ) && $value['type'] === $find ) {
            $i++;
        }
    }
    return $i;
}

//----------------------------------------------------------------------------------------
// Santize multi dimensional array
//----------------------------------------------------------------------------------------
function teoai_sanitize_multi_dimensional_array(  $array  ) {
    foreach ( $array as $key => &$value ) {
        if ( is_array( $value ) ) {
            $value = teoai_sanitize_multi_dimensional_array( $value );
        } else {
            // Assumes that the data is text. Adjust the sanitizing function if not.
            $value = sanitize_text_field( $value );
        }
    }
    return $array;
}

// Fetch languages for dropdown (AJAX).
add_action( 'wp_ajax_teoai_get_dataforseo_languages', 'teoai_get_dataforseo_languages' );
function teoai_get_dataforseo_languages() {
    if ( !check_ajax_referer( 'events-optimizer-nonce', '_ajax_nonce', false ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Invalid nonce', 'events-optimizer' ),
        ), 403 );
    }
    if ( !current_user_can( 'manage_options' ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Unauthorized', 'events-optimizer' ),
        ), 403 );
    }
    $languages = teoai_read_dataforseo_languages_cache();
    if ( is_wp_error( $languages ) ) {
        wp_send_json_error( array(
            'message' => $languages->get_error_message(),
        ) );
    }
    wp_send_json_success( array(
        'items' => $languages,
    ) );
}

// Fetch locations for dropdown (AJAX).
add_action( 'wp_ajax_teoai_get_dataforseo_locations', 'teoai_get_dataforseo_locations' );
function teoai_get_dataforseo_locations() {
    if ( !check_ajax_referer( 'events-optimizer-nonce', '_ajax_nonce', false ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Invalid nonce', 'events-optimizer' ),
        ), 403 );
    }
    if ( !current_user_can( 'manage_options' ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Unauthorized', 'events-optimizer' ),
        ), 403 );
    }
    $locations = teoai_read_dataforseo_locations_cache();
    if ( is_wp_error( $locations ) ) {
        wp_send_json_error( array(
            'message' => $locations->get_error_message(),
        ) );
    }
    $items = array_map( function ( $item ) {
        return array(
            'code'  => ( isset( $item['location_code'] ) ? $item['location_code'] : '' ),
            'label' => teoai_format_dataforseo_location_label( $item ),
        );
    }, $locations );
    wp_send_json_success( array(
        'items' => $items,
    ) );
}

// Fetch Google Translation languages for Google Places (AJAX).
add_action( 'wp_ajax_teoai_get_google_translation_languages', 'teoai_get_google_translation_languages' );
function teoai_get_google_translation_languages() {
    if ( !check_ajax_referer( 'events-optimizer-nonce', '_ajax_nonce', false ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Invalid nonce', 'events-optimizer' ),
        ), 403 );
    }
    if ( !current_user_can( 'manage_options' ) ) {
        wp_send_json_error( array(
            'message' => esc_html__( 'Unauthorized', 'events-optimizer' ),
        ), 403 );
    }
    $languages = teoai_read_google_translation_languages_cache();
    if ( is_wp_error( $languages ) ) {
        wp_send_json_error( array(
            'message' => $languages->get_error_message(),
        ) );
    }
    $items = array_map( function ( $item ) {
        return array(
            'code'  => ( isset( $item['language_code'] ) ? $item['language_code'] : '' ),
            'label' => ( isset( $item['language_name'] ) ? $item['language_name'] : (( isset( $item['language_code'] ) ? $item['language_code'] : '' )) ),
        );
    }, $languages );
    wp_send_json_success( array(
        'items' => $items,
    ) );
}
