<?php
/**
 * OTP Login Service.
 *
 * @package automation-web-platform
 */

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


/**
 * Class WAWP_Otp_Login
 * Handles OTP Login functionality.
 *
 * @package automation-web-platform
 */
class WAWP_Otp_Login {
	use WAWP_Security_Trait;
	use WAWP_Phone_Helper_Trait;
	use WAWP_Settings_Handler;
	use WAWP_Logging_Trait;

	/**
	 * Instance of this class.
	 *
	 * @var WAWP_Otp_Login|null
	 */
	private static $instance = null;

	/**
	 * WAWP Instances.
	 *
	 * @var array|null
	 */
	private $wawp_instances;

	/**
	 * Constructor.
	 *
	 * @param mixed $database_manager Database Manager.
	 * @param mixed $wawp_instances   WAWP Instances.
	 */
	public function __construct( $database_manager = null, $wawp_instances = null ) {
		$this->wawp_instances = $wawp_instances ? $wawp_instances : ( WAWP::instance()->senders ?? null );
	}

	/**
	 * Get instance.
	 *
	 * @param mixed $db        Database Manager.
	 * @param mixed $instances WAWP Instances.
	 * @return WAWP_Otp_Login
	 */
	public static function get_instance( $db = null, $instances = null ) {
		if ( null === self::$instance ) {
			self::$instance = new self( $db, $instances );
		}

		return self::$instance;
	}

	/**
	 * Get instance row cached.
	 *
	 * @param string $instance_id Instance ID.
	 * @return object|null
	 */
	private function get_instance_row_cached( string $instance_id ) {
		if ( empty( $instance_id ) ) {
			return null;
		}

		$cache_key = 'wawp_inst_' . md5( $instance_id );
		$instance  = wp_cache_get( $cache_key, 'wawp_database' );

		if ( false === $instance ) {
			$instance = WAWP()->instance_manager->get_instance_by_instance_id( $instance_id );
			if ( $instance && 'online' === $instance->status ) {
				wp_cache_set( $cache_key, $instance, 'wawp_database', HOUR_IN_SECONDS );
			}
		}

		return $instance ? $instance : null;
	}

	/**
	 * Get default settings.
	 *
	 * @return array
	 */
	public function get_default_settings() {
		return array(
			'instance'                         => 0,
			'otp_message_whatsapp'             => esc_html__( 'Your OTP code is: {{otp}}', 'automation-web-platform' ),
			'otp_message_email'                => esc_html__( 'Please click the link below to verify your identity: {{magic_link}}', 'automation-web-platform' ),
			'magic_link_message_email'         => esc_html__( 'Click here to sign in: {{wawp_login_link}}', 'automation-web-platform' ),
			'login_method'                     => 'phone_login',
			'enable_email_password'            => 1,
			'enable_whatsapp'                  => 1,
			'enable_email'                     => 0,
			'enable_firebase_sms'              => 0,
			'custom_shortcode'                 => '',
			'custom_css'                       => '',
			'redirect_rules'                   => array(),
			'signup_logo'                      => array(
				'default'           => WAWP_PLUGIN_DIR . 'login-WhatsApp_icon.png',
				'sanitize_callback' => 'esc_url_raw',
			),
			'title'                            => esc_html__( 'Welcome back', 'automation-web-platform' ),
			'description'                      => esc_html__( 'Choose a sign-in method to continue', 'automation-web-platform' ),
			'whatsapp_button_color'            => '#22c55e',
			'whatsapp_button_text_color'       => '#ffffff',
			'firebase_button_color'            => '#3b82f6',
			'firebase_button_text_color'       => '#ffffff',
			'email_otp_button_color'           => '#22c55e',
			'email_otp_button_text_color'      => '#ffffff',
			'password_login_button_color'      => '#ef4444',
			'password_login_button_text_color' => '#ffffff',
			'verify_button_color'              => '#3b82f6',
			'verify_button_text_color'         => '#ffffff',
			'resend_button_color'              => '#64748b',
			'resend_button_text_color'         => '#ffffff',
			'show_password_button_color'       => '#ef4444',
			'show_password_button_text_color'  => '#ffffff',
			'back_button_color'                => '#64748b',
			'back_button_text_color'           => '#ffffff',
			'primary_phone_method'             => 'whatsapp',
			'primary_email_method'             => 'otp',
			'session_lifetime_type'            => 'lifetime',
			'session_lifetime_value'           => 0,
			'whatsapp_auth_type'               => 'otp',
			'whatsapp_otp_lang_type'           => 'site',
			'whatsapp_otp_custom_lang'         => 'ar',
			'whatsapp_otp_footer_enabled'      => 0,
			'whatsapp_otp_footer'              => '',
			'whatsapp_list_title'              => esc_html__( 'Secure Login', 'automation-web-platform' ),
			'whatsapp_list_desc'               => esc_html__( 'Please confirm your identity to continue.', 'automation-web-platform' ),
			'whatsapp_list_footer'             => esc_html__( 'Secure authentication via Wawp', 'automation-web-platform' ),
			'whatsapp_list_button'             => esc_html__( 'Choose Action', 'automation-web-platform' ),
			'whatsapp_list_item1'              => esc_html__( 'Approve Login', 'automation-web-platform' ),
			'whatsapp_list_item1_desc'         => esc_html__( 'Verify this is you', 'automation-web-platform' ),
			'whatsapp_list_item2'              => __( 'Reject & Report', 'automation-web-platform' ),
			'whatsapp_list_item2_desc'         => esc_html__( 'Secure your account', 'automation-web-platform' ),
		);
	}

	/**
	 * Delete setting.
	 *
	 * @param string $name Setting name.
	 */
	public function delete_setting( $name ) {
		global $wpdb;
		$table = WAWP()->db->tables['otp_login_settings'] ?? '';
		if ( $table ) {
			WAWP()->db->delete_row( 'otp_login_settings', array( 'setting_name' => $name ) );
			wp_cache_delete( 'wawp_otp_settings_raw', 'wawp_otp' );
			wp_cache_delete( 'wawp_otp_setting_' . $name, 'wawp_otp' );
		}
	}

	/**
	 * Get setting.
	 *
	 * @param string $name Setting name.
	 * @return mixed
	 */
	private function get_setting( $name ) {
		global $wpdb;
		$table = WAWP()->db->tables['otp_login_settings'] ?? '';
		if ( ! $table ) {
			return false;
		}

		$cache_key = 'wawp_otp_setting_' . $name;
		$row       = wp_cache_get( $cache_key, 'wawp_otp' );

		if ( false === $row ) {
			$row = WAWP()->db->get_results_cached( $wpdb->prepare( 'SELECT setting_value FROM %i WHERE setting_name = %s', $table, $name ), $cache_key, 'wawp_otp', 300 );
			$row = ! empty( $row ) ? (object) $row[0] : null;
		}

		if ( $row ) {
			$value = $row->setting_value;
			return is_serialized( $value ) ? maybe_unserialize( $value ) : $value;
		}
		return null;
	}

	/**
	 * Get option mapping between pretty keys and DB keys.
	 *
	 * @return array
	 */
	private function get_option_mapping() {
		return array(
			'login_method'                     => WAWP_Settings_Registry::AUTH_OTP_METHOD,
			'session_lifetime_type'            => WAWP_Settings_Registry::AUTH_SESSION_TYPE,
			'session_lifetime_value'           => WAWP_Settings_Registry::AUTH_SESSION_VALUE,
			'primary_email_method'             => WAWP_Settings_Registry::AUTH_PRIMARY_EMAIL_METHOD,
			'enable_email_password'            => WAWP_Settings_Registry::AUTH_ENABLE_EMAIL_PASS,
			'enable_email'                     => WAWP_Settings_Registry::AUTH_ENABLE_EMAIL_OTP,
			'otp_subject_email'                => WAWP_Settings_Registry::AUTH_OTP_SUBJECT_EMAIL,
			'otp_email_template_id'            => WAWP_Settings_Registry::AUTH_OTP_EMAIL_TPL,
			'otp_message_email'                => WAWP_Settings_Registry::AUTH_OTP_MSG_EMAIL,
			'primary_phone_method'             => WAWP_Settings_Registry::AUTH_PRIMARY_PHONE_METHOD,
			'enable_whatsapp'                  => WAWP_Settings_Registry::AUTH_ENABLE_WA_OTP,
			'otp_message_whatsapp'             => WAWP_Settings_Registry::AUTH_OTP_MSG_WA,
			'enable_firebase_sms'              => WAWP_Settings_Registry::AUTH_ENABLE_FB_OTP,
			'redirect_rules'                   => WAWP_Settings_Registry::AUTH_REDIRECT_RULES,
			'logo'                             => WAWP_Settings_Registry::AUTH_LOGO,
			'title'                            => WAWP_Settings_Registry::AUTH_TITLE,
			'description'                      => WAWP_Settings_Registry::AUTH_DESC,
			'color_theme'                      => WAWP_Settings_Registry::AUTH_COLOR_THEME,
			'custom_css'                       => WAWP_Settings_Registry::AUTH_CUSTOM_CSS,
			'custom_shortcode'                 => WAWP_Settings_Registry::AUTH_CUSTOM_SHORTCODE,
			'enable_premium_design'            => WAWP_Settings_Registry::AUTH_PREMIUM_DESIGN,
			'instance'                         => WAWP_Settings_Registry::AUTH_WA_INSTANCE,
			'whatsapp_auth_type'               => WAWP_Settings_Registry::AUTH_WA_AUTH_TYPE,
			'whatsapp_otp_lang_type'           => WAWP_Settings_Registry::AUTH_WA_OTP_LANG_TYPE,
			'whatsapp_otp_custom_lang'         => WAWP_Settings_Registry::AUTH_WA_OTP_CUSTOM_LANG,
			'whatsapp_otp_footer_enabled'      => WAWP_Settings_Registry::AUTH_WA_OTP_FOOTER_ENABLED,
			'whatsapp_otp_footer'              => WAWP_Settings_Registry::AUTH_WA_OTP_FOOTER,
			'whatsapp_list_title'              => WAWP_Settings_Registry::AUTH_WA_LIST_TITLE,
			'whatsapp_list_desc'               => WAWP_Settings_Registry::AUTH_WA_LIST_DESC,
			'whatsapp_list_footer'             => WAWP_Settings_Registry::AUTH_WA_LIST_FOOTER,
			'whatsapp_list_button'             => WAWP_Settings_Registry::AUTH_WA_LIST_BUTTON,
			'whatsapp_list_item1'              => WAWP_Settings_Registry::AUTH_WA_LIST_ITEM1,
			'whatsapp_list_item1_desc'         => WAWP_Settings_Registry::AUTH_WA_LIST_ITEM1_DESC,
			'whatsapp_list_item2'              => WAWP_Settings_Registry::AUTH_WA_LIST_ITEM2,
			'whatsapp_list_item2_desc'         => WAWP_Settings_Registry::AUTH_WA_LIST_ITEM2_DESC,
			'whatsapp_button_color'            => WAWP_Settings_Registry::AUTH_WA_BTN_COLOR,
			'whatsapp_button_text_color'       => WAWP_Settings_Registry::AUTH_WA_BTN_TEXT_COLOR,
			'firebase_button_color'            => WAWP_Settings_Registry::AUTH_FB_BTN_COLOR,
			'firebase_button_text_color'       => WAWP_Settings_Registry::AUTH_FB_BTN_TEXT_COLOR,
			'email_otp_button_color'           => WAWP_Settings_Registry::AUTH_EMAIL_BTN_COLOR,
			'email_otp_button_text_color'      => WAWP_Settings_Registry::AUTH_EMAIL_BTN_TEXT_COLOR,
			'verify_button_color'              => WAWP_Settings_Registry::AUTH_VERIFY_BTN_COLOR,
			'verify_button_text_color'         => WAWP_Settings_Registry::AUTH_VERIFY_BTN_TEXT_COLOR,
			'resend_button_color'              => WAWP_Settings_Registry::AUTH_RESEND_BTN_COLOR,
			'resend_button_text_color'         => WAWP_Settings_Registry::AUTH_RESEND_BTN_TEXT_COLOR,
			'password_login_button_color'      => WAWP_Settings_Registry::AUTH_PASS_LOGIN_BTN_COLOR,
			'password_login_button_text_color' => WAWP_Settings_Registry::AUTH_PASS_LOGIN_BTN_TEXT_COLOR,
			'show_password_button_color'       => WAWP_Settings_Registry::AUTH_SHOW_PASS_BTN_COLOR,
			'show_password_button_text_color'  => WAWP_Settings_Registry::AUTH_SHOW_PASS_BTN_TEXT_COLOR,
			'back_button_color'                => WAWP_Settings_Registry::AUTH_BACK_BTN_COLOR,
			'back_button_text_color'           => WAWP_Settings_Registry::AUTH_BACK_BTN_TEXT_COLOR,
			'initial_cooldown'                 => WAWP_Settings_Registry::AUTH_INITIAL_COOLDOWN,
			'max_cooldown'                     => WAWP_Settings_Registry::AUTH_MAX_COOLDOWN,
			'polling_interval'                 => WAWP_Settings_Registry::AUTH_POLLING_INTERVAL,
		);
	}

	/**
	 * Get plugin settings.
	 *
	 * @return array
	 */
	private function get_plugin_settings() {
		$defaults = $this->get_default_settings();
		global $wpdb;
		$table = WAWP()->db->tables['otp_login_settings'] ?? '';
		$saved = array();

		if ( $table ) {
			$cache_key = 'wawp_otp_settings_raw';
			$rows      = wp_cache_get( $cache_key, 'wawp_otp' );
			if ( false === $rows ) {
				$rows = WAWP()->db->get_results_cached( $wpdb->prepare( 'SELECT setting_name, setting_value FROM %i', $table ), $cache_key, 'wawp_otp', HOUR_IN_SECONDS );
			}
			if ( ! empty( $rows ) ) {
				foreach ( $rows as $row ) {
					$saved[ $row['setting_name'] ] = is_serialized( $row['setting_value'] ) ? maybe_unserialize( $row['setting_value'] ) : $row['setting_value'];
				}
			}
		}

		if ( empty( $saved ) ) {
			$saved = $this->get_wawp_setting( WAWP_Settings_Registry::OTP_SETTINGS, array() );
		}

		// Merge in individual options from the registry if they exist.
		// This ensures settings saved via the React dashboard are correctly picked up.
		$mapping = $this->get_option_mapping();
		foreach ( $mapping as $pretty => $db_key ) {
			$val = get_option( $db_key, null );
			if ( null !== $val ) {
				$saved[ $pretty ] = $val;
				$saved[ $db_key ] = $val;
			}
		}

		$settings = array_merge( $defaults, $saved );

		if ( ! empty( $settings['custom_shortcode'] ) ) {
			if ( ! is_array( $settings['custom_shortcode'] ) ) {
				$decoded = json_decode( $settings['custom_shortcode'], true );
				if ( json_last_error() === JSON_ERROR_NONE && is_array( $decoded ) ) {
					$settings['custom_shortcode'] = $decoded;
				} else {
					$settings['custom_shortcode'] = array( $settings['custom_shortcode'] );
				}
			}

			$max_loops = 5;
			while ( $max_loops-- > 0 && is_array( $settings['custom_shortcode'] ) ) {
				$count = count( $settings['custom_shortcode'] );
				if ( 1 !== $count || ! is_string( $settings['custom_shortcode'][0] ) ) {
					break;
				}
				$candidate = trim( $settings['custom_shortcode'][0] );
				if ( ! empty( $candidate ) && ( strpos( $candidate, '[' ) === 0 || strpos( $candidate, '{' ) === 0 ) ) {
					$next_decoded = json_decode( $candidate, true );
					if ( json_last_error() === JSON_ERROR_NONE && is_array( $next_decoded ) ) {
						$settings['custom_shortcode'] = $next_decoded;
						continue;
					}
				}
				break;
			}
		}

		if ( empty( $settings['custom_shortcode'] ) || ! is_array( $settings['custom_shortcode'] ) ) {
			$settings['custom_shortcode'] = array();
		}

		return $settings;
	}

	/**
	 * Get React settings data.
	 *
	 * @return array
	 */
	public function get_react_settings_data() {
		$rows      = WAWP()->instance_manager->get_online_instances_cached();
		$instances = array();
		if ( ! empty( $rows ) ) {
			foreach ( $rows as $r ) {
				$instances[] = array(
					'instance_id'   => $r->instance_id,
					'instance_name' => $r->name,
					'number'        => property_exists( $r, 'number' ) ? $r->number : '',
				);
			}
		}

		$wa_enabled    = WAWP_Connector()->is_whatsapp_active() || WAWP_Connector()->is_meta_active();
		$email_enabled = WAWP_Connector()->is_email_active();

		global $wpdb;
		$email_templates_table = $wpdb->prefix . 'wawp_email_templates';
		$cache_key             = 'wawp_email_templates_list_v2';
		$email_templates_raw   = wp_cache_get( $cache_key, 'wawp_email' );

		if ( false === $email_templates_raw ) {
			$email_templates_raw = WAWP()->db->get_results_cached( $wpdb->prepare( 'SELECT id, name FROM %i ORDER BY id DESC', $email_templates_table ), $cache_key, 'wawp_email', HOUR_IN_SECONDS );
			$email_templates_raw = array_map(
				function ( $r ) {
					return (object) $r;
				},
				$email_templates_raw
			);
		}

		$email_templates = array();
		if ( $email_templates_raw ) {
			foreach ( $email_templates_raw as $tpl ) {
				$email_templates[] = array(
					'id'   => $tpl->id,
					'name' => $tpl->name,
				);
			}
		}

		$pages_cache_key = 'wawp_otp_pages_list';
		$pages           = wp_cache_get( $pages_cache_key, 'wawp_database' );
		if ( false === $pages ) {
			$pages = get_transient( $pages_cache_key );
			if ( false === $pages ) {
				// Use cached results to avoid heavy queries.
				$pages_raw = WAWP()->db->get_results_cached( "SELECT ID, post_title FROM {$wpdb->posts} WHERE post_type = 'page' AND post_status = 'publish' ORDER BY post_title ASC LIMIT 500", $pages_cache_key, 'wawp_database', DAY_IN_SECONDS );
				$pages_raw = array_map(
					function ( $r ) {
						return (object) $r;
					},
					$pages_raw
				);
				$pages     = array();
				foreach ( $pages_raw as $p ) {
					$pages[] = array(
						'id'    => $p->ID,
						'title' => $p->post_title,
						'url'   => get_permalink( $p->ID ),
					);
				}
				set_transient( $pages_cache_key, $pages, DAY_IN_SECONDS );
			}
			wp_cache_set( $pages_cache_key, $pages, 'wawp_database', DAY_IN_SECONDS );
		}

		$option_names   = $this->get_option_mapping();
		$raw_settings   = $this->get_plugin_settings();
		$mapped_options = array();
		$defaults       = WAWP_Settings_Registry::get_defaults();
		$local_defaults = $this->get_default_settings();

		foreach ( $option_names as $pretty => $db ) {
			$val = isset( $raw_settings[ $db ] ) ? $raw_settings[ $db ] : ( isset( $raw_settings[ $pretty ] ) ? $raw_settings[ $pretty ] : null );

			if ( ( null === $val || '' === $val ) && isset( $local_defaults[ $pretty ] ) ) {
				$val = $local_defaults[ $pretty ];
			}

			if ( ( null === $val || '' === $val ) && isset( $defaults[ $db ] ) ) {
				$val = $defaults[ $db ];
			}

			// Ensure complex fields are decoded.
			if ( in_array( $pretty, array( 'redirect_rules', 'custom_shortcode' ), true ) ) {
				$val = $this->from_db( $val );
			}

			$mapped_options[ $pretty ] = $val;
			$mapped_options[ $db ]     = $val;
		}

		return array(
			'options'         => $mapped_options,
			'optionNames'     => $option_names,
			'onlineInstances' => $instances,
			'availability'    => array(
				'whatsapp'  => array(
					'available' => $wa_enabled,
					'reason'    => ! $wa_enabled ? esc_html__( 'No active WhatsApp instances found.', 'automation-web-platform' ) : '',
				),
				'firebase'  => array(
					'available' => WAWP_Connector()->is_firebase_active(),
					'reason'    => ! WAWP_Connector()->is_firebase_active() ? esc_html__( 'Firebase credentials are not configured.', 'automation-web-platform' ) : '',
				),
				'email_otp' => array(
					'available' => $email_enabled,
					'reason'    => ! $email_enabled ? esc_html__( 'Email SMTP is not configured.', 'automation-web-platform' ) : '',
				),
			),
			'roles'           => wp_roles()->roles,
			'pages'           => $pages,
			'emailTemplates'  => $email_templates,
			'i18n'            => array(
				'general'                        => esc_html__( 'General', 'automation-web-platform' ),
				'email_login'                    => esc_html__( 'Email Login', 'automation-web-platform' ),
				'phone_login'                    => esc_html__( 'Phone Login', 'automation-web-platform' ),
				'redirection'                    => esc_html__( 'Redirection', 'automation-web-platform' ),
				'style'                          => esc_html__( 'Style', 'automation-web-platform' ),
				'shortcodes'                     => esc_html__( 'Shortcodes', 'automation-web-platform' ),
				'settingsSaved'                  => esc_html__( 'Settings saved successfully!', 'automation-web-platform' ),
				'errorOccurred'                  => esc_html__( 'An error occurred while saving.', 'automation-web-platform' ),
				'login_wa_active'                => esc_html__( 'Active: WhatsApp authentication is ready.', 'automation-web-platform' ),
				'login_wa_inactive'              => esc_html__( 'Inactive: WhatsApp authentication is disabled.', 'automation-web-platform' ),
				'login_fb_active'                => esc_html__( 'Active: SMS authentication is ready.', 'automation-web-platform' ),
				'login_fb_inactive'              => esc_html__( 'Inactive: SMS authentication is disabled.', 'automation-web-platform' ),
				'login_em_active'                => esc_html__( 'Active: Email Magic Link is ready.', 'automation-web-platform' ),
				'login_em_inactive'              => esc_html__( 'Inactive: Email Magic Link is disabled.', 'automation-web-platform' ),
				'default_login_method_title'     => esc_html__( 'Default Login Method', 'automation-web-platform' ),
				'default_login_method_desc'      => esc_html__( 'Choose the login method you’d like your users to see first on the login page.', 'automation-web-platform' ),
				'security_session_title'         => __( 'Security & Session', 'automation-web-platform' ),
				'security_session_desc'          => esc_html__( 'Manage session lifetime and other security protocols for authenticated users.', 'automation-web-platform' ),
				'primary_email_method_title'     => esc_html__( 'Primary Email Method', 'automation-web-platform' ),
				'primary_email_method_desc'      => esc_html__( 'Decide which login flow takes precedence when a user provides their email address.', 'automation-web-platform' ),
				'enable_email_password_title'    => __( 'Enable Email & Password', 'automation-web-platform' ),
				'enable_email_password_desc'     => esc_html__( 'Allow users to login using their standard WordPress credentials.', 'automation-web-platform' ),
				'primary_phone_method_title'     => esc_html__( 'Primary Phone Method', 'automation-web-platform' ),
				'primary_phone_method_desc'      => esc_html__( 'Choose the preferred channel for delivering verification codes to mobile devices.', 'automation-web-platform' ),
				'redirection_rules_title'        => esc_html__( 'Custom Redirection Rules', 'automation-web-platform' ),
				'redirection_rules_desc'         => esc_html__( 'Control where users land after a successful login based on their account role.', 'automation-web-platform' ),
				'login_page_style_title'         => esc_html__( 'Login Page Aesthetics', 'automation-web-platform' ),
				'login_page_style_desc'          => esc_html__( 'Customize the look and feel of your login portal to match your brand identity.', 'automation-web-platform' ),
				'shortcode_usage_title'          => esc_html__( 'Shortcode Integration', 'automation-web-platform' ),
				'shortcode_usage_desc'           => esc_html__( 'Use the following shortcodes to embed the login form or logout buttons anywhere on your site.', 'automation-web-platform' ),
				'add_rule'                       => esc_html__( 'Add Rule', 'automation-web-platform' ),
				'redirect_to'                    => esc_html__( 'Redirect To', 'automation-web-platform' ),
				'all_roles'                      => esc_html__( 'All Roles', 'automation-web-platform' ),
				'chooseWaSender'                 => esc_html__( 'Choose WhatsApp Sender', 'automation-web-platform' ),
				'chooseWaSenderDesc'             => esc_html__( 'Select the WhatsApp number that will be used to send messages for this feature.', 'automation-web-platform' ),
				'preferredChannel'               => esc_html__( 'Preferred Verification Channel', 'automation-web-platform' ),
				'msg_config_label'               => esc_html__( 'Message Configuration', 'automation-web-platform' ),
				'force_lang_label'               => esc_html__( 'Force Language', 'automation-web-platform' ),
				'enable_custom_footer_label'     => esc_html__( 'Enable Custom Footer', 'automation-web-platform' ),
				'list_ui_label'                  => esc_html__( 'List Interface Design', 'automation-web-platform' ),
				'preferred_channel_label'        => esc_html__( 'Preferred Verification Channel', 'automation-web-platform' ),
				'standard_otp_label'             => esc_html__( 'Standard OTP', 'automation-web-platform' ),
				'standard_otp_desc'              => esc_html__( '6-digit code via Message', 'automation-web-platform' ),
				'interactive_list_label'         => esc_html__( 'Interactive List', 'automation-web-platform' ),
				'interactive_list_desc'          => esc_html__( 'One-tap Verify/Reject', 'automation-web-platform' ),
				'message_config_label'           => esc_html__( 'Message Configuration', 'automation-web-platform' ),
				'force_language_label'           => esc_html__( 'Force Language', 'automation-web-platform' ),
				'list_interface_design_label'    => esc_html__( 'List Interface Design', 'automation-web-platform' ),
				'list_title_field_label'         => esc_html__( 'List Title', 'automation-web-platform' ),
				'main_description_field_label'   => esc_html__( 'Main Description', 'automation-web-platform' ),
				'item1_success_action_label'     => esc_html__( 'Item 1 (Success Action)', 'automation-web-platform' ),
				'action_title_field_label'       => esc_html__( 'Action Title', 'automation-web-platform' ),
				'action_description_field_label' => esc_html__( 'Action Description', 'automation-web-platform' ),
				'item2_reject_action_label'      => esc_html__( 'Item 2 (Reject Action)', 'automation-web-platform' ),
				'selection_button_field_label'   => esc_html__( 'Selection Button', 'automation-web-platform' ),
				'bottom_footer_field_label'      => esc_html__( 'Bottom Footer', 'automation-web-platform' ),
				'select_language_label'          => esc_html__( 'Select Language', 'automation-web-platform' ),
				'footer_content_label'           => esc_html__( 'Footer Content', 'automation-web-platform' ),
				'selectInstance'                 => esc_html__( '— Select Instance —', 'automation-web-platform' ),
				'passwordless_login_title'       => esc_html__( 'Passwordless Login', 'automation-web-platform' ),
				'passwordless_login_desc'        => esc_html__( 'Configure passwordless authentication via WhatsApp, Email Magic Link, or Firebase SMS.', 'automation-web-platform' ),
				'phone_login_label'              => esc_html__( 'Phone Login', 'automation-web-platform' ),
				'phone_login_desc'               => esc_html__( 'Direct WhatsApp or SMS verification', 'automation-web-platform' ),
				'email_login_label'              => esc_html__( 'Email Login', 'automation-web-platform' ),
				'email_login_desc'               => esc_html__( 'Secure OTP or password auth', 'automation-web-platform' ),
				'visual_exp_title'               => esc_html__( 'Visual Experience', 'automation-web-platform' ),
				'visual_exp_desc'                => esc_html__( 'Customize the look and feel of the login form to match your brand identity.', 'automation-web-platform' ),
				'appended_content_title'         => esc_html__( 'Appended Content', 'automation-web-platform' ),
				'appended_content_desc'          => esc_html__( 'Add additional shortcodes to display dynamic content or banners below the core login form.', 'automation-web-platform' ),
				'phone_login_status_desc'        => __( 'Users will see the <b>WhatsApp/Phone</b> login field by default. Highly recommended for mobile-first audiences.', 'automation-web-platform' ),
				'email_login_status_desc'        => __( 'Users will see the <b>Email</b> login field first. Best for professional or desktop-heavy platforms.', 'automation-web-platform' ),
				'session_lifetime_type_label'    => esc_html__( 'Session Lifetime Type', 'automation-web-platform' ),
				'lifetime_follow_wp'             => esc_html__( 'Lifetime (Follow WordPress)', 'automation-web-platform' ),
				'minutes'                        => esc_html__( 'Minutes', 'automation-web-platform' ),
				'hours'                          => esc_html__( 'Hours', 'automation-web-platform' ),
				'days'                           => esc_html__( 'Days', 'automation-web-platform' ),
				'lifetime_value_label'           => esc_html__( 'Lifetime Value', 'automation-web-platform' ),
				'session_lifetime_lifetime_desc' => esc_html__( 'Sessions will follow your global WordPress login duration (usually 14 days).', 'automation-web-platform' ),
				'session_lifetime_custom_desc'   => __( 'User sessions will expire automatically after <b>{{value}} {{type}}</b> of inactivity.', 'automation-web-platform' ),
				'password_label'                 => esc_html__( 'Classic Password', 'automation-web-platform' ),
				'password_desc'                  => esc_html__( 'Standard site credentials', 'automation-web-platform' ),
				'customer_email_label'           => esc_html__( 'Customer Email', 'automation-web-platform' ),
				'subject_label'                  => esc_html__( 'Subject', 'automation-web-platform' ),
				'body_template_label'            => esc_html__( 'Body Template', 'automation-web-platform' ),
				'select_email_template'          => esc_html__( 'Select Email Template...', 'automation-web-platform' ),
				'manage_templates'               => esc_html__( 'Manage Templates', 'automation-web-platform' ),
				'email_otp_limit_warning'        => esc_html__( 'Attention: Email Magic Link functionality might be limited by your server mail configuration.', 'automation-web-platform' ),
				'add_new_rule'                   => esc_html__( 'Add New Rule', 'automation-web-platform' ),
				'target_user_role_label'         => esc_html__( 'Target User Role', 'automation-web-platform' ),
				'everywhere_global'              => esc_html__( 'All Roles', 'automation-web-platform' ),
				'page_link'                      => esc_html__( 'Page Link', 'automation-web-platform' ),
				'redirection_endpoint_label'     => esc_html__( 'Redirection Endpoint', 'automation-web-platform' ),
				'no_custom_endpoints'            => esc_html__( 'No custom endpoints defined', 'automation-web-platform' ),
				'default_wp_landing_desc'        => esc_html__( 'Users will follow the default WordPress landing page after login.', 'automation-web-platform' ),
				'form_logo_label'                => esc_html__( 'Form Logo', 'automation-web-platform' ),
				'upload_label'                   => esc_html__( 'Upload', 'automation-web-platform' ),
				'logo_specs_desc'                => esc_html__( 'Better to use a horizontal PNG/SVG with transparent background.', 'automation-web-platform' ),
				'select_image_btn'               => esc_html__( 'Select Image', 'automation-web-platform' ),
				'logo_set_desc'                  => esc_html__( 'Your brand logo will appear at the top of the login form.', 'automation-web-platform' ),
				'no_logo_set_desc'               => esc_html__( 'No logo set. The form will display your site title instead.', 'automation-web-platform' ),
				'form_headline_label'            => esc_html__( 'Form Headline', 'automation-web-platform' ),
				'form_description_label'         => esc_html__( 'Form Description', 'automation-web-platform' ),
				'custom_header_active_desc'      => esc_html__( 'Custom form header (title and description) is active and visible to users.', 'automation-web-platform' ),
				'default_header_active_desc'     => esc_html__( 'Using default header text. Consider adding a custom title to welcome users.', 'automation-web-platform' ),
				'theme_presets_label'            => esc_html__( 'Theme Presets', 'automation-web-platform' ),
				'detailed_colors_title'          => esc_html__( 'Detailed Colors', 'automation-web-platform' ),
				'bg_label'                       => esc_html__( 'Bg', 'automation-web-platform' ),
				'text_label'                     => esc_html__( 'Text', 'automation-web-platform' ),
				'custom_styling_css_label'       => esc_html__( 'Custom Styling (CSS)', 'automation-web-platform' ),
				'premium_design_active_desc'     => esc_html__( 'Premium custom design is active and applied to your login form.', 'automation-web-platform' ),
				'standard_design_active_desc'    => esc_html__( 'Standard design is active. Enable premium design to apply these custom styles.', 'automation-web-platform' ),
				'core_login_shortcode_title'     => esc_html__( 'Core Login Shortcode', 'automation-web-platform' ),
				'core_login_shortcode_desc'      => esc_html__( 'Default method to render the Secure Passwordless Login form on any WordPress page.', 'automation-web-platform' ),
				'production_badge'               => esc_html__( 'Production', 'automation-web-platform' ),
				'dev_integration_title'          => esc_html__( 'Developer Integration', 'automation-web-platform' ),
				'dev_integration_desc'           => esc_html__( 'Seamlessly embed the login logic directly within your custom theme template files.', 'automation-web-platform' ),
				'select_logo_dialog_title'       => esc_html__( 'Select Logo', 'automation-web-platform' ),
				'use_this_logo_btn'              => esc_html__( 'Use this logo', 'automation-web-platform' ),
				'methods_group'                  => esc_html__( 'Methods', 'automation-web-platform' ),
				'verification_group'             => esc_html__( 'Verification', 'automation-web-platform' ),
				'navigation_group'               => esc_html__( 'Navigation', 'automation-web-platform' ),
				'wa_button_label'                => esc_html__( 'WA Button', 'automation-web-platform' ),
				'firebase_button_label'          => esc_html__( 'Firebase Button', 'automation-web-platform' ),
				'email_button_label'             => esc_html__( 'Email Button', 'automation-web-platform' ),
				'password_login_label'           => esc_html__( 'Password Login', 'automation-web-platform' ),
				'verify_action_label'            => esc_html__( 'Verify Action', 'automation-web-platform' ),
				'resend_button_label'            => esc_html__( 'Resend Button', 'automation-web-platform' ),
				'show_password_label'            => esc_html__( 'Show Password', 'automation-web-platform' ),
				'back_link_label'                => esc_html__( 'Back Link', 'automation-web-platform' ),
				'addExtension'                   => esc_html__( 'Add Extension', 'automation-web-platform' ),
				'noExtensions'                   => esc_html__( 'No extensions defined', 'automation-web-platform' ),
				'useCustomShortcodes'            => esc_html__( 'Use custom shortcodes to inject content before or after the form.', 'automation-web-platform' ),
				'customStylesActive'             => esc_html__( 'Custom Styles Active', 'automation-web-platform' ),
				'standardDesignActive'           => esc_html__( 'Standard design is active', 'automation-web-platform' ),
				'customStylesApplied'            => esc_html__( 'Your custom styles are being applied with high priority.', 'automation-web-platform' ),
				'customStylesInjected'           => esc_html__( 'Your custom styles will be injected into the footer and applied with high priority to override default layouts.', 'automation-web-platform' ),
			),
			'colorPresets'    => self::get_color_presets(),
		);
	}

	/**
	 * Get color presets.
	 *
	 * @return array
	 */
	public static function get_color_presets() {
		return array(
			'default'  => array(
				'name'   => __( 'Default (WhatsApp Green)', 'automation-web-platform' ),
				'colors' => array(
					'whatsapp_button_color'            => '#22c55e',
					'whatsapp_button_text_color'       => '#ffffff',
					'firebase_button_color'            => '#3b82f6',
					'firebase_button_text_color'       => '#ffffff',
					'email_otp_button_color'           => '#22c55e',
					'email_otp_button_text_color'      => '#ffffff',
					'verify_button_color'              => '#3b82f6',
					'verify_button_text_color'         => '#ffffff',
					'resend_button_color'              => '#64748b',
					'resend_button_text_color'         => '#ffffff',
					'password_login_button_color'      => '#ef4444',
					'password_login_button_text_color' => '#ffffff',
					'show_password_button_color'       => '#ef4444',
					'show_password_button_text_color'  => '#ffffff',
					'back_button_color'                => '#64748b',
					'back_button_text_color'           => '#ffffff',
				),
			),
			'wawp'     => array(
				'name'   => __( 'Wawp Official (Teal)', 'automation-web-platform' ),
				'colors' => array(
					'whatsapp_button_color'            => '#004444',
					'whatsapp_button_text_color'       => '#ffffff',
					'firebase_button_color'            => '#141b38',
					'firebase_button_text_color'       => '#ffffff',
					'email_otp_button_color'           => '#004444',
					'email_otp_button_text_color'      => '#ffffff',
					'verify_button_color'              => '#004444',
					'verify_button_text_color'         => '#ffffff',
					'resend_button_color'              => '#cbd5e1',
					'resend_button_text_color'         => '#0f172a',
					'password_login_button_color'      => '#141b38',
					'password_login_button_text_color' => '#ffffff',
					'show_password_button_color'       => '#141b38',
					'show_password_button_text_color'  => '#ffffff',
					'back_button_color'                => '#0f172a',
					'back_button_text_color'           => '#ffffff',
				),
			),
			'ocean'    => array(
				'name'   => __( 'Modern Ocean (Blue/Teal)', 'automation-web-platform' ),
				'colors' => array(
					'whatsapp_button_color'            => '#0891b2',
					'whatsapp_button_text_color'       => '#ffffff',
					'firebase_button_color'            => '#2563eb',
					'firebase_button_text_color'       => '#ffffff',
					'email_otp_button_color'           => '#0891b2',
					'email_otp_button_text_color'      => '#ffffff',
					'verify_button_color'              => '#2563eb',
					'verify_button_text_color'         => '#ffffff',
					'resend_button_color'              => '#64748b',
					'resend_button_text_color'         => '#ffffff',
					'password_login_button_color'      => '#0f172a',
					'password_login_button_text_color' => '#ffffff',
					'show_password_button_color'       => '#0f172a',
					'show_password_button_text_color'  => '#ffffff',
					'back_button_color'                => '#64748b',
					'back_button_text_color'           => '#ffffff',
				),
			),
			'midnight' => array(
				'name'   => __( 'Midnight (Dark/Purple)', 'automation-web-platform' ),
				'colors' => array(
					'whatsapp_button_color'            => '#7c3aed',
					'whatsapp_button_text_color'       => '#ffffff',
					'firebase_button_color'            => '#4f46e5',
					'firebase_button_text_color'       => '#ffffff',
					'email_otp_button_color'           => '#7c3aed',
					'email_otp_button_text_color'      => '#ffffff',
					'verify_button_color'              => '#4f46e5',
					'verify_button_text_color'         => '#ffffff',
					'resend_button_color'              => '#334155',
					'resend_button_text_color'         => '#ffffff',
					'password_login_button_color'      => '#1e1b4b',
					'password_login_button_text_color' => '#ffffff',
					'show_password_button_color'       => '#1e1b4b',
					'show_password_button_text_color'  => '#ffffff',
					'back_button_color'                => '#475569',
					'back_button_text_color'           => '#ffffff',
				),
			),
			'sunset'   => array(
				'name'   => __( 'Sunset (Orange/Red)', 'automation-web-platform' ),
				'colors' => array(
					'whatsapp_button_color'            => '#f97316',
					'whatsapp_button_text_color'       => '#ffffff',
					'firebase_button_color'            => '#ea580c',
					'firebase_button_text_color'       => '#ffffff',
					'email_otp_button_color'           => '#f97316',
					'email_otp_button_text_color'      => '#ffffff',
					'verify_button_color'              => '#ea580c',
					'verify_button_text_color'         => '#ffffff',
					'resend_button_color'              => '#94a3b8',
					'resend_button_text_color'         => '#ffffff',
					'password_login_button_color'      => '#7c2d12',
					'password_login_button_text_color' => '#ffffff',
					'show_password_button_color'       => '#7c2d12',
					'show_password_button_text_color'  => '#ffffff',
					'back_button_color'                => '#64748b',
					'back_button_text_color'           => '#ffffff',
				),
			),
			'minimal'  => array(
				'name'   => __( 'Minimal (Black/Gray)', 'automation-web-platform' ),
				'colors' => array(
					'whatsapp_button_color'            => '#0f172a',
					'whatsapp_button_text_color'       => '#ffffff',
					'firebase_button_color'            => '#1e293b',
					'firebase_button_text_color'       => '#ffffff',
					'email_otp_button_color'           => '#0f172a',
					'email_otp_button_text_color'      => '#ffffff',
					'verify_button_color'              => '#334155',
					'verify_button_text_color'         => '#ffffff',
					'resend_button_color'              => '#94a3b8',
					'resend_button_text_color'         => '#000000',
					'password_login_button_color'      => '#020617',
					'password_login_button_text_color' => '#ffffff',
					'show_password_button_color'       => '#020617',
					'show_password_button_text_color'  => '#ffffff',
					'back_button_color'                => '#94a3b8',
					'back_button_text_color'           => '#000000',
				),
			),
		);
	}

	/**
	 * Init hooks.
	 */
	public function init() {
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_scripts' ) );
		add_filter( 'wawp_frontend_global_vars', array( $this, 'add_frontend_global_vars' ) );
		add_action( 'init', array( $this, 'maybe_handle_magic_login' ), 20 );
		add_shortcode( 'wawp_otp_login', array( $this, 'render_otp_login_form' ) );
		add_filter( 'pre_update_option_wawp_otp_settings', array( $this, 'save_settings_to_db' ), 10 );
		$this->migrate_settings_to_db();
		add_filter( 'auth_cookie_expiration', array( $this, 'control_session_expiration' ), 20 );
		add_action( 'init', array( $this, 'enforce_session_expiration' ) );

		add_action(
			'admin_init',
			function () {
				$action = filter_input( INPUT_POST, 'action', FILTER_SANITIZE_SPECIAL_CHARS );
				if ( ! $action ) {
					$action = filter_input( INPUT_GET, 'action', FILTER_SANITIZE_SPECIAL_CHARS );
				}

				if ( defined( 'DOING_AJAX' ) && DOING_AJAX && $action && 0 === strpos( $action, 'wawp_' ) ) {
					nocache_headers();
					header( 'Expires: 0' );
				}
			},
			1
		);
	}

	/**
	 * Enqueue frontend scripts.
	 */
	public function enqueue_frontend_scripts() {
		wp_enqueue_style( 'remix-icon', WAWP_PLUGIN_URL . 'assets/css/resources/remixicon.css', array(), '4.6.0' );
		wp_enqueue_style( 'wawp-otp-frontend-styles', WAWP_PLUGIN_URL . 'assets/css/wawp-otp-frontend.css', array(), WAWP_PLUGIN_VERSION );
		wp_enqueue_script( 'wawp-otp-frontend-scripts', WAWP_PLUGIN_URL . 'assets/js/wawp-otp-frontend.js', array( 'jquery', 'wawp-global-data-hub' ), WAWP_PLUGIN_VERSION, true );

		$settings = $this->get_plugin_settings();
		if ( ! empty( $settings['enable_firebase_sms'] ) ) {
			wp_enqueue_script( 'firebase-app', WAWP_PLUGIN_URL . 'assets/js/resources/firebase-app-compat.js', array(), '9.1.1', true );
			wp_enqueue_script( 'firebase-auth', WAWP_PLUGIN_URL . 'assets/js/resources/firebase-auth-compat.js', array( 'firebase-app' ), '9.1.1', true );
		}
	}

	/**
	 * Add global variables to the central data hub.
	 *
	 * @param array $vars Global variables array.
	 * @return array
	 */
	public function add_frontend_global_vars( $vars ) {
		$settings = $this->get_plugin_settings();

		$vars['wawpOtpAjax'] = array(
			'ajax_url'           => add_query_arg( '_nocache', time(), admin_url( 'admin-ajax.php' ) ),
			'rest_url'           => esc_url_raw( rest_url( 'wawp/v1/otp-login' ) ),
			'nonce'              => wp_create_nonce( 'wp_rest' ),
			'emptyFields'        => esc_html__( 'Please fill in all required fields.', 'automation-web-platform' ),
			'first_login_method' => $settings['login_method'] ?? 'phone_login',
			'redirect_url'       => esc_url( $settings['redirect_url'] ?? home_url( '/' ) ),
			'button_colors'      => array(
				'whatsapp'       => esc_attr( $settings['whatsapp_button_color'] ),
				'firebase'       => esc_attr( $settings['firebase_button_color'] ),
				'email_otp'      => esc_attr( $settings['email_otp_button_color'] ),
				'password_login' => esc_attr( $settings['password_login_button_color'] ),
				'verify'         => esc_attr( $settings['verify_button_color'] ),
				'resend'         => esc_attr( $settings['resend_button_color'] ),
				'show_pass'      => esc_attr( $settings['show_password_button_color'] ),
				'back'           => esc_attr( $settings['back_button_color'] ),
			),
			'recaptcha_enabled'  => $this->get_wawp_setting( WAWP_Settings_Registry::GOOGLE_RECAPTCHA_ENABLE_WAWP_LOGIN ),
			'recaptcha_site_key' => $this->get_wawp_setting( WAWP_Settings_Registry::GOOGLE_RECAPTCHA_SITE_KEY ),
			'recaptcha_type'     => $this->get_wawp_setting( WAWP_Settings_Registry::GOOGLE_RECAPTCHA_TYPE, 'v2_invisible' ),
			'custom_shortcode'   => $settings['custom_shortcode'],
			'firebase_config'    => ( function () {
				if ( ! class_exists( 'WAWP_Firebase_Sender' ) && file_exists( WAWP_PLUGIN_DIR . 'includes/senders/class-wawp-firebase-sender.php' ) ) {
					include_once WAWP_PLUGIN_DIR . 'includes/senders/class-wawp-firebase-sender.php';
				}

				return class_exists( 'WAWP_Firebase_Sender' ) ? WAWP_Firebase_Sender::get_active_account() : array();
			} )(),
			'firebase_enabled'   => ! empty( $settings['enable_firebase_sms'] ),
			'is_rtl'             => is_rtl(),
			'initial_cooldown'   => $settings['initial_cooldown'] ?? 30,
			'max_cooldown'       => $settings['max_cooldown'] ?? 300,
			'polling_interval'   => $settings['polling_interval'] ?? 1500,
			'email_domains'      => $settings['email_domains'] ?? array( 'gmail.com', 'yahoo.com', 'outlook.com', 'hotmail.com', 'icloud.com' ),
		);

		$vars['wawpOtpL10n'] = array(
			'checkWhatsApp'        => esc_html__( 'Check your WhatsApp', 'automation-web-platform' ),
			'checkEmail'           => esc_html__( 'Check your Email', 'automation-web-platform' ),
			'weSentCode'           => esc_html__( 'We’ve sent you a 6-digit code to', 'automation-web-platform' ),
			'resendCode'           => esc_html__( 'Resend Code', 'automation-web-platform' ),
			/* translators: %s: seconds */
			'resendIn'             => esc_html__( 'You can resend in %s s', 'automation-web-platform' ),
			'checkSMS'             => esc_html__( 'Check your SMS', 'automation-web-platform' ),
			'sentTo'               => esc_html__( 'We’ve sent you a 6-digit code to', 'automation-web-platform' ),
			'editNumber'           => esc_html__( 'Edit number', 'automation-web-platform' ),
			'editEmail'            => esc_html__( 'Edit email', 'automation-web-platform' ),
			'firebaseNetworkError' => esc_html__( 'A network error occurred. If you are using Safari or Brave, please disable tracking protection (Shields) or try another browser.', 'automation-web-platform' ),
			'verifyYourIdentity'   => esc_html__( 'Verify Your Identity', 'automation-web-platform' ),
			'weSentSecureRequest'  => esc_html__( 'We sent a secure verification request to', 'automation-web-platform' ),
			'pleaseCheckDevice'    => esc_html__( 'Please check your device and approve it to continue.', 'automation-web-platform' ),
			'pleaseCheckInbox'     => esc_html__( 'Please check your inbox and click the link to continue.', 'automation-web-platform' ),
			'editNumberOrMethod'   => esc_html__( 'Edit number or use another method', 'automation-web-platform' ),
			'editEmailOrMethod'    => esc_html__( 'Edit email or use another method', 'automation-web-platform' ),
			'verified'             => esc_html__( 'Verified!', 'automation-web-platform' ),
			'redirectingDashboard' => esc_html__( 'Redirecting you to dashboard...', 'automation-web-platform' ),
			'pleaseEnterCode'      => esc_html__( 'Please enter the code.', 'automation-web-platform' ),
			'sendingCode'          => esc_html__( 'Sending code...', 'automation-web-platform' ),
			'codeResent'           => esc_html__( 'Code resent!', 'automation-web-platform' ),
			'loginRejectedEmail'   => esc_html__( 'Login request was rejected.', 'automation-web-platform' ),
			'loginRejectedPhone'   => esc_html__( 'Login request was rejected from your phone.', 'automation-web-platform' ),
		);

		return $vars;
	}

	/**
	 * Render OTP login form.
	 *
	 * @param array $atts Shortcode attributes.
	 * @return string
	 */
	public function render_otp_login_form( $atts = array() ) {
		static $instance_counter = 0;
		++$instance_counter;
		$uid  = $instance_counter; // Unique suffix for this render.
		$atts = shortcode_atts(
			array(
				'hide_signup_link' => 'false',
			),
			$atts,
			'wawp_otp_login'
		);

		$this->enqueue_frontend_scripts();
		wp_enqueue_style( 'wawp-frontend-css', WAWP_PLUGIN_URL . 'assets/css/wawp-frontend.css', array(), filemtime( WAWP_PLUGIN_DIR . 'assets/css/wawp-frontend.css' ) );

		if ( is_user_logged_in() ) {
			return esc_html__( 'You are already logged in.', 'automation-web-platform' );
		}

		$conn_status = WAWP_Connector()->get_connection_status();
		$site_active = is_array( $conn_status ) && ! empty( $conn_status['siteActive'] );

		$settings = $this->get_plugin_settings();
		if ( ! $site_active ) {
			// Force only the Email & Password method to be enabled if the site connection is not active.
			$settings['enable_whatsapp']       = 0;
			$settings['enable_firebase_sms']   = 0;
			$settings['enable_email']          = 0;
			$settings['enable_email_password'] = 1;
			$settings['login_method']          = 'email_login';
		}

		ob_start();

		global $wawp_recaptcha_rendered;
		if ( $this->get_wawp_setting( WAWP_Settings_Registry::GOOGLE_RECAPTCHA_ENABLE_WAWP_LOGIN ) && empty( $wawp_recaptcha_rendered['login'] ) ) {
			echo '<div class="wawp-recaptcha-container" id="wawp-recaptcha-login"></div>';
			$wawp_recaptcha_rendered['login'] = true;
		}

		echo '<div class="wawp-otp-login-form" data-wawp-instance="' . esc_attr( $uid ) . '">';
		WAWP_OTP_Service::get_instance()->render_dynamic_styles( $settings );

		if ( ! $site_active ) {
			echo '<div class="wawp-error-message" style="background-color: #fef2f2; border: 1px solid #fca5a5; color: #b91c1c; padding: 12px; border-radius: 6px; margin-bottom: 20px; font-size: 14px; text-align: center; direction: rtl;">';
			echo esc_html__( 'Site connection is not active. Local password login enabled.', 'automation-web-platform' );
			echo '</div>';
		}

		echo '<div class="wawp-login-branding">
			<div class="wawp-logo-container">';
		if ( ! empty( $settings['logo'] ) ) {
			echo '<div class="wawp-logo"><img src="' . esc_url( $settings['logo'] ) . '" alt=""/></div>';
		}
		echo '</div>';
		echo '<h3 class="wawp-login-title">' . esc_html( $settings['title'] ? $settings['title'] : esc_html__( 'Welcome back', 'automation-web-platform' ) ) . '</h3>';
		echo '<div class="wawp-login-description">' . wp_kses_post( $settings['description'] ? $settings['description'] : esc_html__( 'Choose a sign-in method to continue', 'automation-web-platform' ) ) . '</div>';
		echo '</div>';

		$enabled_groups = array();
		if ( ! empty( $settings['enable_whatsapp'] ) || ! empty( $settings['enable_firebase_sms'] ) ) {
			$enabled_groups[] = 'phone_login';
		}
		if ( ! empty( $settings['enable_email'] ) || ! empty( $settings['enable_email_password'] ) ) {
			$enabled_groups[] = 'email_login';
		}

		$first_group = $settings['login_method'] ?? 'phone_login';
		if ( $first_group ) {
			$k = array_search( $first_group, $enabled_groups, true );
			if ( false !== $k ) {
				unset( $enabled_groups[ $k ] );
				array_unshift( $enabled_groups, $first_group );
			}
		}

		if ( count( $enabled_groups ) > 1 ) {
			echo '<div class="wawp-tabs"><ul class="wawp-tab-list">';
			foreach ( $enabled_groups as $g ) {
				$active = ( $g === $first_group ) ? 'active' : '';
				$label  = ( 'phone_login' === $g ) ? esc_html__( 'Phone Login', 'automation-web-platform' ) : esc_html__( 'Email Login', 'automation-web-platform' );
				$icon   = ( 'phone_login' === $g ) ? 'ri-smartphone-line' : 'ri-mail-line';
				echo '<li class="wawp-tab ' . esc_attr( $active ) . '" data-tab="' . esc_attr( $g . '_' . $uid ) . '"><i class="' . esc_attr( $icon ) . '"></i> ' . esc_html( $label ) . '</li>';
			}
			echo '</ul></div>';
		}

		echo '<div class="wawp-tab-content">';
		if ( in_array( 'phone_login', $enabled_groups, true ) ) {
			$p_active = ( 'phone_login' === $first_group ) ? 'active' : '';
			echo '<div class="wawp-tab-pane ' . esc_attr( $p_active ) . '" id="phone_login_' . esc_attr( $uid ) . '">
                    <form id="wawp-otp-login-form-phone-' . esc_attr( $uid ) . '" class="wawp-merged-form wawp-phone-form">
                        <div class="wawp-form-group wawp-phone-group">
                            <label for="wawp_phone_' . esc_attr( $uid ) . '"><i class="ri-phone-line"></i> ' . esc_html__( 'Phone Number', 'automation-web-platform' ) . '</label>
                            <input type="tel" id="wawp_phone_' . esc_attr( $uid ) . '" name="phone" inputmode="numeric" pattern="[0-9]*" placeholder="' . esc_attr__( 'Enter your phone number', 'automation-web-platform' ) . '" required />
                        </div>
                        <div class="wawp-form-group wawp-hide wawp-otp-group-phone">
                            <label><i class="ri-shield-keyhole-line"></i> ' . esc_html__( 'Verification Code', 'automation-web-platform' ) . '</label>
                            <div class="wawp-otp-inputs" data-target="#wawp_otp_phone_' . esc_attr( $uid ) . '">
                                <input type="tel" inputmode="numeric" pattern="[0-9]*" maxlength="1"><input type="tel" inputmode="numeric" pattern="[0-9]*" maxlength="1"><input type="tel" inputmode="numeric" pattern="[0-9]*" maxlength="1">
                                <input type="tel" inputmode="numeric" pattern="[0-9]*" maxlength="1"><input type="tel" inputmode="numeric" pattern="[0-9]*" maxlength="1"><input type="tel" inputmode="numeric" pattern="[0-9]*" maxlength="1">
                            </div>
                            <input type="hidden" id="wawp_otp_phone_' . esc_attr( $uid ) . '" name="otp">
                        </div>
                        <div class="wawp-recaptcha-phone"></div>
                        <div id="wawp-firebase-recaptcha-phone" class="wawp-hide"></div>
                        <div class="wawp-form-group wawp-action-buttons">';
			if ( ! empty( $settings['enable_whatsapp'] ) ) {
				echo '<button type="button" class="wawp-btn wawp-btn-green wawp-request-btn wawp-whatsapp-btn" data-method="whatsapp"><i class="ri-whatsapp-line"></i> ' . esc_html__( 'Continue with WhatsApp', 'automation-web-platform' ) . '</button>';
			}
			if ( ! empty( $settings['enable_firebase_sms'] ) ) {
				echo '<button type="button" class="wawp-btn wawp-btn-blue wawp-request-btn wawp-firebase-btn" data-method="firebase"><i class="ri-message-3-line"></i> ' . esc_html__( 'Continue with SMS', 'automation-web-platform' ) . '</button>';
			}
			echo '<div class="wawp-verify-row wawp-hide wawp-verify-row-phone">
                                <button type="button" class="wawp-submit-button wawp-btn wawp-verify-btn wawp-verify-otp-phone">' . esc_html__( 'Confirm Code', 'automation-web-platform' ) . '</button>
                                <button type="button" class="wawp-resend-otp-btn wawp-btn wawp-resend-btn wawp-resend-otp-phone">' . esc_html__( 'Resend', 'automation-web-platform' ) . '</button>
                            </div>
                        </div>
                        <div class="wawp-form-group wawp-remember-me">
                            <label><div class="wawp-switch"><input type="checkbox" class="wawp-remember-phone-cb" name="remember" value="1" checked /><span class="wawp-slider"></span></div> ' . esc_html__( 'Remember Me', 'automation-web-platform' ) . '</label>
                        </div>
                        <div class="wawp-form-group wawp-hide wawp-otp-sent-message-phone">
                            <p class="wawp-otp-resend">' . esc_html__( 'Wrong number?', 'automation-web-platform' ) . ' <a class="wawp-edit-button wawp-edit-phone">' . esc_html__( 'Edit number', 'automation-web-platform' ) . '</a></p>
                        </div>
                        <div class="wawp-login-message-phone"></div>
                    </form>
                  </div>';
		}

		if ( in_array( 'email_login', $enabled_groups, true ) ) {
			$e_active             = ( 'email_login' === $first_group || 1 === count( $enabled_groups ) ) ? 'active' : '';
			$password_group_class = ( empty( $settings['enable_email'] ) && ! empty( $settings['enable_email_password'] ) ) ? '' : 'wawp-hide';
			echo '<div class="wawp-tab-pane ' . esc_attr( $e_active ) . '" id="email_login_' . esc_attr( $uid ) . '">
                    <form id="wawp-otp-login-form-email-' . esc_attr( $uid ) . '" class="wawp-merged-form js-wawp-email-form">
                        <div class="wawp-form-group js-wawp-email-group">
                            <label><i class="ri-user-line"></i> ' . esc_html__( 'Email or Username', 'automation-web-platform' ) . '</label>
                            <input type="text" id="wawp_merged_email_' . esc_attr( $uid ) . '" name="email" class="js-wawp-email-input" required />
                        </div>
                        <div class="wawp-form-group js-wawp-password-group ' . esc_attr( $password_group_class ) . '">
                            <label><i class="ri-lock-password-line"></i> ' . esc_html__( 'Password', 'automation-web-platform' ) . '</label>
                            <div class="password-container">
                                <input type="password" id="wawp_password_merged_' . esc_attr( $uid ) . '" name="password" class="js-wawp-password-input" />
                                <i class="ri-eye-line js-wawp-password-toggle"></i>
                            </div>
                        </div>
                        <div class="wawp-form-group js-wawp-otp-group-email wawp-hide">
                            <label><i class="ri-shield-keyhole-line"></i> ' . esc_html__( 'Verification Code', 'automation-web-platform' ) . '</label>
                            <div class="wawp-otp-inputs" data-target="#wawp_otp_email_' . esc_attr( $uid ) . '">
                                <input type="tel" inputmode="numeric" pattern="[0-9]*" maxlength="1"><input type="tel" inputmode="numeric" pattern="[0-9]*" maxlength="1"><input type="tel" inputmode="numeric" pattern="[0-9]*" maxlength="1">
                                <input type="tel" inputmode="numeric" pattern="[0-9]*" maxlength="1"><input type="tel" inputmode="numeric" pattern="[0-9]*" maxlength="1"><input type="tel" inputmode="numeric" pattern="[0-9]*" maxlength="1">
                            </div>
                            <input type="hidden" id="wawp_otp_email_' . esc_attr( $uid ) . '" name="otp" class="js-wawp-otp-input-email" />
                        </div>
                        <div class="wawp-form-group wawp-action-buttons">';
			if ( ! empty( $settings['enable_email'] ) ) {
				echo '<button type="button" class="wawp-btn wawp-btn-green js-wawp-request-otp-email wawp-email-otp-btn"><i class="ri-mail-send-line"></i> ' . esc_html__( 'Continue with Email', 'automation-web-platform' ) . '</button>';
			}
			if ( ! empty( $settings['enable_email_password'] ) ) {
				if ( ! empty( $settings['enable_email'] ) ) {
					echo '<button type="button" class="wawp-btn wawp-btn-red js-wawp-show-password-btn wawp-show-password-btn"><i class="ri-lock-password-line"></i> ' . esc_html__( 'Enter Password', 'automation-web-platform' ) . '</button>
                                  <button type="button" class="wawp-btn wawp-btn-red js-wawp-login-submit-password wawp-password-login-btn wawp-hide"><i class="ri-login-box-line"></i> ' . esc_html__( 'Login', 'automation-web-platform' ) . '</button>';
				} else {
					echo '<button type="button" class="wawp-btn wawp-btn-red js-wawp-login-submit-password wawp-password-login-btn"><i class="ri-login-box-line"></i> ' . esc_html__( 'Login', 'automation-web-platform' ) . '</button>';
				}
			}
			echo '<div class="wawp-verify-row js-wawp-verify-row-email wawp-hide">
                                <button type="button" class="wawp-btn wawp-btn-blue js-wawp-verify-otp-email wawp-verify-btn">' . esc_html__( 'Confirm OTP', 'automation-web-platform' ) . '</button>
                                <button type="button" class="wawp-resend-otp-btn wawp-btn js-wawp-resend-otp-email wawp-resend-btn">' . esc_html__( 'Resend', 'automation-web-platform' ) . '</button>
                            </div>
                        </div>
                        <div class="wawp-form-group wawp-remember-me">
                            <label><div class="wawp-switch"><input type="checkbox" class="wawp-remember-email-cb" name="remember" value="1" checked /><span class="wawp-slider"></span></div> ' . esc_html__( 'Remember Me', 'automation-web-platform' ) . '</label>
                        </div>
                        <div class="js-wawp-msg-box-email"></div>
                        <div class="wawp-form-group js-wawp-email-back-link wawp-hide">
                            <a href="#" class="js-wawp-back-to-email-options wawp-back-btn">' . esc_html__( 'Back to options', 'automation-web-platform' ) . '</a>
                        </div>
                    </form>
                  </div>';
		}
		echo '</div>';

		$signup_id = $this->get_wawp_setting( WAWP_Settings_Registry::SIGNUP_PAGE_ID );
		if ( $signup_id && ! is_page( $signup_id ) && 'true' !== $atts['hide_signup_link'] ) {
			/* translators: %s: Signup URL */
			echo '<p style="text-align: center; margin-top: 20px;">' . wp_kses_post( sprintf( __( "Don't have an account? <a href='%s'>Sign Up</a>", 'automation-web-platform' ), esc_url( get_permalink( $signup_id ) ) ) ) . '</p>';
		}

		if ( ! empty( $settings['custom_shortcode'] ) ) {
			echo '<div class="wawp-separator"><span>' . esc_html__( 'OR', 'automation-web-platform' ) . '</span></div>';
			echo '<div class="wawp-custom-shortcodes">';
			foreach ( $settings['custom_shortcode'] as $sc ) {
				if ( ! empty( $sc ) ) {
					echo '<div class="wawp-custom-shortcode">' . do_shortcode( $sc ) . '</div>';
				}
			}
			echo '</div>';
		}

		echo '</div>';

		return ob_get_clean();
	}

	/**
	 * AJAX request OTP return.
	 *
	 * @param array $data Request data.
	 * @return array|WP_Error
	 */
	public function ajax_request_otp_return( $data ) {
		$ip_address  = $this->get_client_ip();
		$cache_key   = 'wawp_otp_limit_' . md5( $ip_address );
		$limit_count = (int) wp_cache_get( $cache_key, 'wawp_security' );

		if ( $limit_count >= 5 ) {
			$this->log_action( 'failed', "Rate limit reached for IP: {$ip_address}", array( 'ip' => $ip_address ), 'auth' );
			return new WP_Error( 'rate_limit', esc_html__( 'Too many requests. Please try again later.', 'automation-web-platform' ), array( 'status' => 429 ) );
		}
		wp_cache_set( $cache_key, $limit_count + 1, 'wawp_security', 60 );

		if ( $this->get_wawp_setting( WAWP_Settings_Registry::GOOGLE_RECAPTCHA_ENABLE_WAWP_LOGIN ) && class_exists( 'WAWP_Google_Recaptcha' ) ) {
			$recaptcha = new WAWP_Google_Recaptcha();
			if ( ! $recaptcha->verify_token( $data['g-recaptcha-response'] ?? null ) ) {
				$this->log_action( 'failed', 'Recaptcha verification failed', array( 'ip' => $ip_address ), 'auth' );
				return new WP_Error( 'recaptcha_failed', esc_html__( 'Recaptcha verification failed.', 'automation-web-platform' ), array( 'status' => 403 ) );
			}
		}

		$method   = $data['login_method'] ?? '';
		$settings = $this->get_plugin_settings();

		$recipient = sanitize_text_field( wp_unslash( $data['whatsapp'] ?? $data['phone'] ?? $data['email'] ?? '' ) );
		if ( ! empty( $recipient ) && WAWP()->block_manager && WAWP()->block_manager->is_recipient_blocked( $recipient ) ) {
			// Log blocked request in the unified log.
			if ( class_exists( 'WAWP_Unified_Log' ) ) {
				WAWP()->unified_log->log_auth(
					null,
					'login_request',
					$method,
					'failed',
					array(
						'reason'    => esc_html__( 'Login request blocked: Recipient is blacklisted.', 'automation-web-platform' ),
						'recipient' => $recipient,
					)
				);
			}
			return new WP_Error( 'wawp_recipient_blocked', esc_html__( 'Recipient is blocked.', 'automation-web-platform' ), array( 'status' => 403 ) );
		}

		if ( 'whatsapp_otp' === $method || 'phone_whatsapp' === $method ) {
			if ( ! WAWP_Connector()->is_whatsapp_active() && ! WAWP_Connector()->is_meta_active() ) {
				return new WP_Error( 'wa_disabled', esc_html__( 'WhatsApp Sender is disabled.', 'automation-web-platform' ), array( 'status' => 400 ) );
			}

			return $this->handle_whatsapp_otp_return( $data, $settings );
		} elseif ( 'firebase_sms' === $method || 'phone_firebase' === $method ) {
			if ( ! WAWP_Connector()->is_firebase_active() ) {
				return new WP_Error( 'fb_disabled', esc_html__( 'Firebase is disabled.', 'automation-web-platform' ), array( 'status' => 400 ) );
			}

			$phone       = sanitize_text_field( wp_unslash( $data['phone'] ?? '' ) );
			$phone       = self::format_for_sms( $phone );
			[ $number, ] = $this->format_phone_number( $phone );
			$user        = WAWP()->user_manager->get_user_by_phone( $number );

			if ( ! $user ) {
				$this->log_action(
					'failed',
					"Login attempt for non-existent phone: {$number}",
					array(
						'phone'   => $number,
						'gateway' => 'firebase',
					),
					'auth'
				);
				$signup_id = $this->get_wawp_setting( WAWP_Settings_Registry::SIGNUP_PAGE_ID );
				if ( $signup_id ) {
					return new WP_Error(
						'no_user_redirect',
						esc_html__( 'No user found.', 'automation-web-platform' ),
						array(
							'status'             => 404,
							'redirect_to_signup' => add_query_arg( array( 'pre_phone' => rawurlencode( $number ) ), get_permalink( $signup_id ) ),
						)
					);
				}

				return new WP_Error( 'no_user', esc_html__( 'No user found.', 'automation-web-platform' ), array( 'status' => 404 ) );
			}

			return array(
				'success' => true,
				'message' => esc_html__( 'Firebase session started.', 'automation-web-platform' ),
			);
		} elseif ( 'email_otp' === $method ) {
			return $this->handle_email_otp_return( $data, $settings );
		} elseif ( 'email_password' === $method ) {
			return $this->handle_email_password_login_return( $data );
		}

		return new WP_Error( 'invalid_method', esc_html__( 'Invalid login method.', 'automation-web-platform' ), array( 'status' => 400 ) );
	}

	/**
	 * AJAX resend OTP return.
	 *
	 * @param array $params Request parameters.
	 * @return array|WP_Error
	 */
	public function ajax_resend_otp_return( $params ) {
		return $this->ajax_request_otp_return( $params );
	}

	/**
	 * Handle WhatsApp OTP return.
	 *
	 * @param array $params Request parameters.
	 * @param array $settings Settings.
	 * @return array|WP_Error
	 */
	private function handle_whatsapp_otp_return( $params, $settings ) {
		$whatsapp = isset( $params['whatsapp'] ) ? $params['whatsapp'] : ( isset( $params['phone'] ) ? $params['phone'] : '' );
		$whatsapp = sanitize_text_field( wp_unslash( $whatsapp ) );
		$whatsapp = self::format_for_sms( $whatsapp );

		if ( empty( $whatsapp ) ) {
			return new WP_Error( 'missing_wa', esc_html__( 'WhatsApp number is required.', 'automation-web-platform' ), array( 'status' => 400 ) );
		}

		[ $number, ] = $this->format_phone_number( $whatsapp );
		$user        = WAWP()->user_manager->get_user_by_phone( $number );

		if ( ! $user ) {
			$this->log_action(
				'failed',
				"Login attempt for non-existent phone: {$number}",
				array(
					'phone'   => $number,
					'gateway' => 'whatsapp',
				),
				'auth'
			);
			$signup_id = $this->get_wawp_setting( WAWP_Settings_Registry::SIGNUP_PAGE_ID );
			if ( $signup_id ) {
				return new WP_Error(
					'no_user_redirect',
					esc_html__( 'No user found.', 'automation-web-platform' ),
					array(
						'status'             => 404,
						'redirect_to_signup' => add_query_arg( array( 'pre_phone' => rawurlencode( $number ) ), get_permalink( $signup_id ) ),
					)
				);
			}

			return new WP_Error( 'no_user', esc_html__( 'No user found.', 'automation-web-platform' ), array( 'status' => 404 ) );
		}

		$challenge = WAWP_OTP_Service::get_instance()->send_challenge(
			$number,
			array(
				'method'   => 'whatsapp',
				'context'  => 'Login',
				'settings' => $settings,
				'user_id'  => $user->ID,
				'remember' => ! empty( $params['remember'] ),
			)
		);

		if ( ! $challenge['success'] ) {
			return new WP_Error( 'challenge_failed', $challenge['message'], array( 'status' => 400 ) );
		}

		return array(
			'success'            => true,
			'message'            => $challenge['message'],
			'otp_transient'      => $challenge['transient_key'],
			'whatsapp_auth_type' => $challenge['whatsapp_auth_type'] ?? 'otp',
		);
	}

	/**
	 * Handle Email OTP return.
	 *
	 * @param array $params Request parameters.
	 * @param array $settings Settings.
	 * @return array|WP_Error
	 */
	private function handle_email_otp_return( $params, $settings ) {
		$email = sanitize_email( $params['email'] ?? '' );
		if ( empty( $email ) || ! is_email( $email ) ) {
			return new WP_Error( 'invalid_email', esc_html__( 'Valid email is required.', 'automation-web-platform' ), array( 'status' => 400 ) );
		}

		$user = get_user_by( 'email', $email );
		if ( ! $user ) {
			$this->log_action(
				'failed',
				"Login attempt for non-existent email: {$email}",
				array(
					'email'   => $email,
					'gateway' => 'email',
				),
				'auth'
			);
			$signup_id = $this->get_wawp_setting( WAWP_Settings_Registry::SIGNUP_PAGE_ID );
			if ( $signup_id ) {
				return new WP_Error(
					'no_user_redirect',
					esc_html__( 'No user found.', 'automation-web-platform' ),
					array(
						'status'             => 404,
						'redirect_to_signup' => add_query_arg( array( 'pre_email' => rawurlencode( $email ) ), get_permalink( $signup_id ) ),
					)
				);
			}
			return new WP_Error( 'no_user', esc_html__( 'No user found.', 'automation-web-platform' ), array( 'status' => 404 ) );
		}

		$challenge = WAWP_OTP_Service::get_instance()->send_challenge(
			$email,
			array(
				'method'     => 'email',
				'context'    => 'Login',
				'settings'   => $settings,
				'user_id'    => $user->ID,
				'extra_data' => array(
					'user_id'  => $user->ID,
					'email'    => $email,
					'remember' => ! empty( $params['remember'] ),
				),
			)
		);

		if ( ! $challenge['success'] ) {
			return new WP_Error( 'challenge_failed', $challenge['message'], array( 'status' => 400 ) );
		}

		return array(
			'success'       => true,
			'message'       => esc_html__( 'Verification link sent to email.', 'automation-web-platform' ),
			'otp_transient' => $challenge['transient_key'],
			'is_magic_link' => true,
		);
	}

	/**
	 * Handle Email Password Login return.
	 *
	 * @param array $params Request parameters.
	 * @return array|WP_Error
	 */
	public function handle_email_password_login_return( $params ) {
		$user = wp_authenticate( sanitize_text_field( $params['login'] ?? $params['email'] ?? '' ), $params['password'] ?? '' );
		if ( is_wp_error( $user ) ) {
			$this->log_action( 'failed', 'Email/Password login failed for: ' . ( $params['login'] ?? $params['email'] ?? 'unknown' ), array( 'error' => $user->get_error_message() ), 'auth' );
			return $user;
		}

		$this->perform_user_login(
			$user,
			! empty( $params['remember'] ),
			'password'
		);

		return array(
			'success'      => true,
			'message'      => esc_html__( 'Logged in.', 'automation-web-platform' ),
			'redirect_url' => $this->get_redirect_url_for_user( $user ),
		);
	}

	/**
	 * Maybe handle magic login.
	 */
	public function maybe_handle_magic_login() {
		$query_string = isset( $_SERVER['QUERY_STRING'] ) ? sanitize_text_field( wp_unslash( $_SERVER['QUERY_STRING'] ) ) : '';
		wp_parse_str( $query_string, $query_args );

		$token_input = $query_args['wawp_magic_token'] ?? '';
		$magic_token = $token_input ? sanitize_text_field( $token_input ) : '';

		if ( ! $magic_token ) {
			return;
		}
		$token = $magic_token;
		$key   = ( strpos( $token, 'wawp_otp_' ) === 0 ) ? $token : 'wawp_magic_token_' . $token;

		$data = get_transient( $key );
		if ( ! $data || ( $data['status'] ?? '' ) !== 'verified' ) {
			return;
		}

		$user = get_userdata( is_array( $data ) ? ( $data['user_id'] ?? 0 ) : $data );
		if ( $user ) {
			if ( WAWP()->block_manager && WAWP()->block_manager->is_user_blocked( $user ) ) {
				// Log the blocked attempt in the unified log.
				if ( class_exists( 'WAWP_Unified_Log' ) ) {
					$method = is_array( $data ) ? ( $data['method'] ?? 'magic_link' ) : 'magic_link';
					WAWP()->unified_log->log_auth(
						$user->ID,
						'login',
						$method,
						'failed',
						array(
							'reason' => esc_html__( 'Magic Link login blocked: Account is blacklisted.', 'automation-web-platform' ),
							'email'  => $user->user_email,
						)
					);
				}
				wp_die( esc_html__( 'Your account is blocked.', 'automation-web-platform' ) );
			}

			$method = is_array( $data ) ? ( $data['method'] ?? 'magic_link' ) : 'magic_link';
			if ( 'whatsapp' === $method ) {
				WAWP()->user_manager->update_user_verification( $user->ID, 'whatsapp', true );
			} elseif ( 'firebase' === $method ) {
				WAWP()->user_manager->update_user_verification( $user->ID, 'firebase', true );
			} elseif ( 'email' === $method || 'magic_link' === $method ) {
				WAWP()->user_manager->update_user_verification( $user->ID, 'email', true );
			}

			$this->perform_user_login(
				$user,
				true,
				$method
			);
			if ( is_array( $data ) ) {
				$data['status'] = 'verified';
				set_transient( $key, $data, 30 );
			} else {
				delete_transient( $key );
			}
			$url = $this->get_redirect_url_for_user( $user );
			wp_safe_redirect( $url ? $url : home_url( '/' ) );
			exit;
		}
	}

	/**
	 * Handle verify OTP return.
	 *
	 * @param array $params Request parameters.
	 * @return array|WP_Error
	 */
	public function handle_verify_otp_return( $params ) {
		return WAWP_OTP_Service::get_instance()->verify_otp_return( $params, $this->get_plugin_settings(), array( $this, 'finalize_login' ) );
	}

	/**
	 * AJAX check auth status return.
	 *
	 * @param array $params Request parameters.
	 * @return array|WP_Error
	 */
	public function ajax_check_auth_status_return( $params ) {
		return WAWP_OTP_Service::get_instance()->check_challenge_status_return( $params, $this->get_plugin_settings(), array( $this, 'finalize_login' ) );
	}

	/**
	 * Finalize login.
	 *
	 * @param array $data Login data.
	 * @return array|WP_Error
	 */
	public function finalize_login( $data ) {
		$user = get_userdata( $data['user_id'] ?? 0 );
		if ( ! $user && ! empty( $data['recipient'] ) ) {
			if ( ( $data['method'] ?? '' ) === 'email' ) {
				$user = get_user_by( 'email', $data['recipient'] );
			} else {
				[ $digits, ] = $this->format_phone_number( $data['recipient'] );
				$user        = WAWP()->user_manager->get_user_by_phone( $digits );
			}
		}

		if ( $user ) {
			if ( WAWP()->block_manager && WAWP()->block_manager->is_user_blocked( $user ) ) {
				// Log the blocked attempt in the unified log.
				if ( class_exists( 'WAWP_Unified_Log' ) ) {
					$method = $data['method'] ?? 'otp';
					WAWP()->unified_log->log_auth(
						$user->ID,
						'login',
						$method,
						'failed',
						array(
							'reason' => esc_html__( 'OTP login blocked: Account is blacklisted.', 'automation-web-platform' ),
							'email'  => $user->user_email,
						)
					);
				}
				return new WP_Error(
					'wawp_user_blocked',
					esc_html__( 'Your account is blocked.', 'automation-web-platform' )
				);
			}

			$method = $data['method'] ?? 'otp';
			if ( in_array( $method, array( 'whatsapp', 'firebase' ), true ) ) {
				WAWP()->user_manager->update_user_verification( $user->ID, 'whatsapp', true );
			} elseif ( 'email' === $method || 'magic_link' === $method || is_email( $data['recipient'] ?? '' ) ) {
				WAWP()->user_manager->update_user_verification( $user->ID, 'email', true );
			}
			$this->perform_user_login(
				$user,
				! empty( $data['remember'] ),
				$data['method'] ?? 'otp'
			);

			return array(
				'success'      => true,
				'message'      => esc_html__( 'Logged in.', 'automation-web-platform' ),
				'verified'     => true,
				'redirect_url' => $this->get_redirect_url_for_user( $user ),
			);
		}

		if ( ( $data['method'] ?? '' ) === 'firebase' && ! empty( $data['phone'] ) ) {
			$signup_id = $this->get_wawp_setting( WAWP_Settings_Registry::SIGNUP_PAGE_ID );
			if ( $signup_id ) {
				return new WP_Error(
					'no_user_redirect',
					esc_html__( 'No user found.', 'automation-web-platform' ),
					array(
						'status'             => 404,
						'redirect_to_signup' => add_query_arg( array( 'pre_phone' => rawurlencode( $data['phone'] ) ), get_permalink( $signup_id ) ),
					)
				);
			}
		}

		return new WP_Error( 'no_user', esc_html__( 'No user found.', 'automation-web-platform' ), array( 'status' => 404 ) );
	}

	/**
	 * Handle verify Firebase token return.
	 *
	 * @param array $params Request parameters.
	 * @return array|WP_Error
	 */
	public function handle_verify_firebase_token_return( $params ) {
		return WAWP_OTP_Service::get_instance()->verify_firebase_return( $params, array( $this, 'finalize_login' ) );
	}

	/**
	 * AJAX log Firebase OTP return.
	 *
	 * @param array $params Request parameters.
	 * @return array|WP_Error
	 */
	public function ajax_log_firebase_otp_return( $params ) {
		$phone = sanitize_text_field( wp_unslash( $params['phone'] ?? '' ) );
		$phone = self::format_for_sms( $phone );
		if ( empty( $phone ) ) {
			return new WP_Error( 'missing_phone', esc_html__( 'Phone is required.', 'automation-web-platform' ), array( 'status' => 400 ) );
		}

		[ $number, ] = $this->format_phone_number( $phone );
		$user        = WAWP()->user_manager->get_user_by_phone( $number );

		$this->log_action(
			'success',
			'Firebase SMS sent.',
			array(
				'recipient'  => $number,
				'user_id'    => $user ? $user->ID : 0,
				'event_type' => 'Firebase Login',
			),
			'firebase'
		);

		return array( 'success' => true );
	}

	/**
	 * AJAX log frontend auth failures to Activity Hub.
	 *
	 * @param array $params Request parameters.
	 * @return array
	 */
	public function ajax_log_auth_failure( $params ) {
		$phone  = sanitize_text_field( wp_unslash( $params['phone'] ?? '' ) );
		$method = sanitize_text_field( wp_unslash( $params['method'] ?? 'firebase' ) );
		$error  = sanitize_text_field( wp_unslash( $params['error'] ?? 'Unknown authentication error.' ) );

		$number = '';
		$user   = null;
		if ( ! empty( $phone ) ) {
			$phone       = self::format_for_sms( $phone );
			[ $number, ] = $this->format_phone_number( $phone );
			$user        = WAWP()->user_manager->get_user_by_phone( $number );
		}

		if ( class_exists( 'WAWP' ) && isset( WAWP()->unified_log ) ) {
			WAWP()->unified_log->add_activity_log(
				array(
					'user_id'    => $user ? $user->ID : 0,
					'phone'      => ! empty( $number ) ? $number : $phone,
					'event_type' => 'login',
					'gateway'    => 'system',
					'status'     => 'failed',
					// translators: 1: Auth method name, 2: The error message details.
					'message'    => sprintf( __( '%1$s Auth Error: %2$s', 'automation-web-platform' ), ucfirst( $method ), $error ),
					'details'    => array(
						'method' => $method,
						'error'  => $error,
						'ip'     => $this->get_client_ip(),
					),
				)
			);
		}

		return array( 'success' => true );
	}

	/**
	 * Get redirect URL for user.
	 *
	 * @param WP_User $user User object.
	 * @return string
	 */
	private function get_redirect_url_for_user( $user ) {
		$settings = $this->get_plugin_settings();
		if ( ! empty( $settings['redirect_rules'] ) ) {
			foreach ( $settings['redirect_rules'] as $rule ) {
				if ( in_array( $rule['role'], $user->roles, true ) ) {
					return esc_url( $rule['redirect_url'] );
				}
			}
			foreach ( $settings['redirect_rules'] as $rule ) {
				if ( 'all' === $rule['role'] ) {
					return esc_url( $rule['redirect_url'] );
				}
			}
		}

		return '';
	}

	/**
	 * Perform user login.
	 *
	 * @param WP_User $user     User object.
	 * @param bool    $remember Remember me flag.
	 * @param string  $method   Login method.
	 */
	private function perform_user_login( $user, $remember, $method = 'otp' ) {
		update_user_meta( $user->ID, 'wawp_last_login_timestamp', time() );
		wp_set_current_user( $user->ID );
		wp_set_auth_cookie( $user->ID, $remember, is_ssl() );
		// Set hint for Unified Log method.
		if ( class_exists( 'WAWP_Unified_Log' ) ) {
			WAWP_Unified_Log::$current_login_method = $method;
		}

		do_action( 'wawp_user_logged_in', $user->ID );
		call_user_func( 'do_action', 'wp_login', $user->user_login, $user );
	}

	/**
	 * Control session expiration.
	 *
	 * @param int $expiration Expiration time.
	 * @return int
	 */
	public function control_session_expiration( $expiration ) {
		$settings = $this->get_plugin_settings();
		$type     = $settings['session_lifetime_type'] ?? 'lifetime';
		$value    = intval( $settings['session_lifetime_value'] ?? 0 );

		if ( 'lifetime' === $type || $value <= 0 ) {
			return $expiration;
		}

		switch ( $type ) {
			case 'minutes':
				return $value * MINUTE_IN_SECONDS;
			case 'hours':
				return $value * HOUR_IN_SECONDS;
			case 'days':
				return $value * DAY_IN_SECONDS;
		}

		return $expiration;
	}

	/**
	 * Enforce session expiration.
	 */
	public function enforce_session_expiration() {
		if ( ! is_user_logged_in() ) {
			return;
		}

		$login_time = get_user_meta( get_current_user_id(), 'wawp_last_login_timestamp', true );
		if ( ! $login_time ) {
			return;
		}

		$settings = $this->get_plugin_settings();
		$type     = $settings['session_lifetime_type'] ?? 'lifetime';
		$value    = intval( $settings['session_lifetime_value'] ?? 0 );

		if ( 'lifetime' === $type || $value <= 0 ) {
			return;
		}

		if ( 'minutes' === $type ) {
			$duration = $value * 60;
		} elseif ( 'hours' === $type ) {
			$duration = $value * 3600;
		} else {
			$duration = $value * 86400;
		}

		if ( time() > ( intval( $login_time ) + $duration ) ) {
			wp_logout();
			wp_safe_redirect( add_query_arg( 'wawp_session_expired', '1', home_url( add_query_arg( array(), $GLOBALS['wp']->request ) ) ) );
			exit;
		}
	}

	/**
	 * Table exists.
	 *
	 * @param string $table Table name.
	 * @return bool
	 */
	private function table_exists( string $table ): bool {
		return WAWP()->db->table_exists_cached( $table );
	}

	/**
	 * Migrate settings to DB.
	 */
	public function migrate_settings_to_db() {
		$table = WAWP()->db->tables['otp_login_settings'] ?? '';
		if ( ! $table ) {
			return;
		}

		if ( ! $this->table_exists( $table ) ) {
			return;
		}

		global $wpdb;
		$count = (int) WAWP()->db->get_results_cached( $wpdb->prepare( 'SELECT COUNT(*) FROM %i', $table ), 'wawp_otp_settings_count', 'wawp_otp', 3600 )[0]['COUNT(*)'] ?? 0;
		if ( $count > 0 ) {
			return;
		}

		$old = $this->get_wawp_setting( WAWP_Settings_Registry::OTP_SETTINGS );
		if ( $old ) {
			foreach ( $old as $k => $v ) {
				WAWP()->db->upsert_row(
					'otp_login_settings',
					array(
						'setting_name'  => $k,
						'setting_value' => maybe_serialize( $v ),
					)
				);
			}
			wp_cache_delete( 'wawp_otp_settings_raw', 'wawp_otp' );
		}
	}

	/**
	 * Save settings to DB.
	 *
	 * @param array $new_value New settings.
	 * @return mixed
	 */
	public function save_settings_to_db( $new_value ) {
		global $wpdb;
		$table = WAWP()->db->tables['otp_login_settings'] ?? '';
		if ( ! $table ) {
			return false;
		}

		WAWP()->db->truncate_row( 'otp_login_settings' );
		foreach ( $new_value as $name => $value ) {
			WAWP()->db->insert(
				'otp_login_settings',
				array(
					'setting_name'  => $name,
					'setting_value' => maybe_serialize( $value ),
				)
			);
		}
		wp_cache_delete( 'wawp_otp_settings_raw', 'wawp_otp' );

		// Keep wawp_auth_wa_instance in sync so get_option_mapping() never overwrites with a stale value.
		if ( isset( $new_value['instance'] ) ) {
			update_option( WAWP_Settings_Registry::AUTH_WA_INSTANCE, $new_value['instance'] );
		}

		return $new_value;
	}
}
