<?php
// phpcs:disable WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL,WordPress.NamingConventions.PrefixAllGlobals -- Subscription data uses plugin-owned tables and established public hooks.

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

$instant_popup_builder_active_license = get_option('subscription_license_active');
		$instant_popup_builder_active_plugin = get_option('instant_popup_subscription_activated');
        if($instant_popup_builder_active_license != 'yes' || $instant_popup_builder_active_plugin == 'no'){
/**
 * The public-facing functionality of the plugin.
 *
 * @link       https://www.example.com
 * @since      1.0.0
 *
 * @package    Instant_Popup_Subscription
 * @subpackage Instant_Popup_Subscription/public
 */

/**
 * The public-facing functionality of the plugin.
 *
 * Defines the plugin name, version, and two examples hooks for how to
 * enqueue the public-facing stylesheet and JavaScript.
 *
 * @package    Instant_Popup_Subscription
 * @subpackage Instant_Popup_Subscription/public
 * @author     7th Sky Software's <example123@gmail.com>
 */

	class Instant_Popup_Subscription_Public
	{

		/**
		 * The ID of this plugin.
		 *
		 * @since    1.0.0
		 * @access   private
		 * @var      string    $plugin_name    The ID of this plugin.
		 */
		private $plugin_name;

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

		/**
		 * Constructor
		 */
		public function __construct($plugin_name, $version)
		{
			$this->plugin_name = $plugin_name;
			$this->version = $version;
			//self::add_ipb_popup($this);

			// Add AJAX handlers
			add_action('wp_ajax_instant_popup_subscriber_ajax', [$this, 'instant_popup_save_subscribers']);
			add_action('wp_ajax_nopriv_instant_popup_subscriber_ajax', [$this, 'instant_popup_save_subscribers']);

			// Add unsubscribe AJAX handlers
			add_action('wp_ajax_instant_popup_unsubscribe_ajax', [$this, 'instant_popup_unsubscribe']);
			add_action('wp_ajax_nopriv_instant_popup_unsubscribe_ajax', [$this, 'instant_popup_unsubscribe']);

			// Add subscription check AJAX handlers
			add_action('wp_ajax_instant_popup_check_subscription', [$this, 'instant_popup_check_subscription']);
			add_action('wp_ajax_nopriv_instant_popup_check_subscription', [$this, 'instant_popup_check_subscription']);

			// Add email verification AJAX handlers
					add_action('wp_ajax_instant_popup_verify_email', [$this, 'instant_popup_verify_email']);
		add_action('wp_ajax_nopriv_instant_popup_verify_email', [$this, 'instant_popup_verify_email']);

		// Ajax call for subscriber db entries - should work regardless of license
		add_action( 'wp_ajax_instant_popup_save_subscribers', [$this, 'instant_popup_save_subscribers'] );
		add_action( 'wp_ajax_nopriv_instant_popup_save_subscribers', [$this, 'instant_popup_save_subscribers'] );

		// Add the correct action handler for save_subscribers (used by forms)
		add_action( 'wp_ajax_save_subscribers', [$this, 'instant_popup_save_subscribers'] );
		add_action( 'wp_ajax_nopriv_save_subscribers', [$this, 'instant_popup_save_subscribers'] );
		// Test verification email functionality removed for production

			// Add shortcodes
			add_shortcode('ipb_subscription', [$this, 'ipb_create_popup_subscription']);
			add_shortcode('ipb_unsubscribe', [$this, 'ipb_create_unsubscribe_form']);
			add_shortcode('ipb_unsubscribe_url', [$this, 'ipb_get_unsubscribe_url']);
			add_shortcode('ipb_verify_email', [$this, 'ipb_create_verification_form']);

			// Add unsubscribe page handler
			add_action('init', [$this, 'handle_unsubscribe_page']);

			// Debug handler removed for production

			// Add email verification page handler
			add_action('init', [$this, 'handle_email_verification_page']);
		}

		/**
		 * Create Shortcode for subscription popup
		 * @return string
		 */

		/**
		 * Register the stylesheets for the public-facing side of the site.
		 *
		 * @since    1.0.0
		 */
		public function enqueue_styles()
		{

			/**
			 * This function is provided for demonstration purposes only.
			 *
			 * An instance of this class should be passed to the run() function
			 * defined in Instant_Popup_Subscription_Extension_Loader as all of the hooks are defined
			 * in that particular class.
			 *
			 * The Instant_Popup_Subscription_Extension_Loader will then create the relationship
			 * between the defined hooks and the functions defined in this
			 * class.
			 */

			wp_enqueue_style($this->plugin_name, plugin_dir_url(__FILE__) . 'css/instant-popup-builder-public.css', array(), $this->version, 'all');
		}

		/**
		 * Register the JavaScript for the public-facing side of the site.
		 *
		 * @since    1.0.0
		 */
		public function subscription_enqueue_scripts()
		{

			/**
			 * This function is provided for demonstration purposes only.
			 *
			 * An instance of this class should be passed to the run() function
			 * defined in Instant_Popup_Subscription_Extension_Loader as all of the hooks are defined
			 * in that particular class.
			 *
			 * The Instant_Popup_Subscription_Extension_Loader will then create the relationship
			 * between the defined hooks and the functions defined in this
			 * class.
			 */

			//wp_enqueue_script($this->plugin_name, plugin_dir_url(__FILE__) . 'js/instant-popup-builder-public.js', array('jquery'), $this->version, false);

			// Localize script for AJAX - improved with nonce support
			wp_localize_script($this->plugin_name, 'instnat_ajax_subscriber', [
				'ajaxurl' => esc_url(admin_url('admin-ajax.php')),
				'ajax_url' => esc_url(admin_url('admin-ajax.php')), // Alternative naming for compatibility
				'nonce' => esc_js(wp_create_nonce('instant_popup_subscriber_ajax_action')),
				'subscription_check_nonce' => esc_js(wp_create_nonce('instant_popup_subscription_check')),
				'verification_nonce' => esc_js(wp_create_nonce('instant_popup_verification_action')),
				// Test verification nonce removed for production
			]);

			// Also add global ajaxurl for fallback
			wp_add_inline_script($this->plugin_name, 'var ajaxurl = "' . esc_url(admin_url('admin-ajax.php')) . '";', 'before');
		}

		/**
		 * Create text popup
		 * @return string
		*/
		public function ipb_create_popup_subscription()
		{

			return  include plugin_dir_path(__FILE__) . 'partials/shortcode-subscription.php';
		}

		/**
		 * Ajax call for save subscriber data
		 *
		 */
		public function instant_popup_save_subscribers()
		{

			// Verify nonce for security
			if (isset($_POST['instant_popup_subscriber_ajax']) && !empty($_POST['instant_popup_subscriber_ajax'])) {
				$nonce_valid = wp_verify_nonce(
					sanitize_text_field(wp_unslash($_POST['instant_popup_subscriber_ajax'])),
					'instant_popup_subscriber_ajax_action'
				);

				if (!$nonce_valid) {
					wp_send_json_error('Security verification failed. Please refresh the page and try again.');
					return;
				}
			} else {
				wp_send_json_error('Security token missing. Please refresh the page and try again.');
				return;
			}

			// Validate email address
			if (!isset($_POST['email_address']) || empty($_POST['email_address'])) {
				wp_send_json_error('Email address is required');
				return;
			}

			$email_address = sanitize_email(wp_unslash($_POST['email_address']));
			if (!is_email($email_address)) {
				wp_send_json_error('Please enter a valid email address');
				return;
			}

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

		if (!$this->subscriber_table_exists()) {
			wp_send_json_error('The subscriber database is not ready. Please ask an administrator to run the database repair tool.');
			return;
		}

		// Get form data
		$first_name = isset($_POST['first_name']) ? sanitize_text_field(wp_unslash($_POST['first_name'])) : '';
		$last_name = isset($_POST['last_name']) ? sanitize_text_field(wp_unslash($_POST['last_name'])) : '';
		$privacy_policy = isset($_POST['privacy_policy']) ? sanitize_text_field(wp_unslash($_POST['privacy_policy'])) : 'yes';
		$campaign = isset($_POST['campaign']) ? sanitize_text_field(wp_unslash($_POST['campaign'])) : '';

		// Auto-generate names from email if not provided
		if (empty($first_name) && empty($last_name)) {
			$email_parts = $this->extract_names_from_email($email_address);
			$first_name = $email_parts['first_name'];
			$last_name = $email_parts['last_name'];
		}

		// Handle default campaign if none provided or invalid
		$campaign = $this->get_default_campaign($campaign);

		// Check if already subscribed
		$existing_subscriber = $wpdb->get_var($wpdb->prepare(
			"SELECT COUNT(*) FROM `{$escaped_table_name}` WHERE emailaddress = %s",
			$email_address
		));

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

			// Check if email verification is enabled for this campaign
			$verification_enabled = $this->is_email_verification_enabled($campaign);

			if ($verification_enabled) {
				// Create unverified subscriber
				$verification_token = $this->generate_verification_token($email_address);

				$data = [
					'firstname' => $first_name,
					'lastname' => $last_name,
					'emailaddress' => $email_address,
					'privacy' => $privacy_policy,
					'campaign' => $campaign,
					'status' => 'pending', // Pending verification
					'verification_token' => $verification_token,
					'verification_expires' => gmdate('Y-m-d H:i:s', strtotime('+24 hours'))
				];
				$format = ['%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'];

				// Insert into database
				$result = $wpdb->insert($table_name, $data, $format);

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

				// Send verification email
				$email_sent = $this->send_verification_email($email_address, $first_name, $campaign, $verification_token);

				if ($email_sent) {
					wp_send_json_success('Please check your email to verify your subscription. We\'ve sent you a verification link.');
				} else {
					// If email failed to send, we should still save the subscriber but inform them

					// Generate manual verification link as fallback
					$manual_verification_link = $this->generate_verification_link($email_address, $verification_token);

					wp_send_json_success('Your subscription has been saved, but we encountered an issue sending the verification email. Please use this link to verify your email: ' . $manual_verification_link);
				}
			} else {
				// Direct subscription without verification
				$data = [
					'firstname' => $first_name,
					'lastname' => $last_name,
					'emailaddress' => $email_address,
					'privacy' => $privacy_policy,
					'campaign' => $campaign,
					'status' => 'yes'
				];
				$format = ['%s', '%s', '%s', '%s', '%s', '%s'];

				// Insert into database
				$result = $wpdb->insert($table_name, $data, $format);

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

				// Trigger autoresponder emails
				$this->trigger_autoresponder_emails($campaign, $email_address);

				// Premium extensions may synchronize the new subscriber.
				do_action('ipb_subscription_subscriber_created', $email_address, $first_name, $last_name);

				// Get subscription settings for success message
				$subscription_settings = $this->get_subscription_settings();
				$success_message = isset($subscription_settings['success_message']) && !empty($subscription_settings['success_message'])
					? $subscription_settings['success_message']
					: 'Thank you for subscribing! You have been successfully added to our newsletter.';

				wp_send_json_success($success_message);
			}
		}

		/**
		 * Check whether the subscriber table is available.
		 */
		private function subscriber_table_exists()
		{
			global $wpdb;
			$table_name = $wpdb->prefix . 'instant_popup_subscriber';

			return $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_name)) === $table_name;
		}

		/**
		 * Extract first and last name from email address
		 *
		 * @param string $email Email address
		 * @return array Array with 'first_name' and 'last_name' keys
		 */
		/**
	 * Extract first and last name from email address
	 *
	 * Attempts to parse names from email username by splitting on common separators.
	 * Falls back to 'Subscriber' if parsing fails.
	 *
	 * @since    1.0.0
	 * @param    string    $email    Email address to parse
	 * @return   array    Array with 'first_name' and 'last_name' keys
	 */
	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 @)
		$email_parts = explode('@', ipb_string($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) : '';

			$first_name = trim(substr($first_name, 0, 50));
			$last_name = trim(substr($last_name, 0, 50));

			return [
				'first_name' => $first_name,
				'last_name' => $last_name
			];
		}

		/**
		 * Get default campaign or validate existing campaign
		 *
		 * @param string $campaign Campaign ID or name
		 * @return string Valid campaign ID
		 */
	private function get_default_campaign($campaign)
	{
		global $wpdb;
		$table_popup = $wpdb->prefix . 'instant_popup_builder';
		$escaped_table_popup = esc_sql($table_popup);

		// If campaign is provided, validate it exists and return it; otherwise use 'newsletter' (No Campaign)
		if (!empty($campaign)) {
			$campaign_exists = $wpdb->get_var($wpdb->prepare(
				"SELECT COUNT(*) FROM `{$escaped_table_popup}` WHERE id = %d AND type = %s",
				intval($campaign),
				'subscription'
			));
				if ($campaign_exists > 0) {
					return $campaign;
				}
			}
			return 'newsletter';
		}

		/**
		 * Get or create a default campaign
		 *
		 * @return string Default campaign ID
		 */
		// Remove default campaign auto-creation; rely on 'newsletter' sentinel instead

		/**
		 * Trigger autoresponder emails for a new subscriber.
		 *
		 * @param string $campaign_id The ID of the campaign to which the subscriber belongs.
		 * @param string $email_address The email address of the new subscriber.
		 */
		private function trigger_autoresponder_emails($campaign_id, $email_address)
		{
			// Get active autoresponders for this campaign
		global $wpdb;
		$autoresponders_table = $wpdb->prefix . 'instant_popup_autoresponders';
		$escaped_autoresponders_table = esc_sql($autoresponders_table);

		// Check if autoresponders table exists
		$table_exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $autoresponders_table));
		if (!$table_exists) {
			return; // No autoresponders table, skip
		}

		// Get active autoresponders for this campaign
		$autoresponders = $wpdb->get_results($wpdb->prepare("
			SELECT * FROM `{$escaped_autoresponders_table}`
			WHERE campaign_ids LIKE %s
			AND status = 'active'
		", '%' . $campaign_id . '%'));

			if (empty($autoresponders)) {
				return; // No active autoresponders for this campaign
			}

			foreach ($autoresponders as $autoresponder) {
				$campaign_ids = json_decode($autoresponder->campaign_ids, true);
				$trigger_rules = json_decode($autoresponder->trigger_rules, true);

				// Check if this campaign is associated with this autoresponder
				if (in_array($campaign_id, $campaign_ids)) {
					// Check if this autoresponder should trigger on subscription
					if (in_array('on_successful_subscription', $trigger_rules)) {
						$this->send_autoresponder_email($autoresponder, $email_address);
					}
				}
			}
		}

		/**
		 * Send autoresponder email
		 *
		 * @param object $autoresponder The autoresponder object
		 * @param string $subscriber_email The subscriber's email address
		 */
		private function send_autoresponder_email($autoresponder, $subscriber_email) {
			// Get email template if specified
			$email_content = 'Thank you for subscribing!'; // Default content

		if ($autoresponder->template_id > 0) {
			global $wpdb;
			$templates_table = $wpdb->prefix . 'instant_popup_templates';
			$escaped_templates_table = esc_sql($templates_table);
			$template = $wpdb->get_row($wpdb->prepare(
				"SELECT content FROM `{$escaped_templates_table}` WHERE id = %d",
				$autoresponder->template_id
			));

				if ($template && !empty($template->content)) {
					$email_content = $template->content;
				}
			}

			// Prepare email headers
			$headers = [];
			$headers[] = 'Content-Type: text/html; charset=UTF-8';
			$headers[] = 'From: ' . $autoresponder->sender_name . ' <' . $autoresponder->sender_email . '>';

			if (!empty($autoresponder->reply_to_email) && !$autoresponder->disable_reply) {
				$headers[] = 'Reply-To: ' . $autoresponder->reply_to_email;
			} elseif ($autoresponder->disable_reply) {
				$parsed_url = wp_parse_url(home_url());
				$host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
				$headers[] = 'Reply-To: noreply@' . $host;
			}

			// Send email
			$subject = $autoresponder->title;
			$sent = wp_mail($subscriber_email, $subject, $email_content, $headers);

			// Autoresponder email sent
		}

		/**
		 * Create email verification form shortcode
		 *
		 * @param array $atts Shortcode attributes
		 * @return string
		 */
		public function ipb_create_verification_form($atts = [])
		{
			// Parse shortcode attributes
			$atts = shortcode_atts([
				'email' => '',
				'token' => '',
				'success_message' => 'Email verified successfully! You are now subscribed to our newsletter.',
				'error_message' => 'Verification failed. Please check your email for a new verification link.',
				'expired_message' => 'Verification link has expired. Please subscribe again.',
				'button_text' => 'Verify Email',
				'loading_text' => 'Verifying...',
				'class' => 'ipb-verification-form'
			], $atts, 'ipb_verify_email');

			// Get email and token from URL if not provided
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters used for display purposes only, values are sanitized
			$email = !empty($atts['email']) ? $atts['email'] : (isset($_GET['email']) ? sanitize_email(wp_unslash($_GET['email'])) : '');
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters used for display purposes only, values are sanitized
			$token = !empty($atts['token']) ? $atts['token'] : (isset($_GET['token']) ? sanitize_text_field(wp_unslash($_GET['token'])) : '');

			ob_start();
			?>
			<div class="<?php echo esc_attr($atts['class']); ?>">
				<div class="ipb-verification-container">
					<h2>Verify Your Email Address</h2>

					<div id="ipb-verification-message" class="ipb-message" style="display: none;"></div>

					<?php if (!empty($email) && !empty($token)): ?>
						<div class="ipb-verification-info">
							<p>Please click the button below to verify your email address: <strong><?php echo esc_html($email ?? ''); ?></strong></p>
						</div>

						<form id="ipb-verification-form" method="post">
							<input type="hidden" name="email" value="<?php echo esc_attr($email ?? ''); ?>">
							<input type="hidden" name="token" value="<?php echo esc_attr($token ?? ''); ?>">

							<div class="ipb-form-actions">
								<button type="submit" class="ipb-btn ipb-btn-primary">
									<span class="btn-text"><?php echo esc_html($atts['button_text']); ?></span>
									<span class="btn-loading" style="display: none;">
										<i class="fa-solid fa-spinner fa-spin"></i>
										<?php echo esc_html($atts['loading_text']); ?>
									</span>
								</button>
							</div>
						</form>
					<?php else: ?>
						<div class="ipb-verification-error">
							<p>Invalid verification link. Please check your email for the correct verification link.</p>
						</div>
					<?php endif; ?>
				</div>
			</div>

			<style>
			.ipb-verification-form {
				max-width: 500px;
				margin: 50px auto;
				padding: 30px;
				background: #fff;
				border-radius: 8px;
				box-shadow: 0 2px 10px rgba(0,0,0,0.1);
			}

			.ipb-verification-container h2 {
				text-align: center;
				color: #2c3e50;
				margin-bottom: 20px;
			}

			.ipb-verification-info {
				text-align: center;
				margin-bottom: 30px;
				padding: 20px;
				background: #f8f9fa;
				border-radius: 5px;
			}

			.ipb-verification-error {
				text-align: center;
				padding: 20px;
				background: #f8d7da;
				border: 1px solid #f5c6cb;
				border-radius: 5px;
				color: #721c24;
			}

			.ipb-message {
				padding: 15px;
				margin-bottom: 20px;
				border-radius: 5px;
				text-align: center;
			}

			.ipb-message.ipb-success {
				background: #d4edda;
				border: 1px solid #c3e6cb;
				color: #155724;
			}

			.ipb-message.ipb-error {
				background: #f8d7da;
				border: 1px solid #f5c6cb;
				color: #721c24;
			}

			.ipb-btn {
				padding: 12px 30px;
				border: none;
				border-radius: 5px;
				cursor: pointer;
				font-size: 16px;
				font-weight: bold;
				transition: all 0.3s ease;
			}

			.ipb-btn-primary {
				background: #007cba;
				color: white;
			}

			.ipb-btn-primary:hover {
				background: #005a87;
			}

			.ipb-btn:disabled {
				opacity: 0.6;
				cursor: not-allowed;
			}
			</style>

			<script>
			jQuery(document).ready(function($) {
				$('#ipb-verification-form').on('submit', function(e) {
					e.preventDefault();

					var $form = $(this);
					var $btn = $form.find('button[type="submit"]');
					var $btnText = $btn.find('.btn-text');
					var $btnLoading = $btn.find('.btn-loading');
					var $message = $('#ipb-verification-message');

					// Show loading state
					$btn.prop('disabled', true);
					$btnText.hide();
					$btnLoading.show();
					$message.hide();

					// Send AJAX request
					$.ajax({
						url: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
						type: 'POST',
						data: {
							action: 'instant_popup_verify_email',
							email: $form.find('input[name="email"]').val(),
							token: $form.find('input[name="token"]').val(),
							nonce: '<?php echo esc_js(wp_create_nonce('instant_popup_verification_action')); ?>'
						},
						success: function(response) {
							if (response.success) {
								showMessage('<?php echo esc_js($atts['success_message']); ?>', 'success');
								$form.hide();
							} else {
								showMessage(response.data || '<?php echo esc_js($atts['error_message']); ?>', 'error');
							}
						},
						error: function() {
							showMessage('<?php echo esc_js($atts['error_message']); ?>', 'error');
						},
						complete: function() {
							// Reset button state
							$btn.prop('disabled', false);
							$btnText.show();
							$btnLoading.hide();
						}
					});
				});

				function showMessage(message, type) {
					var $message = $('#ipb-verification-message');
					$message.removeClass('ipb-success ipb-error').addClass('ipb-' + type);
					$message.html(message).show();

					// Scroll to message
					$('html, body').animate({
						scrollTop: $message.offset().top - 50
					}, 500);
				}
			});
			</script>
			<?php
			return ob_get_clean();
		}

		/**
		 * Create unsubscribe form shortcode
		 */
		public function ipb_create_unsubscribe_form($atts = [])
		{
			// Parse shortcode attributes
			$atts = shortcode_atts([
				'title' => 'Unsubscribe from Newsletter',
				'description' => 'Enter your email address to unsubscribe from our newsletter.',
				'button_text' => 'Unsubscribe',
				'confirmation_text' => 'Are you sure you want to unsubscribe?',
				'success_message' => 'You have been successfully unsubscribed.',
				'not_found_message' => 'Email address not found in our subscriber list.',
				'style' => 'default', // default, minimal, modern
				'email' => '', // Encrypted email from URL parameter
				'campaign' => '' // Campaign ID from URL parameter
			], $atts, 'ipb_unsubscribe');

			// Decrypt email if provided
			$prefilled_email = '';
			if (!empty($atts['email'])) {
				$decrypted_email = $this->decrypt_email($atts['email']);
				if ($decrypted_email) {
					$prefilled_email = esc_attr($decrypted_email);
				}
			}

			// Start output buffering
			ob_start();
			?>
			<div class="ipb-unsubscribe-form ipb-style-<?php echo esc_attr($atts['style']); ?>">
				<div class="ipb-unsubscribe-header">
					<h3><?php echo esc_html($atts['title']); ?></h3>
					<p><?php echo esc_html($atts['description']); ?></p>
				</div>

				<form id="ipb-unsubscribe-form" class="ipb-form">
					<?php wp_nonce_field('ipb_unsubscribe_action', 'ipb_unsubscribe_nonce'); ?>

					<div class="ipb-form-group">
						<label for="ipb_unsubscribe_email">Email Address <span class="required">*</span></label>
						<input type="email" id="ipb_unsubscribe_email" name="email_address"
							   value="<?php echo esc_attr($prefilled_email); ?>"
							   placeholder="Enter your email address" required>
					</div>

					<div class="ipb-form-group">
						<label class="ipb-checkbox-label">
							<input type="checkbox" id="ipb_confirm_unsubscribe" name="confirm_unsubscribe" required>
							<span class="checkmark"></span>
							<?php echo esc_html($atts['confirmation_text']); ?>
						</label>
					</div>

					<div class="ipb-form-group">
						<button type="submit" class="ipb-unsubscribe-btn">
							<span class="btn-text"><?php echo esc_html($atts['button_text']); ?></span>
							<span class="btn-loading" style="display: none;">
								<span class="spinner"></span> Processing...
							</span>
						</button>
					</div>

					<div id="ipb-unsubscribe-message" class="ipb-message" style="display: none;"></div>
				</form>
			</div>

			<script type="text/javascript">
			jQuery(document).ready(function($) {
				$('#ipb-unsubscribe-form').on('submit', function(e) {
					e.preventDefault();

					var $form = $(this);
					var $btn = $form.find('.ipb-unsubscribe-btn');
					var $btnText = $btn.find('.btn-text');
					var $btnLoading = $btn.find('.btn-loading');
					var $message = $('#ipb-unsubscribe-message');

					// Get form data
					var email = $('#ipb_unsubscribe_email').val();
					var confirmUnsubscribe = $('#ipb_confirm_unsubscribe').is(':checked');
					var nonce = $('#ipb_unsubscribe_nonce').val();

					// Validation
					if (!email) {
						showMessage('Please enter your email address.', 'error');
						return;
					}

					if (!confirmUnsubscribe) {
						showMessage('Please confirm that you want to unsubscribe.', 'error');
						return;
					}

					// Show loading state
					$btn.prop('disabled', true);
					$btnText.hide();
					$btnLoading.show();
					$message.hide();

					// Send AJAX request
					$.ajax({
						url: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
						type: 'POST',
						data: {
							action: 'instant_popup_unsubscribe_ajax',
							email_address: email,
							confirm_unsubscribe: confirmUnsubscribe,
							ipb_unsubscribe_nonce: nonce
						},
						success: function(response) {
							if (response.success) {
								showMessage('<?php echo esc_js($atts['success_message']); ?>', 'success');
								$form[0].reset();
							} else {
								showMessage(response.data || 'An error occurred. Please try again.', 'error');
							}
						},
						error: function() {
							showMessage('An error occurred. Please try again.', 'error');
						},
						complete: function() {
							// Reset button state
							$btn.prop('disabled', false);
							$btnText.show();
							$btnLoading.hide();
						}
					});
				});

				function showMessage(message, type) {
					var $message = $('#ipb-unsubscribe-message');
					$message.removeClass('ipb-success ipb-error').addClass('ipb-' + type);
					$message.html(message).show();

					// Scroll to message
					$('html, body').animate({
						scrollTop: $message.offset().top - 50
					}, 500);
				}
			});
			</script>
			<?php
			return ob_get_clean();
		}

		/**
		 * AJAX handler for unsubscribe
		 */
		public function instant_popup_unsubscribe()
		{
			// Verify nonce for security
			if (isset($_POST['ipb_unsubscribe_nonce']) && !empty($_POST['ipb_unsubscribe_nonce'])) {
				$nonce_valid = wp_verify_nonce(
					sanitize_text_field(wp_unslash($_POST['ipb_unsubscribe_nonce'])),
					'ipb_unsubscribe_action'
				);

				if (!$nonce_valid) {
					wp_send_json_error('Security verification failed. Please refresh the page and try again.');
					return;
				}
			} else {
				wp_send_json_error('Security token missing. Please refresh the page and try again.');
				return;
			}

			// Validate email address
			if (!isset($_POST['email_address']) || empty($_POST['email_address'])) {
				wp_send_json_error('Email address is required');
				return;
			}

			$email_address = sanitize_email(wp_unslash($_POST['email_address']));
			if (!is_email($email_address)) {
				wp_send_json_error('Please enter a valid email address');
				return;
			}

			// Check confirmation
			if (!isset($_POST['confirm_unsubscribe']) || $_POST['confirm_unsubscribe'] !== 'true') {
				wp_send_json_error('Please confirm that you want to unsubscribe');
				return;
			}

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

		// Check if subscriber exists
		$subscriber = $wpdb->get_row($wpdb->prepare(
			"SELECT * FROM `{$escaped_table_name}` WHERE emailaddress = %s",
			$email_address
		));

			if (!$subscriber) {
				wp_send_json_error('Email address not found in our subscriber list');
				return;
			}

			// Check if already unsubscribed
			if ($subscriber->status === 'no') {
				wp_send_json_error('This email address is already unsubscribed');
				return;
			}

			// Update subscriber status to unsubscribed
			$result = $wpdb->update(
				$table_name,
				['status' => 'no'],
				['emailaddress' => $email_address],
				['%s'],
				['%s']
			);

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

			// Subscriber unsubscribed

			wp_send_json_success('You have been successfully unsubscribed from our newsletter.');
		}

		/**
		 * Handle unified unsubscribe page system
		 * Supports both legacy and new unified unsubscribe URLs
		 */
		public function handle_unsubscribe_page()
		{
			// Check if this is an unsubscribe page request (legacy support)
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter used for routing/display purposes only, value is sanitized
			$unsubscribe_route = isset($_GET['unsubscribe']) ? sanitize_text_field(wp_unslash($_GET['unsubscribe'])) : '';
			if ($unsubscribe_route === 'true') {
				$this->process_unsubscribe_request();
				return;
			}

		// Check if this is a unified unsubscribe page request
		$current_url = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '';
		$unsubscribe_page_url = get_option('ipb_unsubscribe_page_url', '/unsubscribe/');

		// Normalize strings for PHP 8.1+ compatibility
		$safe_current_url = (string) ( $current_url ?? '' );
		$safe_unsubscribe_url = (string) ( $unsubscribe_page_url ?? '/unsubscribe/' );

		// Handle unified unsubscribe URLs
		if (strpos($safe_current_url, $safe_unsubscribe_url) !== false ||
			strpos($safe_current_url, '/unsubscribe/') !== false) {
			$this->process_unsubscribe_request();
		}
		}

		/**
		 * Debug method removed for production
		 * This method was used for testing unsubscribe functionality
		 */

		/**
		 * Process unsubscribe request and display form
		 */
		private function process_unsubscribe_request()
		{
			// Set page title
			add_filter('wp_title', function($title) {
				return 'Unsubscribe - ' . esc_js(get_bloginfo('name'));
			});

			// Add body class
			add_filter('body_class', function($classes) {
				$classes[] = 'ipb-unsubscribe-page';
				return $classes;
			});

			// Add content filter to show unsubscribe form
			add_filter('the_content', function($content) {
				// Always show unsubscribe form for unsubscribe requests
				$request_args = $this->get_sanitized_unsubscribe_request_params();

				// Security: never pass request-derived data through do_shortcode().
				return $this->render_unsubscribe_form_from_request($request_args);
			});

		// Also add a template redirect for direct URL access
		add_action('template_redirect', function() {
			$current_url = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '';
			$unsubscribe_page_url = get_option('ipb_unsubscribe_page_url', '/unsubscribe/');

			// Normalize strings for PHP 8.1+ compatibility
			$safe_current_url = (string) ( $current_url ?? '' );
			$safe_unsubscribe_url = (string) ( $unsubscribe_page_url ?? '/unsubscribe/' );

			// Check if this is a direct unsubscribe URL access
			if (strpos($safe_current_url, $safe_unsubscribe_url) !== false ||
				strpos($safe_current_url, '/unsubscribe/') !== false) {
					$request_args = $this->get_sanitized_unsubscribe_request_params();

					// Display the unsubscribe form directly
					$this->display_unsubscribe_page($request_args);
					exit;
				}
			});
		}

		/**
		 * Display unsubscribe page with form
		 */
		private function display_unsubscribe_page($request_args = [])
		{
			?>
			<!DOCTYPE html>
			<html <?php language_attributes(); ?>>
			<head>
				<meta charset="<?php bloginfo('charset'); ?>">
				<meta name="viewport" content="width=device-width, initial-scale=1">
				<title><?php echo 'Unsubscribe - ' . esc_js(get_bloginfo('name')); ?></title>
				<?php wp_head(); ?>
			</head>
			<body class="ipb-unsubscribe-page">
			<div class="ipb-unsubscribe-container">
				<div class="ipb-unsubscribe-content">
					<?php
					// Security: render directly instead of executing shortcodes from request input.
					$unsubscribe_markup = $this->render_unsubscribe_form_from_request( (array) $request_args );
					echo wp_kses( $unsubscribe_markup, $this->get_allowed_html_unsubscribe_form_output() );
					?>
				</div>
				</div>
				<?php wp_footer(); ?>
			</body>
			</html>
			<?php
		}

		/**
		 * Get unified unsubscribe URL shortcode
		 * Returns the unique unsubscribe URL for this website
		 *
		 * @param array $atts Shortcode attributes
		 * @return string The unsubscribe URL
		 */
		public function ipb_get_unsubscribe_url($atts = [])
		{
			// Parse shortcode attributes
			$atts = shortcode_atts([
				'email' => '', // Optional email to pre-fill
				'campaign' => '', // Optional campaign ID
				'text' => 'Unsubscribe', // Link text
				'class' => 'ipb-unsubscribe-link' // CSS class
			], $atts, 'ipb_unsubscribe_url');

			// Get the unified unsubscribe URL
			$unsubscribe_url = $this->get_unified_unsubscribe_url();

			// Add email parameter if provided
			if (!empty($atts['email'])) {
				$encrypted_email = $this->encrypt_email($atts['email']);
				$unsubscribe_url .= '?email=' . urlencode($encrypted_email);

				// Add campaign parameter if provided
				if (!empty($atts['campaign'])) {
					$unsubscribe_url .= '&campaign=' . urlencode($atts['campaign']);
				}
			}

			// Return as link or just URL based on text attribute
			if (!empty($atts['text'])) {
				return '<a href="' . esc_url($unsubscribe_url) . '" class="' . esc_attr($atts['class']) . '">' . esc_html($atts['text']) . '</a>';
			}

			return esc_url($unsubscribe_url);
		}

		/**
		 * Get unified unsubscribe URL for this website
		 *
		 * @return string The unified unsubscribe URL
		 */
		private function get_unified_unsubscribe_url() {
			// Check if custom unsubscribe page exists
			$unsubscribe_page = get_option('ipb_unsubscribe_page_url', '');

			if (!empty($unsubscribe_page)) {
				return home_url($unsubscribe_page);
			}

			// Default unified unsubscribe URL
			return home_url('/unsubscribe/');
		}

		/**
		 * Encrypt email address for security
		 *
		 * @param string $email The email address to encrypt
		 * @return string The encrypted email
		 */
		private function encrypt_email($email) {
			$key = wp_salt('auth');
			$method = 'AES-256-CBC';
			$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($method));

			$encrypted = openssl_encrypt($email, $method, $key, 0, $iv);
			return base64_encode($iv . $encrypted);
		}

		/**
		 * Decrypt email address
		 *
		 * @param string $encrypted_email The encrypted email
		 * @return string|false The decrypted email or false on failure
		 */
		private function decrypt_email($encrypted_email) {
			$key = wp_salt('auth');
			$method = 'AES-256-CBC';

			$data = base64_decode($encrypted_email);
			$iv_length = openssl_cipher_iv_length($method);
			$iv = substr($data, 0, $iv_length);
			$encrypted = substr($data, $iv_length);

			return openssl_decrypt($encrypted, $method, $key, 0, $iv);
		}

		/**
		 * Check if user is already subscribed
		 *
		 * @return void
		 */
		public function instant_popup_check_subscription() {
			// Verify nonce for security
			if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'instant_popup_subscription_check')) {
				wp_send_json_error('Security verification failed');
				return;
			}

			$email = isset($_POST['email']) ? sanitize_email(wp_unslash($_POST['email'])) : '';

			if (empty($email) || !is_email($email)) {
				wp_send_json_error('Invalid email address');
				return;
			}

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

		// Check if email exists and is subscribed
		$subscriber = $wpdb->get_row($wpdb->prepare(
			"SELECT * FROM `{$escaped_table_name}` WHERE emailaddress = %s AND status = 'yes'",
			$email
		));

			if ($subscriber) {
				// Get subscription settings to check prevent_reshow setting
				$subscription_settings = $this->get_subscription_settings();
				$prevent_reshow = isset($subscription_settings['prevent_reshow']) && $subscription_settings['prevent_reshow'] == '1';

				wp_send_json_success([
					'subscribed' => true,
					'prevent_reshow' => $prevent_reshow,
					'message' => 'User is already subscribed'
				]);
			} else {
				wp_send_json_success([
					'subscribed' => false,
					'prevent_reshow' => false,
					'message' => 'User is not subscribed'
				]);
			}
		}

		/**
		 * Check if email verification is enabled for a campaign
		 *
		 * @param string $campaign_id
		 * @return bool
		 */
	private function is_email_verification_enabled($campaign_id) {
		global $wpdb;
		$table_name = $wpdb->prefix . 'instant_popup_builder';
		$escaped_table_name = esc_sql($table_name);

		$popup = $wpdb->get_row($wpdb->prepare(
			"SELECT * FROM `{$escaped_table_name}` WHERE id = %d AND type = 'subscription'",
			$campaign_id
		));

			if (!$popup) {
				return false;
			}

			$settings = json_decode($popup->advance, true);
			$verification_enabled = isset($settings['enable_email_verification']) && $settings['enable_email_verification'] === 'yes';

			return $verification_enabled;
		}

		/**
		 * Generate verification token
		 *
		 * @param string $email
		 * @return string
		 */
		private function generate_verification_token($email) {
			return wp_hash($email . time() . wp_salt('auth'));
		}

		/**
		 * Send verification email
		 *
		 * @param string $email
		 * @param string $name
		 * @param string $campaign_id
		 * @param string $token
		 */
		private function send_verification_email($email, $name, $campaign_id, $token) {
			// Send verification email

		// Get campaign details
		global $wpdb;
		$table_name = $wpdb->prefix . 'instant_popup_builder';
		$escaped_table_name = esc_sql($table_name);
		$campaign = $wpdb->get_row($wpdb->prepare(
			"SELECT * FROM `{$escaped_table_name}` WHERE id = %d",
			$campaign_id
		));

			$campaign_name = $campaign ? $campaign->title : 'Newsletter';

			// Get verification email template
			$template = $this->get_verification_email_template($campaign_id);

			// Prepare template data
			$template_data = [
				'subscriber_name' => $name,
				'subscriber_email' => $email,
				'campaign_name' => $campaign_name,
				'site_name' => esc_js(get_bloginfo('name')),
				'site_url' => home_url(),
				'verification_link' => $this->generate_verification_link($email, $token),
				'subscription_date' => date_i18n(get_option('date_format')),
				'verification_expires' => date_i18n(get_option('date_format'), strtotime('+24 hours'))
			];


			// Process template tags
			require_once plugin_dir_path(__FILE__) . '../includes/class-template-tags-processor.php';
			$email_content = Template_Tags_Processor::process_template_tags($template['content'], $template_data);
			$email_subject = Template_Tags_Processor::process_template_tags($template['subject'], $template_data);


			// Send email
			$headers = [
				'Content-Type: text/html; charset=UTF-8',
				'From: ' . $template['from_name'] . ' <' . $template['from_email'] . '>',
				'Reply-To: ' . $template['reply_to']
			];


			// Send the verification email
			$sent = wp_mail($email, $email_subject, $email_content, $headers);

			// Log the email sending result
			if ($sent) {
				// Email sent successfully
			} else {
				// Email failed to send

				// Test functionality removed for production
			}

			return $sent;
		}

		/**
		 * Get verification email template
		 *
		 * @param string $campaign_id
		 * @return array
		 */
		private function get_verification_email_template($campaign_id) {
			// Get default template
			$default_template = [
				'subject' => 'Verify your subscription to {campaign_name}',
				'content' => $this->get_default_verification_template(),
				'from_name' => esc_js(get_bloginfo('name')),
				'from_email' => get_option('admin_email'),
				'reply_to' => get_option('admin_email')
			];

			// Check if custom template exists for this campaign
			$custom_template = get_option('ipb_verification_template_' . $campaign_id);
			if ($custom_template) {
				return array_merge($default_template, $custom_template);
			}

			return $default_template;
		}

		/**
		 * Get default verification email template
		 *
		 * @return string
		 */
		private function get_default_verification_template() {
			return '
			<!DOCTYPE html>
			<html>
			<head>
				<meta charset="UTF-8">
				<meta name="viewport" content="width=device-width, initial-scale=1.0">
				<title>Verify Your Subscription</title>
			</head>
			<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px;">
				<div style="background: #f8f9fa; padding: 30px; border-radius: 8px;">
					<h1 style="color: #2c3e50; margin-bottom: 20px;">Verify Your Email Address</h1>

					<p>Hello {subscriber_name},</p>

					<p>Thank you for subscribing to <strong>{campaign_name}</strong>! To complete your subscription, please verify your email address by clicking the button below:</p>

					<div style="text-align: center; margin: 30px 0;">
						<a href="{verification_link}" style="background: #007cba; color: white; padding: 12px 30px; text-decoration: none; border-radius: 5px; display: inline-block; font-weight: bold;">Verify Email Address</a>
					</div>

					<p><strong>Important:</strong> This verification link will expire in 24 hours for security reasons.</p>

					<p>If you did not request this subscription, you can safely ignore this email.</p>

					<hr style="border: none; border-top: 1px solid #ddd; margin: 30px 0;">

					<p style="font-size: 12px; color: #666;">
						This email was sent to {subscriber_email} from {site_name}.<br>
						If you have any questions, please contact us.
					</p>
				</div>
			</body>
			</html>';
		}

		/**
		 * Generate verification link
		 *
		 * @param string $email
		 * @param string $token
		 * @return string
		 */
		private function generate_verification_link($email, $token) {
			return home_url('/verify-email/?email=' . urlencode($email) . '&token=' . $token);
		}

		/**
		 * AJAX handler for email verification
		 */
		public function instant_popup_verify_email() {
			// Verify nonce for security
			if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'instant_popup_verification_action')) {
				wp_send_json_error('Security verification failed');
				return;
			}

			$email = isset($_POST['email']) ? sanitize_email(wp_unslash($_POST['email'])) : '';
			$token = isset($_POST['token']) ? sanitize_text_field(wp_unslash($_POST['token'])) : '';

			if (empty($email) || empty($token)) {
				wp_send_json_error('Invalid verification parameters');
				return;
			}

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

		// Find subscriber with this token
		$subscriber = $wpdb->get_row($wpdb->prepare(
			"SELECT * FROM `{$escaped_table_name}` WHERE emailaddress = %s AND verification_token = %s AND status = 'pending'",
			$email,
			$token
		));

			if (!$subscriber) {
				wp_send_json_error('Invalid or expired verification link');
				return;
			}

			// Check if token is expired
			if (strtotime($subscriber->verification_expires) < time()) {
				wp_send_json_error('Verification link has expired. Please subscribe again.');
				return;
			}

			// Update subscriber status to verified
			$result = $wpdb->update(
				$table_name,
				[
					'status' => 'yes',
					'verification_token' => null,
					'verification_expires' => null
				],
				['emailaddress' => $email],
				['%s', '%s', '%s'],
				['%s']
			);

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

			// Trigger autoresponder emails for verified subscription
			$this->trigger_autoresponder_emails($subscriber->campaign, $email);

			// Premium extensions may synchronize the verified subscriber.
			do_action('ipb_subscription_subscriber_created', $email, $subscriber->firstname, $subscriber->lastname);

			wp_send_json_success('Email verified successfully! You are now subscribed to our newsletter.');
		}

		/**
		 * Test methods removed for production
		 * These methods were used for testing email functionality
		 */

		/**
		 * Handle email verification page
		 */
		public function handle_email_verification_page() {
			// Check if this is an email verification page request
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter used for routing/display purposes only, value is sanitized
			$verify_email_route = isset($_GET['verify-email']) ? sanitize_text_field(wp_unslash($_GET['verify-email'])) : '';
			if ($verify_email_route === 'true') {
				// Set page title
				add_filter('wp_title', function($title) {
					return 'Verify Email - ' . esc_js(get_bloginfo('name'));
				});

				// Add body class
				add_filter('body_class', function($classes) {
					$classes[] = 'ipb-verification-page';
					return $classes;
				});

				// Add content filter to show verification form
				add_filter('the_content', function($content) {
					if (is_page() || is_single()) {
						$request_args = $this->get_sanitized_verification_request_params();

						// Security: never build shortcode strings from request-derived values.
						return $this->render_verification_form_from_request($request_args);
					}
					return $content;
				});
			}
		}

		/**
		 * Build a safe array of verification request params.
		 *
		 * @return array{email: string, token: string}
		 */
		private function get_sanitized_verification_request_params()
		{
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters used for display purposes only, values are sanitized
			$email = isset($_GET['email']) ? sanitize_email(wp_unslash($_GET['email'])) : '';
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters used for display purposes only, values are sanitized
			$token = isset($_GET['token']) ? sanitize_text_field(wp_unslash($_GET['token'])) : '';

			$email = str_replace(['[', ']'], '', $email);
			$token = str_replace(['[', ']'], '', $token);

			if ($token !== '' && !preg_match('/^[A-Za-z0-9\-_]{10,200}$/', $token)) {
				$token = '';
			}

			return [
				'email' => $email,
				'token' => $token,
			];
		}

		/**
		 * Build a safe array of unsubscribe request params.
		 *
		 * @return array{email: string, campaign: string}
		 */
		private function get_sanitized_unsubscribe_request_params()
		{
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters used for display purposes only, values are sanitized
			$encrypted_email = isset($_GET['email']) ? sanitize_text_field(wp_unslash($_GET['email'])) : '';
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters used for display purposes only, values are sanitized
			$campaign_id = isset($_GET['campaign']) ? sanitize_text_field(wp_unslash($_GET['campaign'])) : '';

			$encrypted_email = str_replace(['[', ']'], '', $encrypted_email);
			$campaign_id = str_replace(['[', ']'], '', $campaign_id);

			return [
				'email' => $encrypted_email,
				'campaign' => $campaign_id,
			];
		}

		/**
		 * Allowed HTML for the standalone unsubscribe page (forms, fields, inline script).
		 *
		 * @return array<string, array<string, bool>>
		 */
		private function get_allowed_html_unsubscribe_form_output()
		{
			$allowed = wp_kses_allowed_html( 'post' );

			$allowed['div'] = array_merge(
				isset( $allowed['div'] ) ? $allowed['div'] : array(),
				array(
					'class' => true,
					'id'    => true,
					'style' => true,
				)
			);

			$allowed['form'] = array(
				'action'         => true,
				'accept'         => true,
				'accept-charset' => true,
				'enctype'        => true,
				'method'         => true,
				'name'           => true,
				'target'         => true,
				'id'             => true,
				'class'          => true,
			);

			$allowed['input'] = array(
				'type'        => true,
				'name'        => true,
				'id'          => true,
				'value'       => true,
				'placeholder' => true,
				'required'    => true,
				'checked'     => true,
				'class'       => true,
				'disabled'    => true,
				'readonly'    => true,
				'maxlength'   => true,
				'size'        => true,
			);

			$allowed['button'] = array_merge(
				isset( $allowed['button'] ) ? $allowed['button'] : array(),
				array(
					'class' => true,
					'id'    => true,
					'style' => true,
				)
			);

			$allowed['label'] = array_merge(
				isset( $allowed['label'] ) ? $allowed['label'] : array(),
				array(
					'class' => true,
				)
			);

			$allowed['span'] = array_merge(
				isset( $allowed['span'] ) ? $allowed['span'] : array(),
				array(
					'class' => true,
					'style' => true,
				)
			);

			$allowed['script'] = array(
				'type' => true,
				'src'  => true,
			);

			return $allowed;
		}

		/**
		 * Render unsubscribe form from pre-sanitized request args.
		 *
		 * @param array $request_args
		 * @return string
		 */
		private function render_unsubscribe_form_from_request($request_args = [])
		{
			$args = is_array($request_args) ? $request_args : [];
			$args = apply_filters('ipb_unsubscribe_request_args', $args);

			$output = $this->ipb_create_unsubscribe_form([
				'email' => isset($args['email']) ? $args['email'] : '',
				'campaign' => isset($args['campaign']) ? $args['campaign'] : '',
			]);

			return apply_filters('ipb_unsubscribe_request_output', $output, $args);
		}

		/**
		 * Render verification form from pre-sanitized request args.
		 *
		 * @param array $request_args
		 * @return string
		 */
		private function render_verification_form_from_request($request_args = [])
		{
			$args = is_array($request_args) ? $request_args : [];
			$args = apply_filters('ipb_verification_request_args', $args);

			$output = $this->ipb_create_verification_form([
				'email' => isset($args['email']) ? $args['email'] : '',
				'token' => isset($args['token']) ? $args['token'] : '',
			]);

			return apply_filters('ipb_verification_request_output', $output, $args);
		}

		/**
		 * Get subscription settings for a specific popup
		 *
		 * @param int $popup_id The popup ID
		 * @return array The subscription settings
		 */
		public function get_subscription_settings($popup_id = null)
		{
			global $wpdb;

			// If no popup_id provided, try to get it from transient
			if (!$popup_id) {
				$popup_id = get_transient('instant_popup_builder_popup_id');
			}

			if (!$popup_id) {
				return array();
			}

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

		// Check if table exists
		if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_name)) != $table_name) {
			return array();
		}

		// Get settings from database
		$result = $wpdb->get_row($wpdb->prepare(
			"SELECT settings FROM `{$escaped_table_name}` WHERE popup_id = %d",
			$popup_id
		));

			if ($result && $result->settings) {
				$settings = maybe_unserialize($result->settings);
				return $settings;
			}

			return array();
		}

		public function get_subscription_count()
		{
			global $wpdb;


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

		// Check if table exists
		if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_name)) != $table_name) {
			return 0;
		}

		// Get settings from database
		$total_records = $wpdb->get_var( "SELECT COUNT(*) FROM `{$escaped_table_name}`" );

            return $total_records;

		}
    	public function admin_notification_subscribers() {
    	$total_subscribers = $this->get_subscription_count();
    	$free_limit = 1000; // Define your free plan limit here
    	if ($total_subscribers >= $free_limit) {
        ?>
        <div class="notice notice-success is-dismissible">
            <p><?php esc_html_e('Instant Popup Subscription: You have reached the limit of subscribers please upgrade to pro for more limit!', 'instant-popup-builder'); ?></p>
        </div>

        <?php
         }
    	}

	}
}
