<?php
// phpcs:disable WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL,PluginCheck.Security.DirectDB.UnescapedDBParameter,WordPress.NamingConventions.PrefixAllGlobals,WordPress.Security.NonceVerification.Recommended -- Uses plugin-owned tables, public legacy hooks, and read-only admin routing parameters.

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * The admin-specific functionality of the plugin.
 *
 * @link       https://example.com
 * @since      1.0.0
 *
 * @package    Instant_Popup_Builder
 * @subpackage Instant_Popup_Builder/admin
 */

/**
 * The admin-specific functionality of the plugin.
 *
 * Defines the plugin name, version, and two examples hooks for how to
 * enqueue the admin-specific stylesheet and JavaScript.
 *
 * @package    Instant_Popup_Builder
 * @subpackage Instant_Popup_Builder/admin
 * @author     7th Sky Software's <example@gmail.com>
 */
class Instant_Popup_Builder_Admin
{

	/**
	 * The ID of this plugin.
	 *
	 * @since    1.0.0
	 * @access   private
	 * @var      string    $plugin_name    The ID of this plugin.
	 */
	private $plugin_name = "Instant Popup Builder";

	/**
	 * The version of this plugin.
	 *
	 * @since    1.0.0
	 * @access   private
	 * @var      string    $version    The current version of this plugin.
	 */

	private $fontawesom = 'fontawesome';
	/**
	 * Undocumented variable
	 *
	 * @since 1.0.0
	 * @access private
	 * @var string
	 */
	private $modal = 'css-modal';
	/**
	 * Undocumented variable
	 *
	 * @since 1.0.0
	 * @access private
	 * @var string
	 */

	private $version = '2.0.1.12';

	/**
	 * Initialize the class and set its properties.
	 *
	 * @since    1.0.0
	 * @param      string    $plugin_name       The name of this plugin.
	 * @param      string    $version    The version of this plugin.
	 */
	public function __construct()
	{
		if (defined('INSTANT_POPUP_BUILDER_VERSION')) {
			$this->version = INSTANT_POPUP_BUILDER_VERSION;
		}

		// $this->plugin_name = $plugin_name;
		// $this->version = $version;
		add_action('admin_menu', [$this, 'ipb_admin_menu_init']);
		add_action('init', [$this, 'ipb_setting_actions']);
		add_action('wp_ajax_ipb_file_upload', [$this, 'ipb_image_file_upload']);
		add_action('wp_ajax_ipb_file_sound_upload', [$this, 'ipb_file_sound_upload']);
		add_action('wp_ajax_ipb_bulk_action', [$this, 'ipb_bulk_action']);
		add_action('wp_ajax_ipb_display_ajax', [$this, 'ipb_display_ajax']);
		add_action('wp_ajax_ipb_popup_status_ajax', [$this, 'ipb_popup_status_ajax']);
		add_action('wp_ajax_ipb_popup_duplicate', [$this, 'ipb_popup_duplicate']);
		add_action('wp_ajax_ipb_calculate_db_size', [$this, 'ipb_calculate_db_size']);
		// Re-run activation tasks (repair/initialize)
		add_action('wp_ajax_ipb_rerun_activation', [$this, 'ipb_rerun_activation']);
		add_action('wp_ajax_ipb_factory_reset', [$this, 'ipb_factory_reset']);
		// add_action('init', [$this, 'ipb_check_popup_submt_request']);
		add_action('add_meta_boxes', [$this, 'post_meta_box']);
		add_action('admin_notices', [$this, 'ipb_admin_notice']);
		add_action('admin_init', [$this, 'ipb_handle_notice_action']);
		add_action('admin_init', [$this, 'ipb_handle_subscriber_export']);
		add_filter('admin_body_class', [$this, 'ipb_admin_body_class']);

		// Toast after extension popups redirect back to the editor (see ipb_redirect_after_extension_popup_update).
		add_action('admin_footer', [$this, 'ipb_render_extension_update_toast']);

		// Hide WordPress admin footer on plugin pages
		add_action('admin_init', [$this, 'ipb_hide_admin_footer']);

		// Add screen options support for All Popups page
		add_action('current_screen', [$this, 'ipb_add_screen_options']);

		// Subscription settings AJAX handler
		add_action('wp_ajax_save_subscription_settings', [$this, 'save_subscription_settings']);

		// Add AJAX handlers for modal subscriber functionality
		add_action('wp_ajax_ipb_add_subscriber', [$this, 'ipb_add_subscriber_ajax']);
		add_action('wp_ajax_ipb_edit_subscriber', [$this, 'ipb_edit_subscriber_ajax']);
	}

	/**
	 * Read a scalar admin query parameter without using it for a state change.
	 *
	 * @param string $key Query parameter name.
	 * @return string
	 */
	private function ipb_get_admin_query_param($key)
	{
		$value = filter_input(INPUT_GET, $key, FILTER_UNSAFE_RAW);

		return is_string($value) ? sanitize_text_field($value) : '';
	}

	/**
	 * Decode values that arrive as literal application/x-www-form-urlencoded text.
	 *
	 * Some admin save paths submit serialized form data through extension JavaScript.
	 * If that payload is forwarded without PHP's normal request parsing, spaces can
	 * be stored as plus signs.
	 *
	 * @param mixed $value Submitted value.
	 * @return mixed
	 */
	private function ipb_decode_form_encoded_value($value)
	{
		if (!is_string($value)) {
			return $value;
		}

		if (preg_match('/%[0-9A-Fa-f]{2}/', $value) || (false !== strpos($value, '+') && false === strpos($value, ' '))) {
			return urldecode($value);
		}

		return $value;
	}

	/**
	 * Read a subscription message from the current admin request.
	 *
	 * @param string $primary_key Current settings field name.
	 * @param string $legacy_key  Legacy AJAX field name.
	 * @param string $default     Default message.
	 * @return string
	 */
	private function ipb_get_posted_subscription_message($primary_key, $legacy_key, $default = '')
	{
		if (isset($_POST[$primary_key])) {
			$value = wp_unslash($_POST[$primary_key]);
		} elseif (isset($_POST[$legacy_key])) {
			$value = wp_unslash($_POST[$legacy_key]);
		} else {
			$value = $default;
		}

		return sanitize_textarea_field($this->ipb_decode_form_encoded_value($value));
	}

	/**
	 * Read a scalar subscription setting from the current admin request.
	 *
	 * @param string $key       Field name.
	 * @param string $default   Default value.
	 * @param string $sanitizer Sanitizer callback.
	 * @return string
	 */
	private function ipb_get_posted_subscription_setting($key, $default = '', $sanitizer = 'sanitize_text_field')
	{
		if (!isset($_POST[$key])) {
			return $default;
		}

		$value = $this->ipb_decode_form_encoded_value(wp_unslash($_POST[$key]));

		return is_callable($sanitizer) ? call_user_func($sanitizer, $value) : sanitize_text_field($value);
	}

	/**
	 * Register the stylesheets for the admin area.
	 *
	 * @since    1.0.0
	 */
	public function enqueue_styles()
	{
		// Keep plugin styles isolated from unrelated WordPress admin screens.
		// Several bundled styles intentionally target generic admin selectors
		// such as .notice, .nav-tab and .form-table.
		if (!$this->is_plugin_page()) {
			return;
		}

		// phpcs:disable WordPress.Security.NonceVerification.Recommended -- values only select assets for the current admin screen.
		$current_page = $this->ipb_get_admin_query_param('page');
		$current_tab = $this->ipb_get_admin_query_param('tab');
		$edit_id = $this->ipb_get_admin_query_param('edit_id');
		$is_popup_editor = ('add-new-instant-popup' === $current_page) || '' !== $edit_id;
		$is_subscriber_screen = in_array($current_page, array('instant-subscriber-list', 'instant-subscriber-add-new'), true)
			|| false !== strpos($current_page, 'subscribers');
		$needs_select2 = $is_popup_editor || ('instant-popup-configuration' === $current_page && 'autoresponder' === $current_tab);
		$needs_modal = $is_popup_editor || $is_subscriber_screen || 'instant-popup-builder' === $current_page;
		// phpcs:enable WordPress.Security.NonceVerification.Recommended

		wp_register_style('select2-css', plugin_dir_url(__FILE__) . 'css/select2.css', array(), $this->version, 'all');
		wp_register_style($this->fontawesom, plugin_dir_url(__FILE__) . 'css/fontawesome.css', array(), $this->version, 'all');
		wp_register_style($this->modal, plugin_dir_url(__FILE__) . 'css/modal.css', array(), $this->version, 'all');
		wp_register_style('css-setting', plugin_dir_url(__FILE__) . 'css/settings.css', array(), $this->version, 'all');

		// Always load base CSS files
		wp_register_style('ipb-admin-base', plugin_dir_url(__FILE__) . 'css/base.css', array(), $this->version, 'all');
		wp_register_style('ipb-admin-notices', plugin_dir_url(__FILE__) . 'css/notices.css', array(), $this->version, 'all');
		wp_register_style($this->plugin_name, plugin_dir_url(__FILE__) . 'css/instant-popup-builder-admin.css', array('ipb-admin-base', 'ipb-admin-notices'), $this->version, 'all');

		// Enqueue base styles
		if ($needs_select2) {
			wp_enqueue_style('select2-css');
		}
		wp_enqueue_style($this->fontawesom);
		if ($needs_modal) {
			wp_enqueue_style($this->modal);
		}
		wp_enqueue_style('ipb-admin-base');
		wp_enqueue_style('ipb-admin-notices');
		wp_enqueue_style($this->plugin_name);
		wp_enqueue_style('css-setting');

		// Conditionally enqueue analytics tab CSS
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter used for tab detection only, value is sanitized
		// Conditionally enqueue dashboard CSS (main popup list page)
		if ('instant-popup-builder' === $current_page) {
			wp_register_style('ipb-admin-dashboard', plugin_dir_url(__FILE__) . 'css/dashboard.css', array($this->plugin_name), $this->version, 'all');
			wp_enqueue_style('ipb-admin-dashboard');
		}

		// Conditionally enqueue Add New Popup page CSS
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET edit_id only distinguishes add-new vs edit screen for CSS; no privileged action.
		if ('add-new-instant-popup' === $current_page && '' === $edit_id) {
			wp_register_style('ipb-admin-add-new', plugin_dir_url(__FILE__) . 'css/add-new-popup.css', array($this->plugin_name), $this->version, 'all');
			wp_enqueue_style('ipb-admin-add-new');
		}

		if ('analytics' === $current_tab && 'instant-popup-configuration' === $current_page) {
			wp_register_style('analytics-tab-css', plugin_dir_url(__FILE__) . 'css/analytics-tab.css', array(), $this->version, 'all');
			wp_enqueue_style('analytics-tab-css');
		}

		// Conditionally enqueue settings page CSS (load after main admin CSS so layout wins)
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter used for page detection only, value is sanitized
		if ('setting-instant-popup' === $current_page) {
			wp_register_style('settings-page-css', plugin_dir_url(__FILE__) . 'css/settings-page.css', array($this->plugin_name), $this->version, 'all');
			wp_enqueue_style('settings-page-css');
		}

		// Conditionally enqueue support page CSS
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter used for page detection only, value is sanitized
		if ('support-instant-popup' === $current_page) {
			wp_register_style('support-page-css', plugin_dir_url(__FILE__) . 'css/support-page.css', array(), $this->version, 'all');
			wp_enqueue_style('support-page-css');
		}

		// Conditionally enqueue upgrade page CSS
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter used for page detection only, value is sanitized
		if ('upgrade-instant-popup' === $current_page) {
			wp_register_style('upgrade-page-css', plugin_dir_url(__FILE__) . 'css/upgrade-page.css', array(), $this->version, 'all');
			wp_enqueue_style('upgrade-page-css');
		}

		// Conditionally enqueue license page CSS
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter used for page detection only, value is sanitized
		if ('license-instant-popup' === $current_page) {
			wp_register_style('license-page-css', plugin_dir_url(__FILE__) . 'css/license.css', array(), $this->version, 'all');
			wp_enqueue_style('license-page-css');
		}

	// Conditionally enqueue subscribers page CSS
	// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter used for page detection only, value is sanitized
	$safe_page_param = $current_page;
	if (
		in_array($safe_page_param, array('instant-subscriber-list', 'instant-subscriber-add-new'), true)
		|| false !== strpos($safe_page_param, 'subscribers')
	) {
		wp_register_style('subscribers-css', plugin_dir_url(__FILE__) . 'css/subscribers.css', array(), $this->version, 'all');
		wp_enqueue_style('subscribers-css');
		wp_register_style('settings-modal-css', plugin_dir_url(__FILE__) . 'css/settings-modal.css', array('subscribers-css'), $this->version, 'all');
		wp_enqueue_style('settings-modal-css');
	}

	// Conditionally enqueue forms CSS
	// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter used for page detection only, value is sanitized
	if (strpos($safe_page_param, 'form') !== false) {
		wp_register_style('forms-css', plugin_dir_url(__FILE__) . 'css/forms.css', array(), $this->version, 'all');
		wp_enqueue_style('forms-css');
	}

		// Conditionally enqueue settings CSS files when on popup editor pages
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET page/edit_id only detect editor screen for CSS; no privileged action.
		if ($is_popup_editor) {
			// Enqueue editor base styles
			wp_register_style('ipb-admin-settings-tabs', plugin_dir_url(__FILE__) . 'css/settings-tabs.css', array($this->plugin_name), $this->version, 'all');
			wp_register_style('ipb-admin-design-tab', plugin_dir_url(__FILE__) . 'css/design-tab.css', array($this->plugin_name), $this->version, 'all');
			wp_register_style('ipb-admin-advance-tab', plugin_dir_url(__FILE__) . 'css/advance-tab.css', array($this->plugin_name), $this->version, 'all');

			wp_enqueue_style('ipb-admin-settings-tabs');
			wp_enqueue_style('ipb-admin-design-tab');
			wp_enqueue_style('ipb-admin-advance-tab');

			// Enqueue popup type-specific CSS
			// Note: Video popup CSS is handled by the video extension plugin itself
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter used for type detection only, value is sanitized
			$popup_type = $this->ipb_get_admin_query_param('type');
			if ('subscription' === $popup_type) {
				wp_register_style('ipb-admin-subscription-popup', plugin_dir_url(__FILE__) . 'css/subscription-popup.css', array($this->plugin_name), $this->version, 'all');
				wp_enqueue_style('ipb-admin-subscription-popup');
				// Template selection modal CSS for subscription popup
				wp_register_style('modals-css', plugin_dir_url(__FILE__) . 'css/modals.css', array(), $this->version, 'all');
				wp_enqueue_style('modals-css');
			}

			// Enqueue all settings CSS files since they're loaded dynamically
			wp_register_style('setting-text-styling-css', plugin_dir_url(__FILE__) . 'css/setting-text-styling.css', array(), $this->version, 'all');
			wp_register_style('setting-targeting-css', plugin_dir_url(__FILE__) . 'css/setting-targeting.css', array(), $this->version, 'all');
			wp_register_style('setting-location-css', plugin_dir_url(__FILE__) . 'css/setting-location.css', array(), $this->version, 'all');
			wp_register_style('setting-device-css', plugin_dir_url(__FILE__) . 'css/setting-device.css', array(), $this->version, 'all');
			wp_register_style('setting-scheduling-css', plugin_dir_url(__FILE__) . 'css/setting-scheduling.css', array(), $this->version, 'all');
			wp_register_style('setting-position-css', plugin_dir_url(__FILE__) . 'css/setting-position.css', array(), $this->version, 'all');
			wp_register_style('setting-frequency-css', plugin_dir_url(__FILE__) . 'css/setting-frequency.css', array(), $this->version, 'all');
			wp_register_style('setting-background-css', plugin_dir_url(__FILE__) . 'css/setting-background.css', array(), $this->version, 'all');
			wp_register_style('setting-size-css', plugin_dir_url(__FILE__) . 'css/setting-size.css', array(), $this->version, 'all');
			wp_register_style('setting-advanced-css', plugin_dir_url(__FILE__) . 'css/setting-advanced.css', array(), $this->version, 'all');
			wp_register_style('setting-animation-css', plugin_dir_url(__FILE__) . 'css/setting-animation.css', array(), $this->version, 'all');
			wp_register_style('setting-display-css', plugin_dir_url(__FILE__) . 'css/setting-display.css', array(), $this->version, 'all');
			wp_register_style('setting-zindex-css', plugin_dir_url(__FILE__) . 'css/setting-zindex.css', array(), $this->version, 'all');
			wp_register_style('setting-sound-css', plugin_dir_url(__FILE__) . 'css/setting-sound.css', array(), $this->version, 'all');
			wp_register_style('setting-trigger-css', plugin_dir_url(__FILE__) . 'css/setting-trigger.css', array(), $this->version, 'all');
			wp_register_style('setting-closing-css', plugin_dir_url(__FILE__) . 'css/setting-closing.css', array(), $this->version, 'all');

			wp_enqueue_style('setting-text-styling-css');
			wp_enqueue_style('setting-targeting-css');
			wp_enqueue_style('setting-location-css');
			wp_enqueue_style('setting-device-css');
			wp_enqueue_style('setting-scheduling-css');
			wp_enqueue_style('setting-position-css');
			wp_enqueue_style('setting-frequency-css');
			wp_enqueue_style('setting-background-css');
			wp_enqueue_style('setting-size-css');
			wp_enqueue_style('setting-advanced-css');
			wp_enqueue_style('setting-animation-css');
			wp_enqueue_style('setting-display-css');
			wp_enqueue_style('setting-zindex-css');
			wp_enqueue_style('setting-sound-css');
			wp_enqueue_style('setting-trigger-css');
			wp_enqueue_style('setting-closing-css');
		}
		// Add custom admin CSS for upgrade menu highlighting
		$custom_css = "
			.ipb-upgrade-menu {
				color: #f39c12 !important;
				font-weight: 600 !important;
			}

			.ipb-upgrade-menu:hover {
				color: #e67e22 !important;
			}

			.ipb-rate-us {
				color: #e74c3c !important;
				font-weight: 600 !important;
			}

			.ipb-rate-us:hover {
				color: #c0392b !important;
			}
		";
		wp_add_inline_style($this->plugin_name, $custom_css);
	}

	/**
	 * Register the JavaScript for the admin area.
	 *
	 * @since    1.0.0
	 */
	public function enqueue_scripts()
	{
		// Do not load editors, modal libraries, Select2, Chart.js, or plugin
		// behavior on unrelated WordPress admin screens.
		if (!$this->is_plugin_page()) {
			return;
		}

		// phpcs:disable WordPress.Security.NonceVerification.Recommended -- values only select assets for the current admin screen.
		$current_page = $this->ipb_get_admin_query_param('page');
		$current_tab = $this->ipb_get_admin_query_param('tab');
		$edit_id = $this->ipb_get_admin_query_param('edit_id');
		$is_popup_editor_screen = ('add-new-instant-popup' === $current_page)
			|| '' !== $edit_id;
		$is_subscriber_screen = in_array($current_page, array('instant-subscriber-list', 'instant-subscriber-add-new'), true)
			|| false !== strpos($current_page, 'subscribers');
		$needs_select2 = $is_popup_editor_screen || ('instant-popup-configuration' === $current_page && 'autoresponder' === $current_tab);
		$needs_modal = $is_popup_editor_screen || $is_subscriber_screen || 'instant-popup-builder' === $current_page;
		$needs_chart = 'instant-popup-builder' === $current_page
			|| ('instant-popup-configuration' === $current_page && 'analytics' === $current_tab);
		$needs_ace = $is_popup_editor_screen;
		// phpcs:enable WordPress.Security.NonceVerification.Recommended

		wp_register_script('select2-js', plugin_dir_url(__FILE__) . 'js/select2.js', array('jquery'), $this->version, true);
		wp_register_script('jquery-modal', plugin_dir_url(__FILE__) . 'js/modal.js', array('jquery'), $this->version, true);
		wp_register_script('chart-js', plugin_dir_url(__FILE__) . 'js/chart.js', array('jquery'), $this->version, true);
		wp_register_script('ace-js', plugin_dir_url(__FILE__) . 'js/ace-builds/ace.js', array('jquery'), $this->version, true);//ace editor

		if ($needs_select2) {
			wp_enqueue_script('select2-js');
		}
		if ($needs_modal) {
			wp_enqueue_script('jquery-modal');
		}
		if ($needs_chart) {
			wp_enqueue_script('chart-js');
		}
		if ($needs_ace) {
			wp_enqueue_script('ace-js');
		}

		// Enqueue WordPress Media Library on popup editor screens (image popup, Design tab background, etc.)
		if ($is_popup_editor_screen) {
			wp_enqueue_media();
		}

		$ipb_admin_script_deps = array('jquery');
		if ($needs_select2) {
			$ipb_admin_script_deps[] = 'select2-js';
		}
		if ($needs_modal) {
			$ipb_admin_script_deps[] = 'jquery-modal';
		}
		if ($needs_chart) {
			$ipb_admin_script_deps[] = 'chart-js';
		}
		if ($needs_ace) {
			$ipb_admin_script_deps[] = 'ace-js';
		}
		if ($is_popup_editor_screen) {
			$ipb_admin_script_deps[] = 'media-upload';
		}
		wp_register_script($this->plugin_name, plugin_dir_url(__FILE__) . 'js/instant-popup-builder-admin.js', $ipb_admin_script_deps, $this->version, true);
		wp_enqueue_script($this->plugin_name);

		// Initialize update-success toasts (HTML is safe, script must not be in message or it flashes as text)
		$ipb_init_update_toast = "jQuery(document).ready(function($){ function ipbInitUpdateToast(t){ t.fadeIn(200); setTimeout(function(){ t.fadeOut(200); }, 2500); t.find('.ipb-popup-update-toast-close').on('click', function(){ t.fadeOut(150); }); } $('.update_messsage .ipb-popup-update-toast').each(function(){ ipbInitUpdateToast($(this)); }); var ipbExt=$( '#ipb-ipb-updated-toast' ); if(ipbExt.length){ ipbInitUpdateToast(ipbExt); } });";
		wp_add_inline_script($this->plugin_name, $ipb_init_update_toast, 'after');

		if ($is_popup_editor_screen || 'instant-popup-builder' === $current_page) {
			wp_register_script('enhanced-preview', plugin_dir_url(__FILE__) . 'js/enhanced-preview.js', array('jquery', 'jquery-modal'), $this->version, true);
			wp_enqueue_script('enhanced-preview');
		}

		if ($is_popup_editor_screen) {
			wp_register_script('popup-settings-enhancement', plugin_dir_url(__FILE__) . 'js/popup-settings-enhancement.js', array('jquery'), $this->version, true);
			wp_enqueue_script('popup-settings-enhancement');
		}

		// Enqueue scripts

		// Localize script for AJAX
		wp_localize_script($this->plugin_name, 'instnat_ajax_handler', [
			'ajaxurl' => admin_url('admin-ajax.php'),
			'file_nonce' => wp_create_nonce('upload_file_action'),
			'display_nonce' => wp_create_nonce('display_ajax_action'),
			'woo_nonce' => wp_create_nonce('woo_ajax_action'),
			'woo_add_to_cart' => wp_create_nonce('woo_addtocart_action'),
			'ipb_admin_nonce' => wp_create_nonce('ipb_admin_nonce'),
			'display_setting' => $this->ipb_display_option(),
			'chart_titles' => $this->ipb_chart_titles()
		]);

		// Localize enhanced preview script
		if (wp_script_is('enhanced-preview', 'enqueued')) {
			wp_localize_script('enhanced-preview', 'instant_popup_admin', [
				'ajaxurl' => admin_url('admin-ajax.php'),
				'plugin_url' => plugin_dir_url(__FILE__),
				'enhanced_preview_nonce' => wp_create_nonce('enhanced_preview_nonce')
			]);
		}
		// Also set the global ajaxurl for backward compatibility
		wp_localize_script($this->plugin_name, 'ipb_ajax_vars', [
			'ajaxurl' => admin_url('admin-ajax.php'),
			'nonce' => wp_create_nonce('ipb_subscriber_action'),
		]);
	}

	/**
	 * Register Custom admin menu option
	 *
	 * @since    1.0.0
	 */
	public function ipb_admin_menu_init()
	{
		// Check extension activation status
		$is_active = class_exists('Class_instant_popup_builder_manager') ? Class_instant_popup_builder_manager::get_active_popup() : [];
		$licenses = class_exists('Class_instant_popup_builder_license') ? Class_instant_popup_builder_license::getLicense() : [];

		// Check if subscription extension is active
		$subscription_active = in_array('subscription', $is_active);

		// Check if any licensed extensions are available
		$has_licensed_extensions = count($licenses) > 0;

		add_menu_page('Instant Popups', 'Instant Popups', 'manage_options', 'instant-popup-builder', [$this, 'ipb_all_popup_callback'],  plugins_url('/image/icon.png', __FILE__), 40);

		// Add Dashboard as the first submenu item
		add_submenu_page(
			'instant-popup-builder', // Parent slug
			'Dashboard', // Page title
			'Dashboard', // Menu title
			'manage_options', // Capability required to access the page
			'instant-popup-builder', // Menu slug (same as parent to override default)
			[$this, 'ipb_all_popup_callback']
		);

		add_submenu_page(

			'instant-popup-builder', // Parent slug
			'Add New', // Page title
			'Add New', // Menu title
			'manage_options', // Capability required to access the page
			'add-new-instant-popup', // Menu slug
			[$this, 'ipb_add_new_popup_callback']
		);

		add_submenu_page(

			'instant-popup-builder', // Parent slug
			'Analytics', // Page title
			'Analytics', // Menu title
			'manage_options', // Capability required to access the page
			'analytics-instant-popup', // Menu slug
			[$this, 'ipb_analytics_popup_callback']
		);
		$active_license = get_option('subscription_license_active');
		$ipd_active_plugin = get_option('instant_popup_subscription_activated');
       if($active_license != 'yes' || $ipd_active_plugin == 'no'){
       add_submenu_page(

				'instant-popup-builder', // Parent slug
				'Subscriber', // Page title
				'Subscriber', // Menu title
				'manage_options', // Capability required to access the page
				'instant-subscriber-list', // Menu slug
				[$this, 'instant_subsriber_callback']
			);
		// Add Configuration menu
			add_submenu_page(
				'instant-popup-builder', // Parent slug
				'Configuration', // Page title
				'Configuration', // Menu title
				'manage_options', // Capability required to access the page
				'instant-popup-configuration', // Menu slug
				[$this, 'instant_popup_configuration_callback']
			);
		}
		// Add License submenu item - Only show if licensed extensions are available
		if ($has_licensed_extensions) {
			add_submenu_page(

				'instant-popup-builder',
				'License', // Page title
				'License', // Menu title
				'manage_options', // Capability required to access the page
				'license-instant-popup', // Menu slug
				[$this, 'ipb_license_popup_callback']
			);
		}

		add_submenu_page(
			'instant-popup-builder',
			'Integration',
			'Integration',
			'manage_options',
			'instant-popup-integration',
			[$this, 'ipb_integration_popup_callback']
		);

		add_submenu_page(

			'instant-popup-builder', // Parent slug
			'Settings', // Page title
			'Settings', // Menu title
			'manage_options', // Capability required to access the page
			'setting-instant-popup', // Menu slug
			[$this, 'ipb_setting_popup_callback']
		);

		add_submenu_page(

			'instant-popup-builder', // Parent slug
			'Support', // Page title
			'Support', // Menu title
			'manage_options', // Capability required to access the page
			'support-instant-popup', // Menu slug
			[$this, 'ipb_support_popup_callback']
		);
		// NOTE: Support menu should always be second to last (before Upgrade)
		// The Upgrade menu should always be the LAST item in the submenu
		add_submenu_page(

			'instant-popup-builder', // Parent slug
			'Upgrade', // Page title
			'<span class="ipb-upgrade-menu">Upgrade</span>', // Menu title with highlighting
			'manage_options', // Capability required to access the page
			'upgrade-instant-popup', // Menu slug
			[$this, 'ipb_upgrade_popup_callback']
		);
		add_action('admin_menu', array($this,'push_selected_submenus_to_bottom'), 999);
	}
    /**
	 * Rearange meuu
	 *
	 * @since    1.0.0
	 * @return string
	 */
	public function push_selected_submenus_to_bottom() {
	    global $submenu;

	    $main_menu_slug  = 'instant-popup-builder';
	    $main_submenu_slugs  = [
			'license-instant-popup',
			'analytics-instant-popup',
	        'setting-instant-popup',
	        'support-instant-popup',
	        'upgrade-instant-popup',
	    ];

	    if (!isset($submenu[$main_menu_slug])) {
	        return;
	    }

	    $all_items = $submenu[$main_menu_slug];
	    $main_items = [];
	    $other_items = [];

	    foreach ($all_items as $item) {
	        if (in_array($item[2], $main_submenu_slugs)) {
	            $main_items[$item[2]] = $item;
	        } else {
	            $other_items[] = $item;
	        }
	    }


	    foreach ($main_submenu_slugs as $slug) {
	        if (isset($main_items[$slug])) {
	            $other_items[] = $main_items[$slug];
	        }
	    }

	    $submenu[$main_menu_slug] = $other_items;
	}

	/**
	 * Return Content for All Popups menu
	 *
	 * @since    1.0.0
	 * @return string
	 */
	public function ipb_all_popup_callback()
	{

		return   require_once plugin_dir_path(__FILE__) . 'partials/ipb-all-popup.php';
	}
     public  function instant_subsriber_callback()
	{

		include_once plugin_dir_path(__FILE__) . '/partials/instant-popup-subscriber-list.php';
	}
	public function instant_popup_configuration_callback()
	{
		include_once plugin_dir_path(__FILE__) . '/partials/instant-popup-configuration.php';
	}

	/**
	 * Display the core integration upsell, or let a licensed Pro extension
	 * render its full integration controls on the same page.
	 *
	 * @return void
	 */
	public function ipb_integration_popup_callback()
	{
		if (has_action('ipb_render_pro_integration_page')) {
			do_action('ipb_render_pro_integration_page');
			return;
		}

		require_once plugin_dir_path(__FILE__) . 'partials/ipb-integration-popup.php';
	}
	/**
	 * Return Content for All Popups menu
	 *
	 * @since    1.0.0
	 * @return string
	 */
	public function ipb_add_new_popup_callback()
	{

		return   require_once plugin_dir_path(__FILE__) . 'partials/ipb-add-new-popup.php';
	}

	/**
	 * Return Content for All Popups menu
	 *
	 * @since    1.0.0
	 * @return string
	 */
	public function ipb_setting_popup_callback()
	{

		return   require_once plugin_dir_path(__FILE__) . 'partials/ipb-setting-popup.php';
	}

	/**
	 * Return Content for All Popups menu
	 *
	 * @since    1.0.0
	 * @return string
	 */
	public function ipb_analytics_popup_callback()
	{
		$this->display_analytics_page();
	}
	/**
	 * Return Content for All Popups menu
	 *
	 * @since    1.0.0
	 * @return string
	 */
	public function ipb_license_popup_callback()
	{

		return   require_once plugin_dir_path(__FILE__) . 'partials/ipb-license-popup.php';
	}
	/**
	 * Return Content for All Popups menu
	 *
	 * @since    1.0.0
	 * @return string
	 */
	public function ipb_extend_popup_callback()
	{

		return   require_once plugin_dir_path(__FILE__) . 'partials/ipb-extend-popup.php';
	}
	/**
	 * Return Content for All Popups menu
	 *
	 * @since    1.0.0
	 * @return string
	 */
	public function ipb_support_popup_callback()
	{

		return   require_once plugin_dir_path(__FILE__) . 'partials/ipb-support-popup.php';
	}
    /**
	 * Return Content for All Popups menu
	 *
	 * @since    1.0.0
	 * @return string
	 */
	public function ipb_upgrade_popup_callback()
	{
		return require_once plugin_dir_path(__FILE__) . 'partials/ipb-upgrade-popup.php';
	}
	/**
	 * Return All Popups from database
	 *
	 * @since    1.0.0
	 * @return array | object
	 */
	public function ipb_query_all_popup($status)
	{

		global $wpdb;
		$table_name = $wpdb->prefix . 'instant_popup_builder';
		$status = sanitize_text_field($status);
		$cache_key = 'all_quer_key';
		$cache_group = "all_quer_group";

		if ($status == 'publish') {

			$row = wp_cache_get($cache_key, $cache_group);

			if ($row == false) {

				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
				$row = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}instant_popup_builder where status= %s OR  status= %s ORDER BY id DESC",  'publish', 'draft'), ARRAY_A);
				wp_cache_set($cache_key, $row, $cache_group, 3600);
			}
		} else {

			$row = wp_cache_get($cache_key, $cache_group);

			if ($row == false) {

				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
				$row = $wpdb->get_results($wpdb->prepare("SELECT * FROM   {$wpdb->prefix}instant_popup_builder   where status= %s ORDER BY id DESC", $status), ARRAY_A);
				wp_cache_set($cache_key, $row, $cache_group, 3600);
			}
		}

		return $row;
	}

	/**
	 * Return Popup and match using query
	 *
	 * @since    1.0.0
	 * @param    string    $keyword    Search keyword to match against popup titles
	 * @return   array|object    Array of matching popup results
	 */
	public function ipb_search_query_popup($keyword)
	{

		global $wpdb;
		// $table_name = $wpdb->prefix . 'instant_popup_builder';

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
		$results = $wpdb->get_results($wpdb->prepare("SELECT * from  {$wpdb->prefix}instant_popup_builder where title LIKE %s",  '%' . $wpdb->esc_like($keyword) . '%'), ARRAY_A);
		// $results = $wpdb->get_results($row);

		return $results;
	}

	/**
	 * Return Popup and match using query
	 *
	 * @since    1.0.0
	 * @return array | object
	 */
	public function ipb_bulk_query_popup($keyword)
	{

		global $wpdb;
		// $table_name = $wpdb->prefix . 'instant_popup_builder';

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
		$results = $wpdb->get_results($wpdb->prepare("SELECT * from  {$wpdb->prefix}instant_popup_builder where class= %s", $keyword), ARRAY_A);
		// $results = $wpdb->get_results($row);

		return $results;
	}

	// private function handle_popup_video_popup() {
	// 	$video_type = isset($_POST['video_type']) ? sanitize_text_field(wp_unslash($_POST['video_type'])) : '';
	// 	$videoUrl = $video_type === 'self-hosted' ? sanitize_text_field(wp_unslash($_POST['popup_video_url'])) : sanitize_text_field(wp_unslash($_POST['popup_video_url_embed']));
	// 	$advance = $this->get_advance_fields();
	// 	$advance = array_merge($advance, [
	// 		'video_type' => $video_type,
	// 		'video_autoplay' => isset($_POST['video_autoplay']) ? sanitize_text_field(wp_unslash($_POST['video_autoplay'])) : '',
	// 		'video_loop' => isset($_POST['video_loop']) ? sanitize_text_field(wp_unslash($_POST['video_loop'])) : '',
	// 		'video_fullscreen' => isset($_POST['video_fullscreen']) ? sanitize_text_field(wp_unslash($_POST['video_fullscreen'])) : '',
	// 		'video_exit' => isset($_POST['video_exit']) ? sanitize_text_field(wp_unslash($_POST['video_exit'])) : '',
	// 		'video_play_pause' => isset($_POST['video_play_pause']) ? sanitize_text_field(wp_unslash($_POST['video_play_pause'])) : '',
	// 		'video_volume' => isset($_POST['video_volume']) ? sanitize_text_field(wp_unslash($_POST['video_volume'])) : '',
	// 		'video_mute' => isset($_POST['video_mute']) ? sanitize_text_field(wp_unslash($_POST['video_mute'])) : ''
	// 	]);
	// 	$fields = $this->get_common_fields();
	// 	return $this->ipb_query_popup_video($videoUrl, ...array_values($fields), $advance);
	// }

	// private function handle_popup_subscription_popup() {
	// 	$imageUrl = isset($_POST['popu_image_url']) ? sanitize_text_field(wp_unslash($_POST['popu_image_url'])) : '';
	// 	$advance = $this->get_advance_fields();
	// 	$advance = array_merge($advance, [
	// 		'first_label' => isset($_POST['first_label']) ? sanitize_text_field(wp_unslash($_POST['first_label'])) : '',
	// 		'first_placeholder' => isset($_POST['first_placeholder']) ? sanitize_text_field(wp_unslash($_POST['first_placeholder'])) : '',
	// 		'email_label' => isset($_POST['email_label']) ? sanitize_text_field(wp_unslash($_POST['email_label'])) : '',
	// 		'email_placeholder' => isset($_POST['email_placeholder']) ? sanitize_text_field(wp_unslash($_POST['email_placeholder'])) : '',
	// 		'privacy_label' => isset($_POST['privacy_label']) ? sanitize_text_field(wp_unslash($_POST['privacy_label'])) : '',
	// 		'pricacy_url' => isset($_POST['pricacy_url']) ? sanitize_text_field(wp_unslash($_POST['pricacy_url'])) : '',
	// 		'terms_url' => isset($_POST['terms_url']) ? sanitize_text_field(wp_unslash($_POST['terms_url'])) : ''
	// 	]);
	// 	$fields = $this->get_common_fields();
	// 	return $this->ipb_query_popup_subscription($imageUrl, ...array_values($fields), $advance);
	// }

	/**
	 * Markup for the standard "popup updated" toast (same as ipb_update_query success output).
	 *
	 * @param string $html_id Optional HTML id for standalone toasts (extension editor redirect flow).
	 * @return string
	 */
	public static function ipb_get_popup_update_toast_html($html_id = '')
	{
		$success_message = __('The popup has been updated.', 'instant-popup-builder');
		$id_attr = ($html_id !== '') ? ' id="' . esc_attr($html_id) . '"' : '';
		$toast_html = '<div' . $id_attr . ' class="ipb-popup-update-toast" style="position: fixed; top: 52px; right: 24px; z-index: 99999; display: none;">';
		$toast_html .= '<div style="display:flex; align-items:center; gap:12px; padding:12px 18px; background:#22aa5b; color:#fff; border-radius:4px; box-shadow:0 4px 12px rgba(0,0,0,0.18); font-size:13px;">';
		$toast_html .= '<span style="display:inline-flex; align-items:center; justify-content:center; width:18px; height:18px; border-radius:50%; border:2px solid #fff; font-size:11px; line-height:1;">&#10003;</span>';
		$toast_html .= '<span>' . esc_html($success_message) . '</span>';
		$toast_html .= '<button type="button" class="ipb-popup-update-toast-close" style="margin-left:16px; padding:4px 10px; background:#ffffff; color:#1e7b3b; border-radius:3px; border:none; cursor:pointer; font-size:12px;">' . esc_html__('Close', 'instant-popup-builder') . '</button>';
		$toast_html .= '</div></div>';
		return $toast_html;
	}

	/**
	 * Redirect after an extension updates an existing popup (POST handler on admin_init).
	 * Honors the global post-publish setting: dashboard by default, or editor with a toast when "stay" is selected.
	 *
	 * @param int    $popup_id  Database row id.
	 * @param string $type_slug URL type parameter (e.g. social_share, spin_to_win).
	 * @return void
	 */
	public static function ipb_redirect_after_extension_popup_update($popup_id, $type_slug)
	{
		$popup_id = absint($popup_id);
		$type_slug = is_string($type_slug) ? sanitize_key($type_slug) : '';
		if (!$popup_id || $type_slug === '') {
			return;
		}

		$allowed_pages = array('instant-popup-builder', 'add-new-instant-popup');
		$post_publish_behavior = get_option('instant_popup_builder_post_publish_behavior', 'dashboard');

		if ('stay' !== $post_publish_behavior) {
			wp_safe_redirect(
				add_query_arg(
					array(
						'page' => 'instant-popup-builder',
					),
					admin_url('admin.php')
				)
			);
			exit;
		}

		$referer = wp_get_referer();
		$target = '';

		if ($referer) {
			$parsed = wp_parse_url($referer);
			if (!empty($parsed['query'])) {
				parse_str($parsed['query'], $query_args);
				if (!empty($query_args['page']) && in_array((string) $query_args['page'], $allowed_pages, true)) {
					$target = $referer;
				}
			}
		}

		if ($target === '') {
			$target = add_query_arg(
				array(
					'page' => 'instant-popup-builder',
					'edit_id' => $popup_id,
					'type' => $type_slug,
				),
				admin_url('admin.php')
			);
		}

		$target = remove_query_arg(array('published', 'ipb_updated'), $target);
		$target = add_query_arg('ipb_updated', '1', $target);

		wp_safe_redirect($target);
		exit;
	}

	/**
	 * Output update toast on editor screen when extensions redirect with ipb_updated=1.
	 *
	 * @return void
	 */
	public function ipb_render_extension_update_toast()
	{
		if (!is_admin() || !current_user_can('manage_options')) {
			return;
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- display-only query flag after successful save
		if ('1' !== $this->ipb_get_admin_query_param('ipb_updated')) {
			return;
		}

		$page = sanitize_key($this->ipb_get_admin_query_param('page'));
		if ('' === $this->ipb_get_admin_query_param('edit_id')) {
			return;
		}

		$allowed_pages = array('instant-popup-builder', 'add-new-instant-popup');
		if (!in_array($page, $allowed_pages, true)) {
			return;
		}

		echo self::ipb_get_popup_update_toast_html('ipb-ipb-updated-toast'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped in helper
	}

	/**
	 * Persist popup row changes when editing built-in popup types (toast only, no redirect).
	 *
	 * @since 1.0.0
	 * @return string
	 */
	public function ipb_update_query($id, $text, $status, $title, $select_option, $is_display, $spec_val, $triger, $closing, $limit, $design, $advance)
	{

		global $wpdb;
		$table_name = $wpdb->prefix . 'instant_popup_builder';
		$all_popup_url = menu_page_url('instant-popup-builder', false);
		// Keep display rule arrays index-aligned after add/remove operations in the editor.
		if (is_array($spec_val)) {
			$spec_val = array_values($spec_val);
		} else {
			$spec_val = [];
		}

		// Strip stale "everywhere" entries when specific rules also exist.
		if (is_array($select_option) && count($select_option) > 1) {
			$filtered_selected = [];
			$filtered_is_display = [];
			$filtered_spec_val = [];
			foreach ($select_option as $idx => $opt) {
				if ($opt === 'everywhere') {
					continue;
				}
				$filtered_selected[] = $opt;
				$filtered_is_display[] = isset($is_display[$idx]) ? $is_display[$idx] : 'yes';
				$filtered_spec_val[] = isset($spec_val[$idx]) ? $spec_val[$idx] : [];
			}
			if (!empty($filtered_selected)) {
				$select_option = $filtered_selected;
				$is_display = $filtered_is_display;
				$spec_val = $filtered_spec_val;
			}
		}

		$display = [

			'selected' => $select_option,
			'is_display' => $is_display,
			'place' => $spec_val
		];

		// Keep the edit path extensible in the same way as Add New. Extensions can
		// persist namespaced trigger/settings data without a separate AJAX save.
		$triger = apply_filters( 'ipb_trigger_settings', $triger, '', $_POST );

		$data = [
			'title'       => $title,
			'status'      => $status,
			'class'       => ('publish' === $status ? 'yes' : ''),
			'content'     => wp_json_encode($text),
			'display'     => wp_json_encode($display),
			'ipb_trigger' => wp_json_encode($triger),
			'closing'     => wp_json_encode($closing),
			'position'    => wp_json_encode($limit),
			'design'      => wp_json_encode($design),
			'advance'     => wp_json_encode($advance),
		];
		$where = ['id' => $id];
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$result = $wpdb->update($table_name, $data, $where);

		// $wpdb->update returns int rows affected, or false on SQL error only — 0 means "no change", not failure.
		if ( false !== $result ) {
			$escaped_table_name = esc_sql($table_name);
			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- WordPress placeholders do not support table identifiers.
			$popup_type = $wpdb->get_var($wpdb->prepare("SELECT type FROM `{$escaped_table_name}` WHERE id = %d", $id));
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- The update request nonce is verified by the calling save handler.
			$posted_popup_type = isset($_POST['popup_temp_type']) ? sanitize_key(wp_unslash($_POST['popup_temp_type'])) : '';
			if ('subscription' === $popup_type || 'popup_subscription' === $posted_popup_type) {
				$this->save_popup_subscription_settings($id);
			}

			// Return only the toast HTML (no script). Script is stripped by wp_kses_post when
			// message is echoed and would flash as plain text. Toast is initialized by
			// inline script added in enqueue_scripts (ipb-init-update-toast).
			return self::ipb_get_popup_update_toast_html();
		}

		// return false;

	}
	/**
	 * Uploads an image file and returns its URL if the file type is allowed.
	 *
	 * @since    1.0.0
	 * @return void Sends JSON response with file URL or error message
	 */
	public function ipb_image_file_upload()
	{
		// Verify nonce
		if (!isset($_POST['file_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['file_nonce'])), 'upload_file_action')) {
			wp_send_json_error(array('message' => __('Security verification failed. Please refresh the page and try again.', 'instant-popup-builder')));
			return;
		}

		// Verify user capability
		if (!current_user_can('manage_options')) {
			wp_send_json_error(array('message' => __('You do not have permission to upload files.', 'instant-popup-builder')));
			return;
		}

		// Check if file was uploaded
		if (!isset($_FILES['file'], $_FILES['file']['error']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
			wp_send_json_error(array('message' => __('No file was uploaded or upload error occurred.', 'instant-popup-builder')));
			return;
		}

		// Validate file size (max 5MB for images)
		$max_size = 5 * 1024 * 1024; // 5MB in bytes
		if (!isset($_FILES['file']['size']) || $_FILES['file']['size'] > $max_size) {
			wp_send_json_error(array('message' => __('File size exceeds the maximum allowed size of 5MB.', 'instant-popup-builder')));
			return;
		}

		// Get file info using WordPress function for proper validation
		if (!isset($_FILES['file']['name'])) {
			wp_send_json_error(array('message' => __('File name is missing.', 'instant-popup-builder')));
			return;
		}
		$file_name = sanitize_file_name($_FILES['file']['name']);
		$file_info = wp_check_filetype($file_name);
		$allowed_types = array('jpg', 'jpeg', 'png', 'gif', 'webp', 'jfif');

		// Validate file extension
		if (!in_array(strtolower($file_info['ext']), $allowed_types)) {
			wp_send_json_error(array('message' => __('Invalid file type. Only image files (JPG, PNG, GIF, WEBP) are allowed.', 'instant-popup-builder')));
			return;
		}

		// Validate MIME type (additional security check)
		$allowed_mime_types = array('image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/webp', 'image/jfif');
		if (!isset($_FILES['file'], $_FILES['file']['type']) || !in_array($_FILES['file']['type'], $allowed_mime_types)) {
			wp_send_json_error(array('message' => __('Invalid file type. Only image files are allowed.', 'instant-popup-builder')));
			return;
		}

		// Configure upload overrides
		$upload_overrides = array(
			'test_form' => false,
			'mimes' => array(
				'jpg|jpeg|jpe' => 'image/jpeg',
				'png' => 'image/png',
				'gif' => 'image/gif',
				'webp' => 'image/webp',
				'jfif' => 'image/jpeg'
			)
		);

		// Handle file upload
		if (!isset($_FILES['file'])) {
			wp_send_json_error(array('message' => __('File upload data is missing.', 'instant-popup-builder')));
			return;
		}
		$upload = wp_handle_upload($_FILES['file'], $upload_overrides);

		if ($upload && !isset($upload['error'])) {
			// File uploaded successfully
			wp_send_json_success(array('url' => esc_url($upload['url'])));
		} else {
			// Error occurred during file upload
			$error_message = isset($upload['error']) ? $upload['error'] : __('An unknown error occurred during file upload.', 'instant-popup-builder');
			wp_send_json_error(array('message' => $error_message));
		}
	}

	/**
	 * Uploads a sound file and returns its URL if the file type is allowed.
	 *
	 * @since    1.0.0
	 * @return void Sends JSON response with file URL or error message
	 */
	public function ipb_file_sound_upload()
	{
		// Verify nonce
		if (!isset($_POST['file_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['file_nonce'])), 'upload_file_action')) {
			wp_send_json_error(array('message' => __('Security verification failed. Please refresh the page and try again.', 'instant-popup-builder')));
			return;
		}

		// Verify user capability
		if (!current_user_can('manage_options')) {
			wp_send_json_error(array('message' => __('You do not have permission to upload files.', 'instant-popup-builder')));
			return;
		}

		// Check if file was uploaded
		if (!isset($_FILES['file'], $_FILES['file']['error']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
			wp_send_json_error(array('message' => __('No file was uploaded or upload error occurred.', 'instant-popup-builder')));
			return;
		}

		// Validate file size (max 10MB for audio files)
		$max_size = 10 * 1024 * 1024; // 10MB in bytes
		if (!isset($_FILES['file']['size']) || $_FILES['file']['size'] > $max_size) {
			wp_send_json_error(array('message' => __('File size exceeds the maximum allowed size of 10MB.', 'instant-popup-builder')));
			return;
		}

		// Get file info using WordPress function for proper validation
		if (!isset($_FILES['file']['name'])) {
			wp_send_json_error(array('message' => __('File name is missing.', 'instant-popup-builder')));
			return;
		}
		$file_name = sanitize_file_name($_FILES['file']['name']);
		$file_info = wp_check_filetype($file_name);
		$allowed_types = array('mp3', 'mpeg', 'mpg');

		// Validate file extension
		if (!in_array(strtolower($file_info['ext']), $allowed_types)) {
			wp_send_json_error(array('message' => __('Invalid file type. Only MP3 audio files are allowed.', 'instant-popup-builder')));
			return;
		}

		// Validate MIME type (additional security check)
		$allowed_mime_types = array('audio/mpeg', 'audio/mp3', 'audio/x-mpeg', 'audio/x-mp3', 'audio/mpeg3', 'audio/mpg', 'audio/x-mpg', 'audio/x-mpegaudio');
		if (!isset($_FILES['file'], $_FILES['file']['type']) || !in_array($_FILES['file']['type'], $allowed_mime_types)) {
			wp_send_json_error(array('message' => __('Invalid file type. Only MP3 audio files are allowed.', 'instant-popup-builder')));
			return;
		}

		// Configure upload overrides
		$upload_overrides = array(
			'test_form' => false,
			'mimes' => array(
				'mp3' => 'audio/mpeg',
				'mpeg' => 'audio/mpeg',
				'mpg' => 'audio/mpeg'
			)
		);

		// Handle file upload
		if (!isset($_FILES['file'])) {
			wp_send_json_error(array('message' => __('File upload data is missing.', 'instant-popup-builder')));
			return;
		}
		$upload = wp_handle_upload($_FILES['file'], $upload_overrides);

		if ($upload && !isset($upload['error'])) {
			// File uploaded successfully
			wp_send_json_success(array('url' => esc_url($upload['url'])));
		} else {
			// Error occurred during file upload
			$error_message = isset($upload['error']) ? $upload['error'] : __('An unknown error occurred during file upload.', 'instant-popup-builder');
			wp_send_json_error(array('message' => $error_message));
		}
	}

	/**
	 * Uploads an image file and returns its URL if the file type is allowed.
	 *
	 * @since    1.0.0
	 * @return string The url of the uploaded image,or return blank
	 */
	// public function ipb_video_file_upload()
	// {

	// 	$arr_video_ext = array('video/mp4', 'video/mpeg', 'video/quicktime', 'video/x-msvideo', 'video/x-flv', 'video/3gpp', 'video/webm', 'video/x-ms-wmv');
	// 	if (in_array($_FILES['file']['type'], $arr_video_ext)) {
	// 		$upload = wp_upload_bits($_FILES["file"]["name"], null, wp_remote_get($_FILES["file"]["tmp_name"]));
	// 		echo   esc_url($upload['url']);
	// 	} else {

	// 		echo '';
	// 	}
	// 	wp_die();
	// }

	/**
	 * Check bulk action and perfom action trash/edit.
	 *
	 * @since    1.0.0
	 * @return string The url of the uploaded image,or return blank
	 */
	public function ipb_bulk_action()
	{
		if (!current_user_can('manage_options')) {
			wp_send_json_error(__('Insufficient permissions.', 'instant-popup-builder'), 403);
		}

		global $wpdb;
		$table_name = $wpdb->prefix . 'instant_popup_builder';

		// Check if the form is submitted
		if (isset($_POST['status'], $_POST['popup_ids'], $_POST['file_nonce'])) {
			// Verify nonce
			// $nonce = isset($_POST['file_nonce']) ? $_POST['file_nonce'] : '';
			if (isset($_POST['file_nonce']) && !empty($_POST['file_nonce']) &&  !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['file_nonce'])), 'upload_file_action')) {

				exit;
			}

			// Sanitize and validate input
			$status = sanitize_text_field(wp_unslash($_POST['status']));
			$popup_ids = is_array($_POST['popup_ids']) ? array_map('intval', $_POST['popup_ids']) : [];

			// Check if status is valid
			if ($status != 'delete-permenant'  && !empty($popup_ids)) {
				$count = 0;
				foreach ($popup_ids as $id) {
					// Update status for each popup
					$data = ['class' => $status];
					$where = ['id' => $id];

					// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
					// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching

					$updated = $wpdb->update($table_name, $data, $where);
					if ($updated !== false) {
						$count++;
					}
				}
				echo esc_html($count); // Output the number of popups updated
			} else {

				$count = 0;
				foreach ($popup_ids as $id) {
					// Update status for each popup
				$where = ['id' => $id];
				$format = ['%d'];
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
				$update = $wpdb->delete($table_name, $where, $format);
					if ($update !== false) {
						$count++;
					}
				}
				echo esc_html($count);
			}
		}
		wp_die();
	}

	/**
	 * Return Content for All Popups menu
	 *
	 * @since    1.0.0
	 * @return array
	 */
	public function ipb_display_option()
	{

		$array = [

			'post' => [

				'all-posts' => 'All Posts',
				'selected-post' => ' Selected Posts',
				'post-type' => 'Post Type',
				'post-category' => 'Post Category'
			],
			'page' => [

				'all-pages' => 'All Pages',
				'selected-page' => ' Selected Pages',
				// 'page-type' => 'Page Type',
			],
			'tags' => [

				'all-tags' => 'All Tags',
				'selected-tags' => ' Selected Tags',
			],
			'everywhere' => [

				'everywhere' => 'All',
			]

		];

		return $array;
	}

	/**
	 * Return Content for All Popups menu
	 *
	 * @since    1.0.0
	 * @return array
	 */
	public function ipb_chart_titles()
	{

		global $wpdb;
		$table_name = $wpdb->prefix . 'instant_popup_builder';
		$escaped_table_name = esc_sql($table_name);
		// Table name is safely escaped with esc_sql() - no user input values to prepare
		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
		$rows = $wpdb->get_results("SELECT title,views FROM `{$escaped_table_name}`");

		$title = [];
		$count = [];

		foreach ($rows as $row) {

			$title[] = $row->title;
			$count[] = intval($row->views);
		}

		$data = [
			'title' => $title,
			'count' => $count
		];

		return $data;
	}

	/**
	 * Display tab Ajax call
	 *
	 * @since    1.0.0
	 * @return string
	 */

	public function ipb_display_ajax()
	{
		$response = array();

		if (!current_user_can('manage_options')) {
			wp_send_json_error(__('Insufficient permissions.', 'instant-popup-builder'), 403);
		}

		if (isset($_POST['value']) && !empty($_POST['value']) && isset($_POST['nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'display_ajax_action')) {

			$value = sanitize_text_field(wp_unslash($_POST['value']));

			if ($value == 'all-posts' || $value == 'selected-post' || $value == 'post-category' || $value == 'post-type' || $value == 'everywhere') {

				$response = $this->get_post_request($value);
			}
			if ($value == 'all-pages' || $value == 'selected-page') {

				$response = $this->get_page_request($value);
			}
			if ($value == 'all-tags' || $value == 'selected-tags') {

				$response = $this->get_tags_request($value);
			}
		}

		wp_send_json($response);
		die();
	}

	/**
	 * Popup Status Active/Inactive Ajax call
	 *
	 * @since    1.0.0
	 * @return string
	 */

	public function ipb_popup_status_ajax()
	{
		$response = array( 'response' => false );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json( $response );
			return;
		}

		if ( ! isset( $_POST['value'] ) || ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'display_ajax_action' ) ) {
			wp_send_json( $response );
			return;
		}

		global $wpdb;
		$table = $wpdb->prefix . 'instant_popup_builder';
		$value = sanitize_text_field( wp_unslash( $_POST['value'] ) );
		$id    = isset( $_POST['id'] ) ? sanitize_text_field( wp_unslash( $_POST['id'] ) ) : '';

		if ( ! $id ) {
			wp_send_json( $response );
			return;
		}

		// Block activation if popup type requires an extension that is not active.
		if ( $value === 'yes' && class_exists( 'Instant_Popup_Builder_Extension_Dependency', false ) ) {
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			$popup_row = $wpdb->get_row( $wpdb->prepare( "SELECT type, advance FROM {$table} WHERE id = %s LIMIT 1", $id ) );
			$popup_type = ( $popup_row && isset( $popup_row->type ) ) ? $popup_row->type : '';
			$popup_advance = ( $popup_row && isset( $popup_row->advance ) ) ? $popup_row->advance : '';
			if ( $popup_type && Instant_Popup_Builder_Extension_Dependency::is_extension_required_for_type( $popup_type, $popup_advance ) && ! Instant_Popup_Builder_Extension_Dependency::is_extension_active_for_type( $popup_type, $popup_advance ) ) {
				wp_send_json( $response );
				return;
			}
		}

		if ( $value ) {
			$data   = array( 'class' => $value );
			$where  = array( 'id' => $id );
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			$status = $wpdb->update( $table, $data, $where );

			if ( $status ) {
				$response = array( 'response' => true );
			}
		}

		wp_send_json( $response );
	}

	/**
	 * Duplicate Popups
	 *
	 */
	public function ipb_popup_duplicate(){
		$response = ['response' => false];

		if (!current_user_can('manage_options')) {
			wp_send_json($response, 403);
		}

		if (isset($_POST['id']) && !empty($_POST['id']) && isset($_POST['nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'display_ajax_action')) {

			global $wpdb;
			$id = intval($_POST['id']);
			$table = $wpdb->prefix . 'instant_popup_builder';
			$escaped_table = esc_sql($table);

			// Fetch the row
			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
			$row = $wpdb->get_row($wpdb->prepare("SELECT * FROM `{$escaped_table}` WHERE id = %d", $id), ARRAY_A);

				if ($row) {

					unset($row['id']);   // Remove the ID for a new row insertion
					$row['title'] = $row['title'] . ' (Copy)';
					$row['views'] = '0';  // Reset views
					$currentDate = new DateTime();
					$cur_date = $currentDate->format('Y-m-d H:i:s');
					$row['date'] = $cur_date;
					// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
					// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
					$inserted = $wpdb->insert($table, $row);

					if ($inserted) {

					$response = ['response' => true];
					} else {

						$response = ['response' => false];
					}
				}

		}

		wp_send_json($response);
		die();
	}

	/**
	 * Get post response
	 *
	 * @since    1.0.0
	 * @return object | array
	 */

	public function get_post_request($value)
	{

		$post = [];

		if ($value == 'selected-post') {

			$posts = get_posts([

				'post_type' => 'post',
				'posts_per_page' => -1,
				'post_status' => 'publish'
			]);

			foreach ($posts as $p) {

				$post[$p->ID] = get_the_title($p->ID);
			}
		}
		if ($value == 'all-posts') {

			$post['allposts'] = 'All';
		}
		if ($value == 'everywhere') {

			$post['everywhere'] = 'All';
		}

		if ($value == 'post-type') {

			$post_types = get_post_types(array('public' => true), 'objects');

			// Post types to exclude
			$post_types_to_exclude = array('revision', 'attachment', 'page');

			// Loop through each post type
			foreach ($post_types as $post_type) {
				// Check if the post type is not in the excluded list
				if (!in_array($post_type->name, $post_types_to_exclude)) {
					$post[$post_type->name] = $post_type->name;
				}
			}
		}

		if ($value == 'post-category') {

			$terms = get_terms([
				'taxonomy' => 'category',
				'hide_empty' => false
			]);

			if (!empty($terms)) {

				foreach ($terms as $term) {

					$post[$term->term_id] = $term->name;
				}
			}
		}

		return $post;
	}

	/**
	 * Get page response
	 *
	 * @since    1.0.0
	 * @return object | array
	 */

	public function get_page_request($value)
	{

		$page = [];

		if ($value == 'selected-page') {

			$pages = get_pages();

			foreach ($pages as $p) {

				$page[$p->post_name] = $p->post_title;
			}
		}
		if ($value == 'all-pages') {

			$page['all-pages'] = 'All Pages';
		}

		return $page;
	}

	/**
	 * Get tags response
	 *
	 * @since    1.0.0
	 * @return object | array
	 */

	public function get_tags_request($value)
	{

		$tag = [];

		if ($value == 'selected-tags') {

			$tags = get_terms(
				[
					'taxonomy' => 'post_tag',
					'hide_empty' => false
				]
			);

			if ($tags) {

				foreach ($tags as $t) {

					$tag[$t->term_id] = $t->name;
				}
			} else {

				$tag['no-tags'] = "No Tag Found";
			}
		}
		if ($value == 'all-tags') {

			$tag['all-tags'] = 'All Tags';
		}

		return $tag;
	}

	/**
	 * Meta boxes for post
	 * @return void
	 *
	 */
	public function post_meta_box()
	{

		add_meta_box(
			'post-meta-box',
			'Setting',
			[$this, 'post_meta_box_content'],
			'post',  // Replace 'post' with your desired post type slug
			'normal',
			'default'
		);
	}

	public function post_meta_box_content()
	{

?>
		<input type="text" id="custom-field" name="custom_field" value="" />

	<?php
	}

	/**
	 * Update setting data
	 * s
	 */
	public function ipb_setting_actions()
	{
		// Verify nonce before processing form data
		if ( ! isset( $_POST['instant_popup_builder_setting'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['instant_popup_builder_setting'] ) ), 'instant_popup_builder_setting_action' ) ) {
			return;
		}

		if ( isset( $_POST['database_deactivate'] ) ) {

			// Handle existing setting
			if (isset($_POST['ipb_db_del'])) {
				update_option('instant_popup_builder_db_active', sanitize_text_field(wp_unslash($_POST['ipb_db_del'])));
			} else {
				update_option('instant_popup_builder_db_active', 'no');
			}

			// Handle debug mode
			if (isset($_POST['ipb_debug_mode'])) {
				update_option('instant_popup_builder_db_debug', sanitize_text_field(wp_unslash($_POST['ipb_debug_mode'])));
			} else {
				update_option('instant_popup_builder_db_debug', 'no');
			}

			// Handle new enhanced settings
			if (isset($_POST['ipb_preserve_analytics'])) {
				update_option('instant_popup_builder_preserve_analytics', sanitize_text_field( wp_unslash( $_POST['ipb_preserve_analytics'] )));
			} else {
				update_option('instant_popup_builder_preserve_analytics', 'no');
			}

			if (isset($_POST['ipb_cleanup_options'])) {
				update_option('instant_popup_builder_cleanup_options', sanitize_text_field(wp_unslash($_POST['ipb_cleanup_options'])));
			} else {
				update_option('instant_popup_builder_cleanup_options', 'no');
			}

			// Handle post-publish behavior (where to redirect after creating/updating a popup)
			if (isset($_POST['ipb_post_publish_behavior'])) {
				$instant_popup_builder_post_publish_behavior = sanitize_text_field(wp_unslash($_POST['ipb_post_publish_behavior']));
				// Only allow known values to be stored
				$allowed_behaviors = array('dashboard', 'stay');
				if (! in_array($instant_popup_builder_post_publish_behavior, $allowed_behaviors, true)) {
					$instant_popup_builder_post_publish_behavior = 'dashboard';
				}
				update_option('instant_popup_builder_post_publish_behavior', $instant_popup_builder_post_publish_behavior);
			}

			// Handle Analytics Dashboard Widget setting
			if (isset($_POST['ipb_dashboard_widget'])) {
				update_option('instant_popup_analytics_dashboard_widget', sanitize_text_field(wp_unslash($_POST['ipb_dashboard_widget'])));
			} else {
				update_option('instant_popup_analytics_dashboard_widget', 'no');
			}

			// Show success message
			add_action('admin_notices', function() {
				echo '<div class="notice notice-success is-dismissible"><p>Settings saved successfully!</p></div>';
			});

			// Allow extensions to save their own settings
			do_action('instant_popup_builder_save_settings');
		}
	}

	/**
	 * Modal function to render differnt modal type
	 *
	 * @return string
	 * @param string
	 *
	 */
	public function trigger_modal($type, $id)
	{

		$popup_id = $id;

		return include_once plugin_dir_path(__FILE__) . '/popup_modal/modal-' . $type . '.php';
	}

	/**
	 * Sticky top bar - DISABLED
	 * Top menu has been moved to left sidebar for cleaner UI
	 *
	 */
	public static function ipb_top_header()
	{
		// Top header has been disabled - all menu items moved to left sidebar
		return;
	}

	/**
	 * Admin notice to add a review
	 *
	 */
	public function ipb_admin_notice()
	{
		// Only show on plugin pages
		if (!$this->is_plugin_page()) {
			return;
		}

		if (!current_user_can('manage_options')) {
			return;
		}

		$dismissed = get_user_meta(get_current_user_id(), 'ipb_review_notice_dismissed', true);
		$already_given = get_user_meta(get_current_user_id(), 'ipb_review_already_given', true);
		$show_notice = get_option('ipb_show_review_notice', 'no');
		$review_show_date = get_option('ipb_review_show_date', 0);

		$two_weeks = 14 * DAY_IN_SECONDS;
		$now = time();

		// Don't show if user already gave a review
		if ($already_given) {
			return;
		}

		// Don't show if global flag is off
		if ($show_notice !== 'yes') {
			return;
		}

		// Don't show if it's too early (before 5-7 days after activation)
		if ($now < $review_show_date) {
			return;
		}

		// If user clicked "Maybe Later" and 2 weeks haven't passed, don't show
		if ($dismissed && ($now - $dismissed) < $two_weeks) {
			return;
		}

		$review_url = esc_url('https://wordpress.org/plugins/instant-popup-builder/#reviews');
		$dismiss_url = esc_url(add_query_arg('ipb_notice_action', 'dismiss'));
		$already_given_url = esc_url(add_query_arg('ipb_notice_action', 'already_given'));

		echo '<div class="notice notice-info ipb-review-notice">';
		echo '<div class="ipb-review-notice__inner">';
		echo '<p class="ipb-review-notice__message"><strong>' . esc_html__('Enjoying Instant Popup Builder?', 'instant-popup-builder') . '</strong> ';
		echo esc_html__('Please consider leaving a review on WordPress.org. Your feedback helps us improve.', 'instant-popup-builder') . '</p>';
		echo '<p class="ipb-review-notice__actions">';
		echo '<a class="button button-primary" href="' . esc_url($review_url) . '" target="_blank" rel="noopener noreferrer">' . esc_html__('Leave a review', 'instant-popup-builder') . '</a> ';
		echo '<a class="button button-secondary" href="' . esc_url($already_given_url) . '">' . esc_html__('Already reviewed', 'instant-popup-builder') . '</a> ';
		echo '<a class="button button-secondary" href="' . esc_url($dismiss_url) . '">' . esc_html__('Remind me later', 'instant-popup-builder') . '</a>';
		echo '</p>';
		echo '</div>';
		echo '</div>';
	}

	/**
	 * Check if current page is a plugin page
	 *
	 */
	private function is_plugin_page()
	{
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$current_page = $this->ipb_get_admin_query_param('page');
		if (!is_admin() || '' === $current_page) {
			return false;
		}

		$plugin_pages = [
			'instant-popup-builder',
			'add-new-instant-popup',
			'analytics-instant-popup',
			'setting-instant-popup',
			'support-instant-popup',
			'upgrade-instant-popup',
			'license-instant-popup',
			'instant-popup-configuration',
			'configuration-instant-popup',
			'instant-subscriber-list',
			'instant-subscriber-add-new',
			'instant-popup-analytics-enhanced',
		];

		if (in_array($current_page, $plugin_pages, true)) {
			return true;
		}

		// Allow extension screens that belong to Instant Popup Builder while
		// avoiding broad matches against unrelated WordPress admin pages.
		$plugin_page_fragments = [
			'instant-popup-',
			'instant-subscriber-',
			'ipb-',
		];

		foreach ($plugin_page_fragments as $fragment) {
			if (0 === strpos($current_page, $fragment)) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Add a stable body class on Instant Popup Builder admin screens.
	 *
	 * This provides a compatibility-safe namespace for current and future
	 * admin CSS without modifying WordPress core page classes.
	 *
	 * @param string $classes Existing admin body classes.
	 * @return string
	 */
	public function ipb_admin_body_class($classes)
	{
		if ($this->is_plugin_page()) {
			$classes .= ' ipb-admin-page';
		}

		return $classes;
	}

	/**
	 * Admin notice action handler
	 *
	 */
	public function ipb_handle_notice_action()
	{
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$action = $this->ipb_get_admin_query_param('ipb_notice_action');
		if ('' === $action || !current_user_can('manage_options')) {
			return;
		}

		switch ($action) {
			case 'dismiss': // Maybe Later
				update_user_meta(get_current_user_id(), 'ipb_review_notice_dismissed', time());
				break;

			case 'already_given':
				update_user_meta(get_current_user_id(), 'ipb_review_already_given', 1);
				break;
		}

		// Redirect to clean up URL
		wp_safe_redirect(remove_query_arg('ipb_notice_action'));
		exit;
	}

	/**
	 * Hide WordPress admin footer on plugin pages
	 *
	 */
	public function ipb_hide_admin_footer()
	{
		// Check if we're on a plugin admin page
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$current_page = $this->ipb_get_admin_query_param('page');
		if (!is_admin() || '' === $current_page) {
			return;
		}

		// Check extension activation status for conditional pages
		$is_active = class_exists('Class_instant_popup_builder_manager') ? Class_instant_popup_builder_manager::get_active_popup() : [];
		$licenses = class_exists('Class_instant_popup_builder_license') ? Class_instant_popup_builder_license::getLicense() : [];
		$subscription_active = in_array('subscription', $is_active);
		$has_licensed_extensions = count($licenses) > 0;

		// Base plugin pages that are always available
		$plugin_pages = [
			'instant-popup-builder',
			'add-new-instant-popup',
			'analytics-instant-popup',
			'setting-instant-popup',
			'support-instant-popup',
			'upgrade-instant-popup'
		];

		// Add conditional pages based on extension status
		if ($subscription_active) {
			$plugin_pages[] = 'configuration-instant-popup';
			$plugin_pages[] = 'instant-subscriber-list';
			$plugin_pages[] = 'instant-subscriber-add-new';
		}

		if ($has_licensed_extensions) {
			$plugin_pages[] = 'license-instant-popup';
		}

		// Also include analytics extension pages
		$plugin_pages[] = 'instant-popup-analytics-enhanced';

		// Editor layouts should not show custom footer text in content area.
		// phpcs:disable WordPress.Security.NonceVerification.Recommended -- GET edit_id only affects which footer text is shown; no privileged action.
		$is_popup_editor_layout = ($current_page === 'add-new-instant-popup')
			|| (
				$current_page === 'instant-popup-builder'
				&& '' !== $this->ipb_get_admin_query_param('edit_id')
			);
		// phpcs:enable WordPress.Security.NonceVerification.Recommended

		if (in_array($current_page, $plugin_pages)) {
			if ($is_popup_editor_layout) {
				add_filter('admin_footer_text', '__return_empty_string', 99);
			} else {
				add_filter('admin_footer_text', function () {
					return 'Loving Instant Popup Builder? A quick <a href="https://wordpress.org/support/plugin/instant-popup-builder/reviews/#new-post" target="_blank" rel="noopener noreferrer">&#9733;&#9733;&#9733;&#9733;&#9733; rating on WordPress.org</a> would mean a lot and help others discover it too.';
				}, 99);
			}
			add_filter('update_footer', '__return_empty_string', 99);
		}
	}

	/**
	 * Add screen options support for All Popups page
	 *
	 * @since 1.0.6.3
	 */
	public function ipb_add_screen_options()
	{
		$screen = get_current_screen();
		// Only add screen options to the All Popups page
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if (!$screen || 'instant-popup-builder' !== $this->ipb_get_admin_query_param('page')) {
			return;
		}
		// Don't add screen options if we're editing a popup
		if ('' !== $this->ipb_get_admin_query_param('edit_id')) {
			return;
		}

		// Add screen options for per-page display
		add_screen_option('per_page', array(
			'label' => __('Popups per page', 'instant-popup-builder'),
			'default' => 10,
			'option' => 'ipb_popups_per_page'
		));

		// Add filter to save screen options
		add_filter('set-screen-option', [$this, 'ipb_set_screen_option'], 10, 3);
	}

	/**
	 * Save screen options for All Popups page
	 *
	 * @since 1.0.6.3
	 * @param mixed $status
	 * @param string $option
	 * @param mixed $value
	 * @return mixed
	 */
	public function ipb_set_screen_option($status, $option, $value)
	{
		if ('ipb_popups_per_page' === $option) {
			// Validate the value
			$value = intval($value);
			if ($value < 1 || $value > 999) {
				$value = 10; // Default fallback
			}
			return $value;
		}

		return $status;
	}

	/**
	 * Get the number of popups to display per page
	 *
	 * @since 1.0.6.3
	 * @return int
	 */
	public static function ipb_get_popups_per_page()
	{
		$user = get_current_user_id();
		$screen = get_current_screen();

		// Get user's preference, default to 10
		$per_page = get_user_meta($user, 'ipb_popups_per_page', true);

		if (empty($per_page) || $per_page < 1) {
			$per_page = 10; // Updated default from 3 to 10
		}

		return intval($per_page);
	}

	public function display_analytics_page() {
		if (!current_user_can('manage_options')) {
			wp_die(esc_html__('You do not have sufficient permissions to access this page.','instant-popup-builder'));
		}

		// Get analytics data
		$analytics_data = Instant_Popup_Builder_Analytics::get_all_popups_summary();

		echo '<div class="wrap">';
		echo '<h1>' . esc_html__('Popup Analytics', 'instant-popup-builder') . '</h1>';

		// Add basic styling
		echo '<style>
			.ipb-analytics-summary { margin: 20px 0; }
			.ipb-analytics-summary table th { background-color: #f1f1f1; }
			.ipb-analytics-summary table td,
			.ipb-analytics-summary table th { padding: 10px; text-align: center; }
			.ipb-analytics-summary table td:first-child { text-align: left; font-weight: bold; }
			.ipb-analytics-note { margin-top: 20px; padding: 15px; background-color: #f9f9f9; border-left: 4px solid #72aee6; }
			.ipb-analytics-note p { margin: 0; color: #646970; }

			/* Upgrade Notice Styles */
			.ipb-analytics-upgrade-notice {
				background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
				border-radius: 8px;
				margin: 20px 0;
				overflow: hidden;
				box-shadow: 0 4px 12px rgba(0,0,0,0.15);
			}
			.upgrade-notice-content {
				padding: 25px;
				color: white;
			}
			.upgrade-notice-content h3 {
				margin: 0 0 15px 0;
				font-size: 24px;
				font-weight: 600;
				color: white;
			}
			.upgrade-notice-content p {
				margin: 0 0 20px 0;
				font-size: 16px;
				opacity: 0.9;
			}
			.upgrade-features {
				display: flex;
				gap: 30px;
				margin: 20px 0;
				flex-wrap: wrap;
			}
			.features-column {
				flex: 1;
				min-width: 300px;
			}
			.upgrade-features ul {
				margin: 0;
				padding: 0;
				list-style: none;
			}
			.upgrade-features li {
				margin: 8px 0;
				font-size: 14px;
				line-height: 1.4;
				opacity: 0.95;
			}
			.upgrade-cta {
				margin-top: 25px;
				display: flex;
				align-items: center;
				gap: 15px;
				flex-wrap: wrap;
			}
			.upgrade-cta .button-primary {
				background: #ffffff;
				border-color: #ffffff;
				color: #667eea;
				font-weight: 600;
				padding: 8px 20px;
				font-size: 16px;
				border-radius: 5px;
				text-decoration: none;
				transition: all 0.3s ease;
			}
			.upgrade-cta .button-primary:hover {
				background: #f8f9fa;
				transform: translateY(-1px);
				box-shadow: 0 2px 8px rgba(0,0,0,0.2);
			}
			.pricing-info {
				color: rgba(255,255,255,0.9);
				font-size: 14px;
				font-weight: 500;
			}

			@media (max-width: 768px) {
				.upgrade-features { flex-direction: column; gap: 15px; }
				.features-column { min-width: auto; }
				.upgrade-cta { flex-direction: column; align-items: flex-start; }
			}
		</style>';

		if (empty($analytics_data)) {
			echo '<div class="notice notice-info"><p>' . esc_html__('No analytics data available yet.', 'instant-popup-builder') . '</p></div>';
			echo '</div>';
			return;
		}

		// Add upgrade notice for advanced analytics
		echo '<div class="ipb-analytics-upgrade-notice">';
		echo '<div class="upgrade-notice-content">';
		echo '<h3>' . esc_html__('🚀 Unlock Advanced Analytics', 'instant-popup-builder') . '</h3>';
		echo '<p>' . esc_html__('Take your popup analytics to the next level with our Advanced Analytics Extension:', 'instant-popup-builder') . '</p>';
		echo '<div class="upgrade-features">';
		echo '<div class="features-column">';
		echo '<ul>';
		echo '<li>✨ ' . esc_html__('Professional dashboard with real-time stats', 'instant-popup-builder') . '</li>';
		echo '<li>📊 ' . esc_html__('Interactive charts powered by Chart.js', 'instant-popup-builder') . '</li>';
		echo '<li>🎯 ' . esc_html__('Advanced conversion tracking', 'instant-popup-builder') . '</li>';
		echo '<li>📈 ' . esc_html__('30-day trend analysis with ranked tables', 'instant-popup-builder') . '</li>';
		echo '</ul>';
		echo '</div>';
		echo '<div class="features-column">';
		echo '<ul>';
		echo '<li>🤖 ' . esc_html__('AI-driven insights and recommendations', 'instant-popup-builder') . '</li>';
		echo '<li>👥 ' . esc_html__('User behavior and session data tracking', 'instant-popup-builder') . '</li>';
		echo '<li>📱 ' . esc_html__('Device metrics and performance analytics', 'instant-popup-builder') . '</li>';
		echo '<li>📄 ' . esc_html__('Exportable reports for campaigns', 'instant-popup-builder') . '</li>';
		echo '</ul>';
		echo '</div>';
		echo '</div>';
		echo '<div class="upgrade-cta">';
		echo '<a href="https://instantpopupbuilder.com/extensions/analytics/" target="_blank" class="button button-primary button-large">' . esc_html__('Get Advanced Analytics Extension', 'instant-popup-builder') . '</a>';
		echo '</div>';
		echo '</div>';
		echo '</div>';

		echo '<div class="ipb-analytics-summary">';
		echo '<table class="wp-list-table widefat fixed striped">';
		echo '<thead>';
		echo '<tr>';
		echo '<th>' . esc_html__('Popup Title', 'instant-popup-builder') . '</th>';
		echo '<th>' . esc_html__('Total Views', 'instant-popup-builder') . '</th>';
		echo '<th>' . esc_html__('Total Clicks', 'instant-popup-builder') . '</th>';
		echo '<th>' . esc_html__('Recent Views (30d)', 'instant-popup-builder') . '</th>';
		echo '<th>' . esc_html__('Recent Clicks (30d)', 'instant-popup-builder') . '</th>';
		echo '<th>' . esc_html__('Click Through Rate', 'instant-popup-builder') . '</th>';
		echo '<th>' . esc_html__('Conversion Rate', 'instant-popup-builder') . '</th>';
		echo '</tr>';
		echo '</thead>';
		echo '<tbody>';

		foreach ($analytics_data as $data) {
			echo '<tr>';
			echo '<td><strong>' . esc_html($data['title']) . '</strong></td>';
			echo '<td>' . esc_html(number_format($data['total_views'])) . '</td>';
			echo '<td>' . esc_html(number_format($data['total_clicks'])) . '</td>';
			echo '<td>' . esc_html(number_format($data['recent_views'])) . '</td>';
			echo '<td>' . esc_html(number_format($data['recent_clicks'])) . '</td>';
			echo '<td>' . esc_html($data['click_through_rate']) . '%</td>';
			echo '<td>' . esc_html($data['conversion_rate']) . '%</td>';
			echo '</tr>';
		}

		echo '</tbody>';
		echo '</table>';
		echo '</div>';

		echo '<div class="ipb-analytics-note">';
		echo '<p><em>' . esc_html__('Note: This is basic analytics included with the core plugin. For advanced reporting, interactive charts, AI-driven insights, and comprehensive analytics features, ', 'instant-popup-builder') . '<a href="https://instantpopupbuilder.com/extensions/analytics/" target="_blank">' . esc_html__('upgrade to our Analytics Extension', 'instant-popup-builder') . '</a>.</em></p>';
		echo '</div>';

		echo '</div>';
	}

	/**
	 * Calculate database size for popups
	 *
	 * @since    1.0.62
	 */
	public function ipb_calculate_db_size()
	{
		// Check nonce
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field( wp_unslash($_POST['nonce'])), 'ipb_admin_nonce')) {
			wp_die('Security check failed');
		}

		if (!current_user_can('manage_options')) {
			wp_die('Insufficient permissions');
		}

		try {
			global $wpdb;
			$table_name = $wpdb->prefix . 'instant_popup_builder';

			// Get table size
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
			$size_query = $wpdb->prepare(
				"SELECT
					ROUND(((data_length + index_length) / 1024 / 1024), 2) AS 'DB Size in MB'
				FROM information_schema.tables
				WHERE table_schema = %s
				AND table_name = %s",
				DB_NAME,
				$table_name
			);

			// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Query is prepared immediately above with fixed placeholders.
			$size = $wpdb->get_var($size_query);

			if ($size === null) {
				$size = 'Unknown';
			} else {
				$size = $size . ' MB';
			}

			wp_send_json_success([
				'size' => $size
			]);

		} catch (Exception $e) {
			wp_send_json_error([
				'message' => 'Failed to calculate database size: ' . $e->getMessage()
			]);
		}
	}

	/**
	 * Re-run activation-related routines to repair/initialize missing data
	 * Ensures DB schema upgrades, subscription settings table, defaults, and default campaign
	 */
	public function ipb_rerun_activation()
	{
		// Check nonce
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ipb_admin_nonce')) {
			wp_die('Security check failed');
		}

		if (!current_user_can('manage_options')) {
			wp_die('Insufficient permissions');
		}

		$results = [
			'upgrade_database' => false,
			'create_subscription_table' => false,
			'ensure_global_subscription_options' => false,
			'ensure_default_subscription_campaign' => false,
		];

		// Load activator
		require_once plugin_dir_path(__DIR__) . 'includes/class-instant-popup-builder-activator.php';

		// Run schema upgrades (idempotent)
		try {
			Instant_Popup_Builder_Activator::upgrade_database();
			Instant_Popup_Builder_Activator::install_feature_tables();
			update_option(
				'instant_popup_builder_db_version',
				defined('INSTANT_POPUP_BUILDER_DB_VERSION') ? INSTANT_POPUP_BUILDER_DB_VERSION : INSTANT_POPUP_BUILDER_VERSION
			);
			$results['upgrade_database'] = true;
		} catch (Exception $e) {
			// silently record failure state
			$results['upgrade_database'] = false;
		}

		// Ensure subscription settings table exists (idempotent)
		try {
			Instant_Popup_Builder_Activator::create_subscription_settings();
			$results['create_subscription_table'] = true;
		} catch (Exception $e) {
			$results['create_subscription_table'] = false;
		}

		// Ensure global subscription options exist
		$existing = get_option('instant_popup_subscription_settings', null);
		if (empty($existing) || !is_array($existing)) {
			$defaults = self::get_subscription_settings();
			if (is_array($defaults)) {
				$results['ensure_global_subscription_options'] = update_option('instant_popup_subscription_settings', $defaults) ? true : false;
			}
		} else {
			$results['ensure_global_subscription_options'] = true; // already present
		}

		// Ensure a default subscription campaign exists
		try {
			$default_id = $this->get_or_create_default_campaign();
			$results['ensure_default_subscription_campaign'] = !empty($default_id);
		} catch (Exception $e) {
			$results['ensure_default_subscription_campaign'] = false;
		}

		wp_send_json_success([
			'message' => 'Activation routines executed',
			'results' => $results,
		]);
	}

	/**
	 * Factory reset: drop plugin tables and delete plugin options, then re-run activation
	 */
	public function ipb_factory_reset()
	{
		// Check nonce
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ipb_admin_nonce')) {
			wp_die('Security check failed');
		}
		if (!current_user_can('manage_options')) {
			wp_die('Insufficient permissions');
		}

		global $wpdb;
		$prefix = $wpdb->prefix;
		$tables = [
			$prefix . 'instant_popup_builder',
			$prefix . 'instant_popup_analytics',
			$prefix . 'instant_popup_subscription_settings',
			$prefix . 'instant_popup_subscriber',
		];

		$deleted_tables = [];
		foreach ($tables as $table) {
			// Only drop if exists
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
			$exists = $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $table));
			if ($exists) {
				// Table name is from whitelist and safely escaped with esc_sql() - no user input values to prepare
				$escaped_table = esc_sql($table);
				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange
				$wpdb->query("DROP TABLE IF EXISTS `{$escaped_table}`");
				$deleted_tables[] = $table;
			}
		}

		// Delete plugin options (safe list)
		$options = [
			'instant_popup_builder_db_active',
			'instant_popup_builder_db_debug',
			'instant_popup_builder_preserve_analytics',
			'instant_popup_builder_cleanup_options',
			'instant_popup_analytics_dashboard_widget',
			'ipb_activation_date',
			'ipb_review_show_date',
			'ipb_show_review_notice',
			'instant_popup_subscription_settings',
			'instant_popup_subscription_activated',
			'subscription_license_active',
		];
		$deleted_options = [];
		foreach ($options as $opt) {
			if (get_option($opt, null) !== null) {
				delete_option($opt);
				$deleted_options[] = $opt;
			}
		}

		// Clear user meta flags for review notices
		$users = get_users(['fields' => 'ID']);
		foreach ($users as $uid) {
			delete_user_meta($uid, 'ipb_review_notice_dismissed');
			delete_user_meta($uid, 'ipb_review_already_given');
		}

		// Re-run activation to recreate schema and defaults
		require_once plugin_dir_path(__DIR__) . 'includes/class-instant-popup-builder-activator.php';
		Instant_Popup_Builder_Activator::activate();

		wp_send_json_success([
			'message' => 'Factory reset completed',
			'dropped_tables' => $deleted_tables,
			'deleted_options' => $deleted_options,
		]);
	}
	/**
	 * Export all popups to JSON file
	 *
	 * @since    1.0.62
	 */
	public function ipb_export_popups()
	{
		// Check nonce
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ipb_admin_nonce')) {
			wp_die('Security check failed');
		}

		if (!current_user_can('manage_options')) {
			wp_die('Insufficient permissions');
		}

		try {
			global $wpdb;
			$table_name = $wpdb->prefix . 'instant_popup_builder';
			$escaped_table_name = esc_sql($table_name);

			// Table name is safely escaped with esc_sql() - no user input values to prepare
			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
			$popups = $wpdb->get_results("SELECT * FROM `{$escaped_table_name}`", ARRAY_A);

			// Prepare export data
			$export_data = [
				'export_date' => current_time('mysql'),
				'site_url' => get_site_url(),
				'plugin_version' => INSTANT_POPUP_BUILDER_VERSION,
				'total_popups' => count($popups),
				'popups' => $popups
			];

			// Create filename with timestamp
			$filename = 'instant-popups-export-' . gmdate('Y-m-d-H-i-s') . '.json';
			$upload_dir = wp_upload_dir();
			$file_path = $upload_dir['path'] . '/' . $filename;

			// Write file
			if (file_put_contents($file_path, json_encode($export_data, JSON_PRETTY_PRINT))) {
				wp_send_json_success([
					'download_url' => $upload_dir['url'] . '/' . $filename,
					'filename' => $filename,
					'total_popups' => count($popups)
				]);
			} else {
				wp_send_json_error([
					'message' => 'Failed to create export file'
				]);
			}

		} catch (Exception $e) {
			wp_send_json_error([
				'message' => 'Export failed: ' . $e->getMessage()
			]);
		}
	}

	/**
	 * Create manual backup of popup data
	 *
	 * @since    1.0.62
	 */
	public function ipb_create_backup()
	{
		// Check nonce
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ipb_admin_nonce')) {
			wp_die('Security check failed');
		}

		if (!current_user_can('manage_options')) {
			wp_die('Insufficient permissions');
		}

		try {
			global $wpdb;
			$table_name = $wpdb->prefix . 'instant_popup_builder';
			$escaped_table_name = esc_sql($table_name);

			// Table name is safely escaped with esc_sql() - no user input values to prepare
			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
			$popups = $wpdb->get_results("SELECT * FROM `{$escaped_table_name}`", ARRAY_A);

			// Get plugin options
			$options = [
				'instant_popup_builder_db_active' => get_option('instant_popup_builder_db_active'),
				'instant_popup_builder_db_debug' => get_option('instant_popup_builder_db_debug'),
				'instant_popup_builder_preserve_analytics' => get_option('instant_popup_builder_preserve_analytics'),
				'instant_popup_builder_backup_before_delete' => get_option('instant_popup_builder_backup_before_delete'),
				'instant_popup_builder_confirm_deletion' => get_option('instant_popup_builder_confirm_deletion'),
				'instant_popup_builder_cleanup_options' => get_option('instant_popup_builder_cleanup_options'),
			];

			// Prepare backup data
			$backup_data = [
				'backup_date' => current_time('mysql'),
				'site_url' => get_site_url(),
				'plugin_version' => INSTANT_POPUP_BUILDER_VERSION,
				'total_popups' => count($popups),
				'popups' => $popups,
				'plugin_options' => $options,
				'backup_type' => 'manual'
			];

			// Create filename with timestamp
			$filename = 'instant-popups-backup-' . gmdate('Y-m-d-H-i-s') . '.json';
			$upload_dir = wp_upload_dir();
			$backup_dir = $upload_dir['basedir'] . '/instant-popup-backups';

			// Create backup directory if it doesn't exist
			if (!file_exists($backup_dir)) {
				wp_mkdir_p($backup_dir);
			}

			$file_path = $backup_dir . '/' . $filename;

			// Write backup file
			if (file_put_contents($file_path, json_encode($backup_data, JSON_PRETTY_PRINT))) {
				wp_send_json_success([
					'filename' => $filename,
					'file_path' => $file_path,
					'total_popups' => count($popups),
					'size' => size_format(filesize($file_path))
				]);
			} else {
				wp_send_json_error([
					'message' => 'Failed to create backup file'
				]);
			}

		} catch (Exception $e) {
			wp_send_json_error([
				'message' => 'Backup failed: ' . $e->getMessage()
			]);
		}
	}

	/**
	 * Preview what will be deleted on deactivation
	 *
	 * @since    1.0.62
	 */
	public function ipb_preview_deletion()
	{
		// Check nonce
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ipb_admin_nonce')) {
			wp_die('Security check failed');
		}

		if (!current_user_can('manage_options')) {
			wp_die('Insufficient permissions');
		}

		try {
			global $wpdb;
			$table_name = $wpdb->prefix . 'instant_popup_builder';
			$escaped_table_name = esc_sql($table_name);

			// Table name is safely escaped with esc_sql() - no user input values to prepare
			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
			$popup_count = $wpdb->get_var("SELECT COUNT(*) FROM `{$escaped_table_name}`");
			// LIMIT value is hardcoded constant (20), table name is safely escaped - no user input
			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
			$popups = $wpdb->get_results("SELECT id, popup_title FROM `{$escaped_table_name}` LIMIT 20", ARRAY_A);

			// Table name is safely escaped with esc_sql() - no user input values to prepare
			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
			$record_count = $wpdb->get_var("SELECT COUNT(*) FROM `{$escaped_table_name}`");

			// Get plugin options count
			$option_count = 0;
			$options_to_check = [
				'instant_popup_builder_db_active',
				'instant_popup_builder_db_debug',
				'instant_popup_builder_preserve_analytics',
				'instant_popup_builder_cleanup_options',
			];

			foreach ($options_to_check as $option) {
				if (get_option($option) !== false) {
					$option_count++;
				}
			}

			// Calculate approximate data size
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
			$size_query = $wpdb->prepare(
				"SELECT ROUND(((data_length + index_length) / 1024 / 1024), 2) AS size
				FROM information_schema.tables
				WHERE table_schema = %s AND table_name = %s",
				DB_NAME,
				$table_name
			);
			// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Query is prepared immediately above with fixed placeholders.
			$data_size = $wpdb->get_var($size_query);
			$data_size = $data_size ? $data_size . ' MB' : 'Unknown';

			// Format popup list
			$popup_list = array_map(function($popup) {
				return [
					'id' => $popup['id'],
					'title' => $popup['popup_title'] ?: 'Untitled Popup'
				];
			}, $popups);

			wp_send_json_success([
				'popup_count' => (int)$popup_count,
				'record_count' => (int)$record_count,
				'option_count' => (int)$option_count,
				'data_size' => $data_size,
				'popup_list' => $popup_list
			]);

		} catch (Exception $e) {
			wp_send_json_error([
				'message' => 'Preview failed: ' . $e->getMessage()
			]);
		}
	}

	/**
	 * Clear debug log file
	 *
	 * @since    1.0.62
	 */
	public function ipb_clear_debug_log()
	{
		wp_send_json_error([
			'message' => __('Clearing the global WordPress debug log is not supported by Instant Popup Builder.', 'instant-popup-builder'),
		], 410);
	}

	/**
	 * Download debug log file
	 *
	 * @since    1.0.62
	 */
	public function ipb_download_debug_log()
	{
		wp_send_json_error([
			'message' => __('Publishing the global WordPress debug log to the uploads directory is not supported.', 'instant-popup-builder'),
		], 410);
	}
	/**
	 * Save subscription settings via AJAX
	 *
	 * @since 1.0.0
	 */
	public function save_subscription_settings()
	{
		// Verify nonce for security
		if ( ! isset( $_POST['nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'subscription_settings_nonce' ) ) {
			wp_send_json_error('Security check failed');
			return;
		}

		// Check user capabilities
		if (!current_user_can('manage_options')) {
			wp_send_json_error('Insufficient permissions');
			return;
		}

		// Sanitize and collect settings
		$settings = array(
			'show_privacy'          => isset( $_POST['subscription_show_privacy'] ) ? sanitize_text_field( wp_unslash( $_POST['subscription_show_privacy'] ) ) : ( isset( $_POST['show_privacy'] ) ? sanitize_text_field( wp_unslash( $_POST['show_privacy'] ) ) : '' ),
			'privacy_link_type'     => $this->ipb_get_posted_subscription_setting('privacy_link_type'),
			'privacy_policy_url'    => $this->ipb_get_posted_subscription_setting('privacy_policy_url', '', 'esc_url_raw'),
			'privacy_policy_page'   => $this->ipb_get_posted_subscription_setting('privacy_policy_page'),
			'agreement_prefix_text' => $this->ipb_get_posted_subscription_setting('agreement_prefix_text', 'I agree to the'),
			'privacy_policy_label'  => $this->ipb_get_posted_subscription_setting('privacy_policy_label', 'Privacy Policy'),
			'privacy_policy_text'   => $this->ipb_get_posted_subscription_setting('privacy_policy_text'),
			'show_terms'            => isset( $_POST['subscription_show_terms'] ) ? sanitize_text_field( wp_unslash( $_POST['subscription_show_terms'] ) ) : ( isset( $_POST['show_terms'] ) ? sanitize_text_field( wp_unslash( $_POST['show_terms'] ) ) : '' ),
			'terms_link_type'       => $this->ipb_get_posted_subscription_setting('terms_link_type'),
			'terms_conditions_url'  => $this->ipb_get_posted_subscription_setting('terms_conditions_url', '', 'esc_url_raw'),
			'terms_conditions_page' => $this->ipb_get_posted_subscription_setting('terms_conditions_page'),
			'terms_conditions_label' => $this->ipb_get_posted_subscription_setting('terms_conditions_label', 'Terms and conditions'),
			'terms_conditions_text' => $this->ipb_get_posted_subscription_setting('terms_conditions_text'),
			'prevent_reshow'        => isset( $_POST['subscription_prevent_reshow'] ) ? sanitize_text_field( wp_unslash( $_POST['subscription_prevent_reshow'] ) ) : ( isset( $_POST['prevent_reshow'] ) ? sanitize_text_field( wp_unslash( $_POST['prevent_reshow'] ) ) : '' ),
			'email_verification'    => isset( $_POST['subscription_email_verification'] ) ? sanitize_text_field( wp_unslash( $_POST['subscription_email_verification'] ) ) : ( isset( $_POST['email_verification'] ) ? sanitize_text_field( wp_unslash( $_POST['email_verification'] ) ) : '' ),
			'success_message'       => $this->ipb_get_posted_subscription_message('subscription_success_message', 'success_message'),
			'error_message'         => $this->ipb_get_posted_subscription_message('subscription_error_message', 'error_message'),
			// Subscribe to Download settings
			'std_file_attachment_id' => isset( $_POST['std_file_attachment_id'] ) ? intval( $_POST['std_file_attachment_id'] ) : 0,
			'std_file_url'          => isset( $_POST['std_file_url'] ) ? esc_url_raw( wp_unslash( $_POST['std_file_url'] ) ) : '',
			'std_delivery_method'    => isset( $_POST['std_delivery_method'] ) ? sanitize_text_field( wp_unslash( $_POST['std_delivery_method'] ) ) : 'button',
			'std_thank_you_message'  => isset( $_POST['std_thank_you_message'] ) ? sanitize_textarea_field( wp_unslash( $_POST['std_thank_you_message'] ) ) : 'Thank you for Subscribing !',
			'std_download_button_text' => isset( $_POST['std_download_button_text'] ) ? sanitize_text_field( wp_unslash( $_POST['std_download_button_text'] ) ) : 'Click to download File',
			'std_file_encryption'    => isset( $_POST['std_file_encryption'] ) ? sanitize_text_field( wp_unslash( $_POST['std_file_encryption'] ) ) : '0',
		);
		
		/**
		 * Filter: Allow extensions to modify subscription settings before processing
		 * 
		 * @param array $settings Subscription settings array
		 * @param int $popup_id Popup ID (0 for global settings)
		 */
		$settings = apply_filters('ipb_subscription_settings_before_save', $settings, 0);
		
		// Process file from media library - copy to secure storage if needed (only if extension/license active)
		$std_plugin_active = is_plugin_active('instant-popup-subscribe-to-download/instant-popup-subscribe-to-download.php');
		$std_license_active = get_option('subscribe_to_download_license_active') === 'yes';
		$std_enabled = $std_plugin_active && $std_license_active;
		
		if ($std_enabled && !empty($settings['std_file_attachment_id']) && class_exists('Instant_Popup_Subscribe_To_Download_File_Storage_Handler')) {
			require_once WP_PLUGIN_DIR . '/instant-popup-subscribe-to-download/includes/class-file-storage-handler.php';
			
			$attachment_id = $settings['std_file_attachment_id'];
			$attachment_path = get_attached_file($attachment_id);
			
			if ($attachment_path && file_exists($attachment_path)) {
				// For global settings, we don't have a popup_id yet, so we'll store the attachment_id
				// It will be processed when popup is saved
				$settings['std_file_id'] = $attachment_id; // Store attachment ID for now
			}
		} else {
			// Remove STD settings if extension/license not active
			unset($settings['std_file_attachment_id']);
			unset($settings['std_file_url']);
			unset($settings['std_delivery_method']);
			unset($settings['std_thank_you_message']);
			unset($settings['std_download_button_text']);
			unset($settings['std_file_encryption']);
		}

		/**
		 * Filter: Allow extensions to modify subscription settings after processing (for global settings)
		 * 
		 * @param array $settings Subscription settings array
		 * @param int $popup_id Popup ID (0 for global settings)
		 */
		$settings = apply_filters('ipb_subscription_settings_after_save', $settings, 0);

		// Save settings to WordPress options
		$saved = update_option('instant_popup_subscription_settings', $settings);

		if ($saved) {
			wp_send_json_success('Settings saved successfully');
		} else {
			wp_send_json_error('Failed to save settings');
		}
	}

	/**
	 * Export subscribers from core so the feature is available with or without Subscription Pro.
	 *
	 * @return void
	 */
	public function ipb_handle_subscriber_export()
	{
		if (!is_admin() || !current_user_can('manage_options')) {
			return;
		}

		if (!isset($_GET['page']) || sanitize_key(wp_unslash($_GET['page'])) !== 'instant-subscriber-list') {
			return;
		}

		if (!isset($_GET['export-subscriber'])) {
			return;
		}

		$export_type = sanitize_key(wp_unslash($_GET['export-subscriber']));
		$subscriber_id = isset($_GET['id']) ? absint(wp_unslash($_GET['id'])) : 0;
		$nonce_action = $subscriber_id ? 'ipb_export_subscriber_' . $subscriber_id : 'ipb_export_subscribers';

		if (!isset($_GET['_wpnonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'])), $nonce_action)) {
			wp_die(esc_html__('Security check failed.', 'instant-popup-builder'));
		}

		global $wpdb;
		$subscriber_table = $wpdb->prefix . 'instant_popup_subscriber';
		$popup_table = $wpdb->prefix . 'instant_popup_builder';

		if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $subscriber_table)) !== $subscriber_table) {
			wp_die(esc_html__('Subscriber table was not found.', 'instant-popup-builder'));
		}

		$escaped_subscriber_table = esc_sql($subscriber_table);
		$escaped_popup_table = esc_sql($popup_table);
		$where = '';
		$query_values = array();

		if ($subscriber_id || $export_type === 'single') {
			if (!$subscriber_id) {
				wp_die(esc_html__('Invalid subscriber.', 'instant-popup-builder'));
			}
			$where = 'WHERE s.id = %d';
			$query_values[] = $subscriber_id;
		}

		$query = "
			SELECT s.id, s.firstname, s.lastname, s.emailaddress, s.campaign, p.title AS campaign_name, s.privacy, s.status, s.created
			FROM `{$escaped_subscriber_table}` s
			LEFT JOIN `{$escaped_popup_table}` p ON s.campaign = p.id AND p.type = 'subscription'
			{$where}
			ORDER BY s.created DESC
		";

		if (!empty($query_values)) {
			// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter -- Identifiers are escaped and the optional WHERE clause is a fixed string.
			$subscribers = $wpdb->get_results($wpdb->prepare($query, $query_values), ARRAY_A);
		} else {
			// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter -- Query contains only escaped internal table identifiers and fixed SQL.
			$subscribers = $wpdb->get_results($query, ARRAY_A);
		}

		$filename = $subscriber_id ? 'instant-popup-subscriber-' . $subscriber_id . '.csv' : 'instant-popup-subscribers-' . gmdate('Y-m-d') . '.csv';

		nocache_headers();
		header('Content-Type: text/csv; charset=utf-8');
		header('Content-Disposition: attachment; filename=' . $filename);

		$output = fopen('php://output', 'w');
		if (!$output) {
			exit;
		}

		fputcsv($output, array('ID', 'First Name', 'Last Name', 'Email', 'Campaign ID', 'Campaign Name', 'Privacy', 'Status', 'Date Subscribed'), ',', '"', '');

		foreach ($subscribers as $subscriber) {
			fputcsv($output, array(
				$subscriber['id'],
				$subscriber['firstname'],
				$subscriber['lastname'],
				$subscriber['emailaddress'],
				$subscriber['campaign'],
				$subscriber['campaign_name'],
				$subscriber['privacy'],
				$subscriber['status'],
				$subscriber['created'],
			), ',', '"', '');
		}

		exit;
	}

	/**
	 * Save subscription settings for a specific popup (editor context)
	 * Stores into wp_{prefix}instant_popup_subscription_settings per popup_id
	 * 
	 * @deprecated This function is kept for backward compatibility but is no longer called from the UI.
	 *             The main "Update" button now calls save_popup_subscription_settings() which properly
	 *             preserves all extension fields. This provides a better UX by using WordPress standard workflow.
	 */
	public function save_subscription_settings_for_popup() {
		// Verify nonce for security
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'subscription_settings_nonce' ) ) {
			wp_send_json_error('Security check failed');
			return;
		}

		// Check capability
		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error('Insufficient permissions');
			return;
		}

		$popup_id = isset($_POST['popup_id']) ? intval($_POST['popup_id']) : 0;
		if ( ! $popup_id ) {
			wp_send_json_error('Invalid popup ID');
			return;
		}

		// Collect settings (same keys as global)
		$settings = array(
			'show_privacy'          => isset( $_POST['subscription_show_privacy'] ) ? sanitize_text_field( wp_unslash( $_POST['subscription_show_privacy'] ) ) : ( isset( $_POST['show_privacy'] ) ? sanitize_text_field( wp_unslash( $_POST['show_privacy'] ) ) : '0' ),
			'privacy_link_type'     => $this->ipb_get_posted_subscription_setting('privacy_link_type', 'url'),
			'privacy_policy_url'    => $this->ipb_get_posted_subscription_setting('privacy_policy_url', '', 'esc_url_raw'),
			'privacy_policy_page'   => $this->ipb_get_posted_subscription_setting('privacy_policy_page'),
			'agreement_prefix_text' => $this->ipb_get_posted_subscription_setting('agreement_prefix_text', 'I agree to the'),
			'privacy_policy_label'  => $this->ipb_get_posted_subscription_setting('privacy_policy_label', 'Privacy Policy'),
			'privacy_policy_text'   => $this->ipb_get_posted_subscription_setting('privacy_policy_text', 'I agree to the Privacy Policy'),
			'show_terms'            => isset( $_POST['subscription_show_terms'] ) ? sanitize_text_field( wp_unslash( $_POST['subscription_show_terms'] ) ) : ( isset( $_POST['show_terms'] ) ? sanitize_text_field( wp_unslash( $_POST['show_terms'] ) ) : '0' ),
			'terms_link_type'       => $this->ipb_get_posted_subscription_setting('terms_link_type', 'url'),
			'terms_conditions_url'  => $this->ipb_get_posted_subscription_setting('terms_conditions_url', '', 'esc_url_raw'),
			'terms_conditions_page' => $this->ipb_get_posted_subscription_setting('terms_conditions_page'),
			'terms_conditions_label' => $this->ipb_get_posted_subscription_setting('terms_conditions_label', 'Terms and conditions'),
			'terms_conditions_text' => $this->ipb_get_posted_subscription_setting('terms_conditions_text', 'I agree to the Terms & Conditions'),
			'prevent_reshow'        => isset( $_POST['subscription_prevent_reshow'] ) ? sanitize_text_field( wp_unslash( $_POST['subscription_prevent_reshow'] ) ) : ( isset( $_POST['prevent_reshow'] ) ? sanitize_text_field( wp_unslash( $_POST['prevent_reshow'] ) ) : '0' ),
			'email_verification'    => isset( $_POST['subscription_email_verification'] ) ? sanitize_text_field( wp_unslash( $_POST['subscription_email_verification'] ) ) : ( isset( $_POST['email_verification'] ) ? sanitize_text_field( wp_unslash( $_POST['email_verification'] ) ) : '0' ),
			'success_message'       => $this->ipb_get_posted_subscription_message('subscription_success_message', 'success_message', 'Thank you for subscribing!'),
			'error_message'         => $this->ipb_get_posted_subscription_message('subscription_error_message', 'error_message', 'Something went wrong. Please try again.'),
			// Subscribe to Download settings
			'std_file_attachment_id' => isset( $_POST['std_file_attachment_id'] ) ? intval( $_POST['std_file_attachment_id'] ) : 0,
			'std_file_url'          => isset( $_POST['std_file_url'] ) ? esc_url_raw( wp_unslash( $_POST['std_file_url'] ) ) : '',
			'std_delivery_method'    => isset( $_POST['std_delivery_method'] ) ? sanitize_text_field( wp_unslash( $_POST['std_delivery_method'] ) ) : 'button',
			'std_thank_you_message'  => isset( $_POST['std_thank_you_message'] ) ? sanitize_textarea_field( wp_unslash( $_POST['std_thank_you_message'] ) ) : 'Thank you for Subscribing !',
			'std_download_button_text' => isset( $_POST['std_download_button_text'] ) ? sanitize_text_field( wp_unslash( $_POST['std_download_button_text'] ) ) : 'Click to download File',
			'std_file_encryption'    => isset( $_POST['std_file_encryption'] ) ? sanitize_text_field( wp_unslash( $_POST['std_file_encryption'] ) ) : '0',
		);
		
		/**
		 * Filter: Allow extensions to modify subscription settings before processing (for popup-specific settings)
		 * 
		 * @param array $settings Subscription settings array
		 * @param int $popup_id Popup ID
		 */
		$settings = apply_filters('ipb_subscription_settings_before_save', $settings, $popup_id);
		
		// Only process Subscribe to Download settings if extension is installed and license is active
		$std_plugin_active = is_plugin_active('instant-popup-subscribe-to-download/instant-popup-subscribe-to-download.php');
		$std_license_active = get_option('subscribe_to_download_license_active') === 'yes';
		$std_enabled = $std_plugin_active && $std_license_active;
		
		// If extension/license not active, remove STD settings and preserve existing ones
		if (!$std_enabled) {
			// Preserve existing settings from database for backward compatibility
			global $wpdb;
			$table_name = $wpdb->prefix . 'instant_popup_subscription_settings';
			
			if ($popup_id) {
				$existing_result = $wpdb->get_row($wpdb->prepare(
					"SELECT settings FROM $table_name WHERE popup_id = %d",
					$popup_id
				));
				
				if ($existing_result && !empty($existing_result->settings)) {
					$existing_settings = maybe_unserialize($existing_result->settings);
					// Preserve existing STD settings if they exist
					if (isset($existing_settings['std_file_id'])) {
						$settings['std_file_id'] = $existing_settings['std_file_id'];
					}
					if (isset($existing_settings['std_file_attachment_id'])) {
						$settings['std_file_attachment_id'] = $existing_settings['std_file_attachment_id'];
					}
					if (isset($existing_settings['std_file_url'])) {
						$settings['std_file_url'] = $existing_settings['std_file_url'];
					}
					if (isset($existing_settings['std_delivery_method'])) {
						$settings['std_delivery_method'] = $existing_settings['std_delivery_method'];
					}
					if (isset($existing_settings['std_thank_you_message'])) {
						$settings['std_thank_you_message'] = $existing_settings['std_thank_you_message'];
					}
					if (isset($existing_settings['std_download_button_text'])) {
						$settings['std_download_button_text'] = $existing_settings['std_download_button_text'];
					}
					if (isset($existing_settings['std_file_encryption'])) {
						$settings['std_file_encryption'] = $existing_settings['std_file_encryption'];
					}
				}
			}
			
			// Remove any NEW STD settings that were submitted (prevent orphaned data)
			// Only keep settings that already existed in database
			if (isset($_POST['std_file_attachment_id']) && !isset($settings['std_file_attachment_id'])) {
				unset($settings['std_file_attachment_id']);
			}
			if (isset($_POST['std_file_url']) && !isset($settings['std_file_url'])) {
				unset($settings['std_file_url']);
			}
			if (isset($_POST['std_delivery_method']) && !isset($settings['std_delivery_method'])) {
				unset($settings['std_delivery_method']);
			}
			if (isset($_POST['std_thank_you_message']) && !isset($settings['std_thank_you_message'])) {
				unset($settings['std_thank_you_message']);
			}
			if (isset($_POST['std_download_button_text']) && !isset($settings['std_download_button_text'])) {
				unset($settings['std_download_button_text']);
			}
			if (isset($_POST['std_file_encryption']) && !isset($settings['std_file_encryption'])) {
				unset($settings['std_file_encryption']);
			}
		}
		
		// Process file from media library - copy to secure storage if needed (only if extension/license active)
		// Skip if std_file_id is already set (processed by hook integration)
		if ($std_enabled && !empty($settings['std_file_attachment_id']) && empty($settings['std_file_id']) && class_exists('Instant_Popup_Subscribe_To_Download_File_Storage_Handler')) {
			require_once WP_PLUGIN_DIR . '/instant-popup-subscribe-to-download/includes/class-file-storage-handler.php';
			
			global $wpdb;
			
			$attachment_id = $settings['std_file_attachment_id'];
			$attachment_path = get_attached_file($attachment_id);
			
			if ($attachment_path && file_exists($attachment_path)) {
				// Check if file already exists in download_files table
				$file_table = $wpdb->prefix . 'instant_popup_download_files';
				$existing_file = $wpdb->get_row($wpdb->prepare(
					"SELECT id FROM $file_table WHERE popup_id = %d AND file_path LIKE %s",
					$popup_id,
					'%' . basename($attachment_path) . '%'
				));
				
				if (!$existing_file) {
					// Copy file to secure storage
					$upload_dir = Instant_Popup_Subscribe_To_Download_File_Storage_Handler::get_upload_dir();
					$file_info = pathinfo($attachment_path);
					$extension = isset($file_info['extension']) ? '.' . $file_info['extension'] : '';
					$secure_filename = wp_generate_password(32, false) . $extension;
					$secure_path = $upload_dir . '/' . $secure_filename;
					
					if (copy($attachment_path, $secure_path)) {
						$file_size = filesize($secure_path);
						$file_type = wp_check_filetype($secure_path);
						
						// Save to download_files table
						$file_data = array(
							'popup_id' => $popup_id,
							'file_name' => basename($attachment_path),
							'file_path' => $secure_path,
							'file_size' => $file_size,
							'file_type' => $file_type['type'],
							'storage_type' => 'local',
							'delivery_method' => $settings['std_delivery_method'],
							'created_at' => current_time('mysql'),
							'updated_at' => current_time('mysql')
						);
						
						$file_format = array('%d', '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%s');
						$wpdb->insert($file_table, $file_data, $file_format);
						$settings['std_file_id'] = $wpdb->insert_id;
					} else {
						// Fallback: use attachment ID directly
						$settings['std_file_id'] = $attachment_id;
					}
				} else {
					$settings['std_file_id'] = $existing_file->id;
				}
			}
		}
		
		/**
		 * Filter: Allow extensions to modify subscription settings after processing (for popup-specific settings)
		 * 
		 * @param array $settings Subscription settings array
		 * @param int $popup_id Popup ID
		 */
		$settings = apply_filters('ipb_subscription_settings_after_save', $settings, $popup_id);

		// Note: STD settings are already in $settings array from lines 2558-2563
		// They will be saved to database below unless extension/license is not active
		// (which is handled in the first block at lines 2571-2630)

		global $wpdb;
		$table_name = $wpdb->prefix . 'instant_popup_subscription_settings';

		$current_user = wp_get_current_user();
		$userID = $current_user ? intval($current_user->ID) : 0;

		// Upsert settings for popup_id
		// Try update first
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
		$updated = $wpdb->update(
			$table_name,
			array(
				'settings'   => maybe_serialize($settings),
				'updated_at' => current_time('mysql'),
			),
			array('popup_id' => $popup_id),
			array('%s','%s'),
			array('%d')
		);
		
		if ($updated === false || $updated === 0) {
			// Insert if not existing
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
			$inserted = $wpdb->insert(
				$table_name,
				array(
					'popup_id'   => $popup_id,
					'settings'   => maybe_serialize($settings),
					'created_by' => $userID,
					'created_at' => current_time('mysql'),
					'updated_at' => current_time('mysql'),
				),
				array('%d','%s','%d','%s','%s')
			);

			if ($inserted === false) {
				wp_send_json_error('Failed to save settings');
				return;
			}
		}

		wp_send_json_success('Settings saved successfully');
	}
	/**
	 * Get global subscription settings
	 *
	 * @since 1.0.0
	 * @return array
	 */
	public static function get_subscription_settings()
	{
		$defaults = array(
			'show_privacy' => '0',
			'privacy_link_type' => 'url',
			'privacy_policy_url' => '',
			'privacy_policy_page' => '',
			'agreement_prefix_text' => 'I agree to the',
			'privacy_policy_label' => 'Privacy Policy',
			'privacy_policy_text' => 'I agree to the Privacy Policy',
			'show_terms' => '0',
			'terms_link_type' => 'url',
			'terms_conditions_url' => '',
			'terms_conditions_page' => '',
			'terms_conditions_label' => 'Terms and conditions',
			'terms_conditions_text' => 'I agree to the Terms & Conditions',
			'prevent_reshow' => '0',
			'email_verification' => '0',
			'success_message' => 'Thank you for subscribing!',
			'error_message' => 'Something went wrong. Please try again.'
		);

		$settings = get_option('instant_popup_subscription_settings', array());
		return wp_parse_args($settings, $defaults);
	}
	/**
		 * AJAX handler for editing subscribers
		 */
		public function ipb_edit_subscriber_ajax() {
			if (!current_user_can('manage_options')) {
				wp_send_json_error('Insufficient permissions.', 403);
				return;
			}

			// Verify nonce
			if (!isset($_POST['ipb_subscriber_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['ipb_subscriber_nonce'])), 'ipb_subscriber_action')) {
				wp_send_json_error('Security verification failed. Please refresh the page and try again.');
				return;
			}

			// Sanitize and validate input data
			$subscriber_id = isset($_POST['sub_edit_id']) ? intval($_POST['sub_edit_id']) : 0;
			$email = isset($_POST['sub_emailaddress']) ? sanitize_email(wp_unslash($_POST['sub_emailaddress'])) : '';
			$firstname = isset($_POST['sub_firstname']) ? sanitize_text_field(wp_unslash($_POST['sub_firstname'])) : '';
			$lastname = isset($_POST['sub_lastname']) ? sanitize_text_field(wp_unslash($_POST['sub_lastname'])) : '';
			$campaign = isset($_POST['ipb_sub_campaign']) ? intval($_POST['ipb_sub_campaign']) : 0;
			$privacy = isset($_POST['popup_privacy_toggle']) ? sanitize_text_field(wp_unslash($_POST['popup_privacy_toggle'])) : 'yes';
			$status = isset($_POST['popup_status_toggle']) ? sanitize_text_field(wp_unslash($_POST['popup_status_toggle'])) : 'yes';

			// Validate required fields
			if ($subscriber_id <= 0) {
				wp_send_json_error('Invalid subscriber ID');
				return;
			}

			if (empty($email)) {
				wp_send_json_error('Email address is required');
				return;
			}

			if (!is_email($email)) {
				wp_send_json_error('Please enter a valid email address');
				return;
			}

			// Auto-generate names from email if both are missing
			if (empty($firstname) && empty($lastname)) {
				$email_parts = $this->extract_names_from_email($email);
				$firstname = $email_parts['first_name'];
				$lastname = $email_parts['last_name'];
			}

			// Handle default campaign assignment
			$campaign = $this->get_default_campaign_for_admin($campaign);

			global $wpdb;
			$table_name = $wpdb->prefix . 'instant_popup_subscriber';
			$escaped_table_name = esc_sql($table_name);

			try {
				// Check if subscriber exists
				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
				$existing_subscriber = $wpdb->get_row($wpdb->prepare(
					"SELECT * FROM `{$escaped_table_name}` WHERE id = %d",
					$subscriber_id
				));

				if (!$existing_subscriber) {
					wp_send_json_error('Subscriber not found');
					return;
				}

				// Check if email exists for other records (excluding current)
				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
				$existing_email = $wpdb->get_var($wpdb->prepare(
					"SELECT COUNT(*) FROM `{$escaped_table_name}` WHERE emailaddress = %s AND id != %d",
					$email, $subscriber_id
				));

				if ($existing_email > 0) {
					wp_send_json_error('This email address is already used by another subscriber');
					return;
				}

				$data = [
					'campaign' => intval($campaign),
					'emailaddress' => $email,
					'firstname' => $firstname,
					'lastname' => $lastname,
					'privacy' => $privacy,
					'status' => $status
				];

				$where = ['id' => $subscriber_id];
				$format = ['%d', '%s', '%s', '%s', '%s', '%s'];
				$where_format = ['%d'];

				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
				$result = $wpdb->update($table_name, $data, $where, $format, $where_format);

				if ($result === false) {
					wp_send_json_error('Failed to update subscriber. Please try again.');
					return;
				}

				wp_send_json_success('Subscriber updated successfully');

			} catch (Exception $e) {
				wp_send_json_error('An error occurred while updating the subscriber. Please try again.');
			}

		}
		/**
		 * AJAX handler for adding new subscriber via modal
		 */
		public function ipb_add_subscriber_ajax() {
			if (!current_user_can('manage_options')) {
				wp_send_json_error('Insufficient permissions.', 403);
				return;
			}

			// Verify nonce
			if (!isset($_POST['ipb_subscriber_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['ipb_subscriber_nonce'])), 'ipb_subscriber_action')) {
				wp_send_json_error('Security verification failed. Please refresh the page and try again.');
				return;
			}

			// Sanitize and validate input data
			$email = isset($_POST['email']) ? sanitize_email(wp_unslash($_POST['email'])) : '';
			$firstname = isset($_POST['firstname']) ? sanitize_text_field(wp_unslash($_POST['firstname'])) : '';
			$lastname = isset($_POST['lastname']) ? sanitize_text_field(wp_unslash($_POST['lastname'])) : '';
			// Accept both 'campaign' and 'ipb_sub_campaign' keys from different UIs
			$campaign = 0;
			if (isset($_POST['campaign'])) {
				$campaign = intval($_POST['campaign']);
			} elseif (isset($_POST['ipb_sub_campaign'])) {
				$campaign = intval($_POST['ipb_sub_campaign']);
			}
			$privacy = isset($_POST['privacy']) ? sanitize_text_field(wp_unslash($_POST['privacy'])) : 'yes';
			$status = isset($_POST['status']) ? sanitize_text_field(wp_unslash($_POST['status'])) : 'yes';

			// Validate required fields
			if (empty($email)) {
				wp_send_json_error('Email address is required');
				return;
			}

			if (!is_email($email)) {
				wp_send_json_error('Please enter a valid email address');
				return;
			}

			// Auto-generate names from email if both are missing
			if (empty($firstname) && empty($lastname)) {
				$email_parts = $this->extract_names_from_email($email);
				$firstname = $email_parts['first_name'];
				$lastname = $email_parts['last_name'];
			}

			// Handle campaign assignment without auto-creating defaults
			// If a valid subscription popup id is provided, use it; otherwise, use 'newsletter' sentinel for No Campaign
			$campaign_value = 'newsletter';
			if (!empty($campaign)) {
				global $wpdb;
				$table_popup = $wpdb->prefix . 'instant_popup_builder';
				$escaped_table_popup = esc_sql($table_popup);
				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
				$exists = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM `{$escaped_table_popup}` WHERE id = %d AND type = %s", intval($campaign), 'subscription'));
				if ($exists > 0) {
					$campaign_value = intval($campaign);
				}
			}

			global $wpdb;
			$table_name = $wpdb->prefix . 'instant_popup_subscriber';
			$escaped_table_name = esc_sql($table_name);

			try {
				// Check for duplicate email
				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
				$existing = $wpdb->get_var($wpdb->prepare(
					"SELECT COUNT(*) FROM `{$escaped_table_name}` WHERE emailaddress = %s",
					$email
				));

				if ($existing > 0) {
					wp_send_json_error('This email address is already subscribed');
					return;
				}

				$data = [
					'campaign' => (string) $campaign_value,
					'emailaddress' => $email,
					'firstname' => $firstname,
					'lastname' => $lastname,
					'privacy' => $privacy,
					'status' => $status,
					'created' => current_time('mysql')
				];

				$format = ['%d', '%s', '%s', '%s', '%s', '%s', '%s'];
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
				$result = $wpdb->insert($table_name, $data, $format);

				if ($result === false) {
					wp_send_json_error('Failed to add subscriber. Please try again.');
					return;
				}

				wp_send_json_success('Subscriber added successfully');

			} catch (Exception $e) {
				wp_send_json_error('An error occurred while adding the subscriber. Please try again.');
			}
		}
	private function extract_names_from_email($email)
		{
		// Validate email input
		if (is_null($email) || empty($email) || !is_string($email)) {
			return [
				'first_name' => 'Subscriber',
				'last_name' => ''
			];
	}

	// Get the username part of the email (before @)
	$safe_email = (string) ( $email ?? '' );
	$email_parts = explode('@', $safe_email);
		if (empty($email_parts) || !isset($email_parts[0])) {
				return [
					'first_name' => 'Subscriber',
					'last_name' => ''
				];
			}
			$username = isset($email_parts[0]) && is_string($email_parts[0]) ? strtolower($email_parts[0]) : '';

			// Validate username is not empty
			if (empty($username)) {
				return [
					'first_name' => 'Subscriber',
					'last_name' => ''
				];
			}

			// Remove common email suffixes and numbers
			$username = is_string($username) ? preg_replace('/[0-9]+$/', '', $username) : ''; // Remove trailing numbers
			$username = is_string($username) ? preg_replace('/\.(com|net|org|edu|gov|mil|biz|info|name|pro|aero|coop|museum)$/', '', $username) : ''; // Remove domain suffixes

			// Split by common separators - validate username is not empty before splitting
			if (empty($username)) {
				return [
					'first_name' => 'Subscriber',
					'last_name' => ''
				];
			}
			$name_parts = preg_split('/[._-]/', $username);

			$first_name = '';
			$last_name = '';

		if (count($name_parts) >= 2) {
			// We have at least two parts, use first as first name, rest as last name
			$first_name = isset($name_parts[0]) && is_string($name_parts[0]) ? ucfirst($name_parts[0]) : '';
			$last_name_parts = array_slice($name_parts, 1);
			$last_name = ucfirst(implode(' ', is_array($last_name_parts) ? $last_name_parts : []));
		} elseif (count($name_parts) == 1) {
				// Only one part, use as first name
				$first_name = isset($name_parts[0]) && is_string($name_parts[0]) ? ucfirst($name_parts[0]) : '';
				$last_name = '';
			} else {
				// Fallback
				$first_name = 'Subscriber';
				$last_name = '';
			}

	// Clean up names (remove special characters, limit length)
	$first_name = is_string($first_name) ? preg_replace('/[^a-zA-Z\s]/', '', $first_name) : '';
	$last_name = is_string($last_name) ? preg_replace('/[^a-zA-Z\s]/', '', $last_name) : '';

	// Ensure values are strings before passing to substr and trim
	$safe_first_name = (string) ( $first_name ?? '' );
	$safe_last_name = (string) ( $last_name ?? '' );
	$first_name = trim(substr($safe_first_name, 0, 50));
	$last_name = trim(substr($safe_last_name, 0, 50));

			return [
				'first_name' => $first_name,
				'last_name' => $last_name
			];
		}
	private function get_default_campaign_for_admin($campaign_id) {
		global $wpdb;
		$table_popup = $wpdb->prefix . 'instant_popup_builder';
		$escaped_table_popup = esc_sql($table_popup);

		// If campaign is provided, validate it exists
		if (!empty($campaign_id)) {
			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
			$campaign_exists = $wpdb->get_var($wpdb->prepare(
				"SELECT COUNT(*) FROM `{$escaped_table_popup}` WHERE id = %d AND type = %s",
				intval($campaign_id),
				'subscription'
			));

				if ($campaign_exists > 0) {
					return $campaign_id;
				}
			}

			// Get or create default campaign
			$default_campaign_id = $this->get_or_create_default_campaign();
			return $default_campaign_id;
		}
	private function get_or_create_default_campaign() {
		global $wpdb;
		$table_popup = $wpdb->prefix . 'instant_popup_builder';
		$escaped_table_popup = esc_sql($table_popup);

		// Try to find existing default campaign
		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$default_campaign = $wpdb->get_row($wpdb->prepare(
			"SELECT id FROM `{$escaped_table_popup}` WHERE type = %s AND title = %s",
			'subscription',
			'Default Newsletter'
		));

			if ($default_campaign) {
				return $default_campaign->id;
			}

		// Create default campaign if it doesn't exist
		$default_campaign_data = [
			'title' => 'Default Newsletter',
			'type' => 'subscription',
			'status' => 'publish',
			'date' => current_time('mysql')
		];

			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
			$result = $wpdb->insert($table_popup, $default_campaign_data);

			if ($result !== false) {
				return $wpdb->insert_id;
			}

			// Fallback to 'newsletter' string if table insert fails
			return 'newsletter';
		}
		/**
		 * Save subscription settings
		 */
	public function save_popup_subscription_settings($popup_id)
	{
		if (!$popup_id) {
			return;
		}

	// Security check - only for AJAX requests
	if (wp_doing_ajax() && (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'subscription_settings_nonce'))) {
		wp_send_json_error('Security check failed');
		return;
	}

		global $wpdb;
		$table_name = $wpdb->prefix . 'instant_popup_subscription_settings';

		// CRITICAL FIX: Retrieve EXISTING settings first to preserve extension fields (like STD fields)
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
		$existing_row = $wpdb->get_row($wpdb->prepare("SELECT settings FROM `" . esc_sql($table_name) . "` WHERE popup_id = %d", $popup_id));
		$existing_settings = array();
		if ($existing_row && !empty($existing_row->settings)) {
			$existing_settings = maybe_unserialize($existing_row->settings);
			if (!is_array($existing_settings)) {
				$existing_settings = array();
			}
		}

		// Collect & sanitize the BASIC settings (these will be updated)
		$basic_settings = array(
			'show_privacy'          => isset($_POST['subscription_show_privacy']) && $_POST['subscription_show_privacy'] == '1' ? '1' : '0',
			'privacy_link_type'     => $this->ipb_get_posted_subscription_setting('privacy_link_type', $existing_settings['privacy_link_type'] ?? 'url'),
			'privacy_policy_url'    => $this->ipb_get_posted_subscription_setting('privacy_policy_url', $existing_settings['privacy_policy_url'] ?? '', 'esc_url_raw'),
			'privacy_policy_page'   => $this->ipb_get_posted_subscription_setting('privacy_policy_page', $existing_settings['privacy_policy_page'] ?? ''),
			'agreement_prefix_text' => $this->ipb_get_posted_subscription_setting('agreement_prefix_text', $existing_settings['agreement_prefix_text'] ?? 'I agree to the'),
			'privacy_policy_label'  => $this->ipb_get_posted_subscription_setting('privacy_policy_label', $existing_settings['privacy_policy_label'] ?? 'Privacy Policy'),
			'privacy_policy_text'   => $this->ipb_get_posted_subscription_setting('privacy_policy_text', $existing_settings['privacy_policy_text'] ?? 'I agree to the Privacy Policy'),
			'show_terms'            => isset($_POST['subscription_show_terms']) && $_POST['subscription_show_terms'] == '1' ? '1' : '0',
			'terms_link_type'       => $this->ipb_get_posted_subscription_setting('terms_link_type', $existing_settings['terms_link_type'] ?? 'url'),
			'terms_conditions_url'  => $this->ipb_get_posted_subscription_setting('terms_conditions_url', $existing_settings['terms_conditions_url'] ?? '', 'esc_url_raw'),
			'terms_conditions_page' => $this->ipb_get_posted_subscription_setting('terms_conditions_page', $existing_settings['terms_conditions_page'] ?? ''),
			'terms_conditions_label' => $this->ipb_get_posted_subscription_setting('terms_conditions_label', $existing_settings['terms_conditions_label'] ?? 'Terms and conditions'),
			'terms_conditions_text' => $this->ipb_get_posted_subscription_setting('terms_conditions_text', $existing_settings['terms_conditions_text'] ?? 'I agree to the Terms & Conditions'),
			'prevent_reshow'        => isset($_POST['subscription_prevent_reshow']) && $_POST['subscription_prevent_reshow'] == '1' ? '1' : '0',
			'email_verification'    => isset($_POST['subscription_email_verification']) && $_POST['subscription_email_verification'] == '1' ? '1' : '0',
			'success_message'       => $this->ipb_get_posted_subscription_message('subscription_success_message', 'success_message'),
			'error_message'         => $this->ipb_get_posted_subscription_message('subscription_error_message', 'error_message'),
		);
		
		$extension_settings = array();
		$extension_field_sanitizers = array(
			'std_file_attachment_id'      => 'absint',
			'std_file_id'                 => 'absint',
			'std_file_url'                => 'esc_url_raw',
			'std_delivery_method'         => 'sanitize_text_field',
			'std_thank_you_message'       => 'sanitize_textarea_field',
			'std_download_button_text'    => 'sanitize_text_field',
			'std_file_encryption'         => 'sanitize_text_field',
		);

		foreach ($extension_field_sanitizers as $field => $sanitizer) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- The popup save nonce is verified at the beginning of this method.
			if (!isset($_POST[$field])) {
				continue;
			}

			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- The value is unslashed here and sanitized in the branches below.
			$value = wp_unslash($_POST[$field]);
			if (is_array($value)) {
				$extension_settings[$field] = map_deep($value, 'sanitize_text_field');
			} elseif (is_callable($sanitizer)) {
				$extension_settings[$field] = call_user_func($sanitizer, $value);
			}
		}

		// MERGE: Start with existing settings, then overlay core and submitted extension fields.
		$settings = array_merge($existing_settings, $basic_settings, $extension_settings);
		$settings = apply_filters('ipb_subscription_settings_before_save', $settings, $popup_id);
		$settings = apply_filters('ipb_subscription_settings_after_save', $settings, $popup_id);

		// Delete existing record for this popup (will be re-inserted with merged settings)
		$wpdb->delete($table_name, array('popup_id' => $popup_id), array('%d'));

		$current_user = wp_get_current_user();
		$userID = $current_user->ID;

		$insert_result = $wpdb->insert(
			$table_name,
			array(
				'popup_id'   => $popup_id,
				'settings'   => maybe_serialize($settings),
				'created_by' => $userID,
				'created_at' => current_time('mysql'),
				'updated_at' => current_time('mysql'),
			),
			array('%d','%s','%d','%s','%s')
		);
	}
}
