<?php

if ( ! class_exists( 'LoginPress_Limit_Login_Attempts_Main' ) ) :

	/**
	 * Main Class.
	 */
	class LoginPress_Limit_Login_Attempts_Main {

		/**
		 * Variable for LoginPress Limit Login Attempts table name.
		 *
		 * @var string $llla_table Custom table name for Limit Login Attempts.
		 * @since 3.0.0
		 */
		protected $llla_table;

		/** * * * * * * * * *
		 *
		 * @since  3.0.0
		 * @access private
		 * @var    bool
		 * * * * * * * * * * */
		private $wp_login_php;

		/**
		 * Variable that Check for LoginPress Key.
		 *
		 * @var string
		 * @since 6.0.0
		 */
		public $attempts_settings;

		/** * * * * * * * * * * * *
		 * Instance of this class.
		 *
		 * @since    3.0.0
		 * @var      object
		 * * * * * * * * * * * * * */
		protected static $llla_instance = null;

		/** * * * * * * * *
		 * Class constructor
		 * * * * * * * * * */
		public function __construct() {

			global $wpdb;
			$this->llla_table = $wpdb->prefix . 'loginpress_limit_login_details';
			$this->hooks();
			$this->includes();
		}

		/** * * * * * *
		 * Action hooks.
		 * * * * * * * */
		public function hooks() {
			add_action( 'rest_api_init', array( $this, 'lp_llla_register_routes' ) );
			// add_action( 'admin_init', array( $this, 'init_addon_updater' ), 0 );
			add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
			add_filter( 'loginpress_settings_tab', array( $this, 'loginpress_limit_login_attempts_tab' ), 10, 1 );
			add_filter( 'loginpress_settings_fields', array( $this, 'loginpress_limit_login_attempts_settings_array' ), 10, 1 );
			add_action( 'wp_ajax_loginpress_load_limit_login_tabs', array( $this, 'loginpress_load_limit_login_tabs' ) );
			add_action( 'wp_ajax_loginpress_limit_login_attempts_log_script', array( $this, 'loginpress_limit_login_attempts_log_callback' ) );
			add_action( 'wp_ajax_loginpress_limit_login_attempts_whitelist_script', array( $this, 'loginpress_limit_login_attempts_whitelist_callback' ) );
			add_action( 'wp_ajax_loginpress_limit_login_attempts_blacklist_script', array( $this, 'loginpress_limit_login_attempts_blacklist_callback' ) );
			add_action( 'loginpress_limit_login_attempts_log_script', array( $this, 'loginpress_limit_login_attempts_log_content' ) );
			add_action( 'loginpress_limit_login_attempts_whitelist_script', array( $this, 'loginpress_limit_login_attempts_whitelist_content' ) );
			add_action( 'loginpress_limit_login_attempts_blacklist_script', array( $this, 'loginpress_limit_login_attempts_blacklist_content' ) );

			$this->attempts_settings = get_option( 'loginpress_limit_login_attempts' );

			$limit_concurrent = isset( $this->attempts_settings['limit_concurrent_sessions'] ) ? sanitize_text_field( $this->attempts_settings['limit_concurrent_sessions'] ) : 'off';
			if ( 'on' === $limit_concurrent ) {
				add_action( 'authenticate', array( $this, 'loginpress_check_concurrent_sessions' ), 100, 3 );
			}
		}

		/**
		 * Register the rest routes for Limit-login-attempts
		 *
		 * @since  6.0.0
		 */
		public function lp_llla_register_routes() {
			// Get users with redirects
			register_rest_route(
				'loginpress/v1',
				'/limit-login-settings',
				array(
					'methods'             => 'GET',
					'callback'            => array( $this, 'loginpress_get_limit_login_settings' ),
					'permission_callback' => 'loginpress_rest_can_manage_options',
				)
			);
			register_rest_route(
				'loginpress/v1',
				'/limit-login-settings',
				array(
					'methods'             => 'POST',
					'callback'            => array( $this, 'loginpress_update_limit_login_settings' ),
					'permission_callback' => 'loginpress_rest_can_manage_options',
				)
			);
			register_rest_route(
				'loginpress/v1',
				'/login-attempts-logs',
				array(
					'methods'             => 'GET',
					'callback'            => array( $this, 'loginpress_get_login_attempts' ),
					'permission_callback' => 'loginpress_rest_can_manage_options',
				)
			);

			// Bulk actions
			register_rest_route(
				'loginpress/v1',
				'/login-attempts/bulk-action',
				array(
					'methods'             => 'POST',
					'callback'            => array( $this, 'loginpress_bulk_action_login_attempts' ),
					'permission_callback' => 'loginpress_rest_can_manage_options',
				)
			);

			// Clear all
			register_rest_route(
				'loginpress/v1',
				'/login-attempts/clear-all',
				array(
					'methods'             => 'POST',
					'callback'            => array( $this, 'loginpress_clear_all_login_attempts' ),
					'permission_callback' => 'loginpress_rest_can_manage_options',
				)
			);

			// Individual action
			register_rest_route(
				'loginpress/v1',
				'/login-attempts/action',
				array(
					'methods'             => 'POST',
					'callback'            => array( $this, 'loginpress_action_login_attempt' ),
					'permission_callback' => 'loginpress_rest_can_manage_options',
				)
			);

			register_rest_route(
				'loginpress/v1',
				'/whitelist-list',
				array(
					'methods'             => 'GET',
					'callback'            => array( $this, 'loginpress_get_whitelist' ),
					'permission_callback' => 'loginpress_rest_can_manage_options',
				)
			);

			register_rest_route(
				'loginpress/v1',
				'/whitelist-list/remove',
				array(
					'methods'             => 'POST',
					'callback'            => array( $this, 'loginpress_remove_from_whitelist' ),
					'permission_callback' => 'loginpress_rest_can_manage_options',
				)
			);

			register_rest_route(
				'loginpress/v1',
				'/whitelist-list/clear-all',
				array(
					'methods'             => 'POST',
					'callback'            => array( $this, 'loginpress_clear_whitelist' ),
					'permission_callback' => 'loginpress_rest_can_manage_options',
				)
			);

			// Blacklist endpoints (similar to whitelist)
			register_rest_route(
				'loginpress/v1',
				'/blacklist-list',
				array(
					'methods'             => 'GET',
					'callback'            => array( $this, 'loginpress_get_blacklist' ),
					'permission_callback' => 'loginpress_rest_can_manage_options',
				)
			);

			register_rest_route(
				'loginpress/v1',
				'/blacklist-list/remove',
				array(
					'methods'             => 'POST',
					'callback'            => array( $this, 'loginpress_remove_from_blacklist' ),
					'permission_callback' => 'loginpress_rest_can_manage_options',
				)
			);

			register_rest_route(
				'loginpress/v1',
				'/blacklist-list/clear-all',
				array(
					'methods'             => 'POST',
					'callback'            => array( $this, 'loginpress_clear_blacklist' ),
					'permission_callback' => 'loginpress_rest_can_manage_options',
				)
			);
			register_rest_route(
				'loginpress/v1',
				'/limit-login-add-ip',
				array(
					'methods'             => 'POST',
					'callback'            => array( $this, 'loginpress_rest_add_ip' ),
					'permission_callback' => 'loginpress_rest_can_manage_options',
				)
			);
		}

		/**
		 * Get limit login settings
		 *
		 * @since  6.0.0
		 */
		public function loginpress_get_limit_login_settings() {
			$settings = get_option( 'loginpress_limit_login_attempts', array() );
			return wp_parse_args( $settings, false );
		}

		/**
		 * Update limit login settings
		 *
		 * @since  6.0.0
		 */
		public function loginpress_update_limit_login_settings( WP_REST_Request $request ) {
			// Get the settings data sent from the frontend
			$new_settings = $request->get_json_params();

			// Make sure it's an array
			if ( ! is_array( $new_settings ) ) {
				return new WP_Error( 'invalid_data', 'Invalid settings data.', array( 'status' => 400 ) );
			}

			// Option name where the settings are stored
			$option_name = 'loginpress_limit_login_attempts';

			// Get the existing settings to preserve any missing keys
			$existing_settings = get_option( $option_name, array() );

			// Merge new settings into existing ones to preserve untouched settings
			$updated_settings = array_merge( $existing_settings, $new_settings );

			// Update the option
			update_option( $option_name, $updated_settings );

			return rest_ensure_response(
				array(
					'success' => true,
					'message' => 'Limit login settings updated successfully.',
				)
			);
		}

		/**
		 * Get all login attempts
		 *
		 * @since  6.0.0
		 */
		public function loginpress_get_login_attempts( WP_REST_Request $request ) {
			global $wpdb;
			$table_name = $this->llla_table;

			// $per_page = $request->get_param('per_page') ?: 10;
			$search = $request->get_param( 'search' ) ?: '';

			$search_sql = '';
			$params     = array();

			if ( ! empty( $search ) ) {
				$like       = '%' . $wpdb->esc_like( $search ) . '%';
				$search_sql = ' AND (ip LIKE %s OR username LIKE %s)';
				$params[]   = $like;
				$params[]   = $like;
			}

			$query = "
				SELECT * FROM {$table_name}
				WHERE (whitelist + blacklist) = 0
				{$search_sql}
				ORDER BY datentime DESC
			";

			// Prepare the full query with parameters
			$prepared_query = $wpdb->prepare( $query, ...$params );

			$results = $wpdb->get_results( $prepared_query );

			// Format the datetime before returning
			$formatted_results = array_map(
				function ( $item ) {
					return array(
						'id'           => (int) $item->id,
						'ip'           => sanitize_text_field( $item->ip ),
						'username'     => sanitize_text_field( $item->username ),
						'datentime'    => gmdate( 'm/d/Y H:i:s', (int) $item->datentime ),
						'gateway'      => sanitize_text_field( $item->gateway ),
						'login_status' => $item->login_status,
					// Add other fields if needed
					);
				},
				$results
			);

			return new WP_REST_Response( $formatted_results );
		}

		/**
		 * Bulk action callback
		 *
		 * @since  6.0.0
		 */
		public function loginpress_bulk_action_login_attempts( WP_REST_Request $request ) {
			global $wpdb;
			$table_name = $this->llla_table;

			$ids    = $request->get_param( 'ids' );
			$action = $request->get_param( 'action' );

			if ( empty( $ids ) || empty( $action ) ) {
				return new WP_Error( 'invalid_params', 'Invalid parameters', array( 'status' => 400 ) );
			}

			$ids              = array_map( 'intval', $ids );
			$ids_placeholders = implode( ',', array_fill( 0, count( $ids ), '%d' ) );

			// Step 1: Get unique IPs for the given IDs
			$ips = $wpdb->get_col(
				$wpdb->prepare(
					"SELECT DISTINCT ip FROM $table_name WHERE id IN ($ids_placeholders)",
					$ids
				)
			);

			if ( empty( $ips ) ) {
				return new WP_Error( 'no_ips_found', 'No IPs found for the provided IDs', array( 'status' => 404 ) );
			}

			// Step 2: Prepare placeholders for IPs
			$ips_placeholders = implode( ',', array_fill( 0, count( $ips ), '%s' ) );

			// Step 3: Run action based on IPs
			switch ( $action ) {
				case 'unlock':
					$wpdb->query(
						$wpdb->prepare(
							"DELETE FROM $table_name WHERE ip IN ($ips_placeholders)",
							$ips
						)
					);
					break;

				case 'whitelist':
					$wpdb->query(
						$wpdb->prepare(
							"UPDATE $table_name SET whitelist = 1 WHERE ip IN ($ips_placeholders)",
							$ips
						)
					);
					break;

				case 'blacklist':
					$wpdb->query(
						$wpdb->prepare(
							"UPDATE $table_name SET blacklist = 1 WHERE ip IN ($ips_placeholders)",
							$ips
						)
					);
					break;
			}

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


		/**
		 * Clear all login attempts
		 *
		 * @since  6.0.0
		 */
		public function loginpress_clear_all_login_attempts() {
			global $wpdb;
			$table_name = $this->llla_table;

			$query = $wpdb->prepare(
				"DELETE FROM {$table_name} WHERE (whitelist + blacklist) = %d",
				0
			);
			$wpdb->query( $query );

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

		/**
		 * Login attempts action (whitelist, blacklist, unclock) callback
		 *
		 * @since  6.0.0
		 */
		public function loginpress_action_login_attempt( WP_REST_Request $request ) {
			global $wpdb;
			$table_name = $this->llla_table;

			$ip     = $request->get_param( 'ip' );
			$action = $request->get_param( 'action' );

			if ( empty( $ip ) || empty( $action ) ) {
				return new WP_Error( 'invalid_params', 'Invalid parameters', array( 'status' => 400 ) );
			}

			switch ( $action ) {
				case 'unlock':
					$wpdb->query(
						$wpdb->prepare(
							"DELETE FROM {$table_name} WHERE ip = %s AND whitelist = %d AND blacklist = %d",
							$ip,
							0,
							0
						)
					);
					break;

				case 'whitelist':
					$wpdb->query(
						$wpdb->prepare(
							"UPDATE {$table_name} SET whitelist = %d WHERE ip = %s",
							1,
							$ip
						)
					);
					break;

				case 'blacklist':
					$wpdb->query(
						$wpdb->prepare(
							"UPDATE {$table_name} SET blacklist = %d WHERE ip = %s",
							1,
							$ip
						)
					);
					break;
			}

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

		/**
		 * Get all whitelist record
		 *
		 * @since  6.0.0
		 */
		public function loginpress_get_whitelist( WP_REST_Request $request ) {
			global $wpdb;
			$table_name = $this->llla_table;

			$per_page = absint( $request->get_param( 'per_page' ) ) ?: 10;
			$search   = sanitize_text_field( $request->get_param( 'search' ) ) ?: '';

			$query = "SELECT DISTINCT ip FROM $table_name WHERE whitelist = 1";

			if ( ! empty( $search ) ) {
				$query .= $wpdb->prepare( ' AND ip LIKE %s', '%' . $wpdb->esc_like( $search ) . '%' );
			}

			return $wpdb->get_results( $query );
		}

		/**
		 * Remove from whitelist table
		 *
		 * @since  6.0.0
		 */
		public function loginpress_remove_from_whitelist( WP_REST_Request $request ) {
			global $wpdb;
			$table_name = $this->llla_table;

			$ip = $request->get_param( 'ip' );

			if ( empty( $ip ) ) {
				return new WP_Error( 'missing_ip', __( 'Missing IP address.', 'loginpress-pro' ), array( 'status' => 400 ) );
			}

			$wpdb->query(
				$wpdb->prepare(
					"DELETE FROM {$table_name} WHERE ip = %s",
					$ip
				)
			);

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

		/**
		 * Clear whitelist table
		 *
		 * @since  6.0.0
		 */
		public function loginpress_clear_whitelist() {
			global $wpdb;
			$table_name = $this->llla_table;

			$wpdb->query(
				$wpdb->prepare(
					"UPDATE {$table_name} SET whitelist = %d WHERE whitelist = %d",
					0,
					1
				)
			);

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

		/**
		 * Get all blacklist entries
		 *
		 * @since  6.0.0
		 */
		public function loginpress_get_blacklist( WP_REST_Request $request ) {
			global $wpdb;
			$table_name = $this->llla_table;

			$per_page = absint( $request->get_param( 'per_page' ) ) ?: 10;
			$search   = sanitize_text_field( $request->get_param( 'search' ) ) ?: '';

			$query = "SELECT DISTINCT ip FROM $table_name WHERE blacklist = 1";

			if ( ! empty( $search ) ) {
				$query .= $wpdb->prepare( ' AND ip LIKE %s', '%' . $wpdb->esc_like( $search ) . '%' );
			}

			// $query .= " LIMIT $per_page";

			return $wpdb->get_results( $query );
		}

		/**
		 * Remove from blacklist table
		 *
		 * @since  6.0.0
		 */
		public function loginpress_remove_from_blacklist( WP_REST_Request $request ) {
			global $wpdb;
			$table_name = $this->llla_table;

			$ip = $request->get_param( 'ip' );

			if ( empty( $ip ) ) {
				return new WP_Error( 'missing_ip', __( 'Missing IP address.', 'loginpress-pro' ), array( 'status' => 400 ) );
			}

			$wpdb->query(
				$wpdb->prepare(
					"DELETE FROM {$table_name} WHERE ip = %s",
					$ip
				)
			);

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

		/**
		 * Clear blacklist table entries
		 *
		 * @since  6.0.0
		 */
		public function loginpress_clear_blacklist() {
			global $wpdb;
			$table_name = $this->llla_table;

			$wpdb->query(
				$wpdb->prepare(
					"UPDATE {$table_name} SET blacklist = %d WHERE blacklist = %d",
					0,
					1
				)
			);

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

		/**
		 * Add entry to whitelist or blacklist table
		 *
		 * @since  6.0.0
		 */
		public function loginpress_rest_add_ip( WP_REST_Request $request ) {
			global $wpdb;

			$ip           = $request->get_param( 'ip' );
			$list_type    = $request->get_param( 'list_type' );
			$current_time = current_time( 'timestamp' );

			if ( empty( $ip ) || ! filter_var( $ip, FILTER_VALIDATE_IP ) ) {
				return new WP_REST_Response(
					array( 'message' => __( 'Invalid or missing IP address.', 'loginpress-pro' ) ),
					400
				);
			}

			$table        = $this->llla_table; // replace with your actual table
			$exist_record = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $table WHERE ip = %s LIMIT 1", $ip ) );

			// Ensure only one record per IP
			if ( count( $exist_record ) > 0 ) {
				$id_to_keep = $exist_record[0]->id;
				$wpdb->query( $wpdb->prepare( "DELETE FROM $table WHERE ip = %s AND id != %d", $ip, $id_to_keep ) );
			}
			$exist_record = array_slice( $exist_record, 0, 1 );

			if ( $list_type === 'whitelist' ) {
				if ( count( $exist_record ) > 0 && $exist_record[0]->whitelist !== '1' ) {
					$wpdb->update(
						$table,
						array(
							'whitelist' => 1,
							'blacklist' => 0,
							'gateway'   => 'Manually',
						),
						array( 'ip' => $ip )
					);

					$action  = $exist_record[0]->blacklist === '1' ? 'move_black_to_white' : 'new_whitelist';
					$message = $action === 'move_black_to_white'
						? __( 'IP Address already existed, successfully moved from blacklist to whitelist.', 'loginpress-pro' )
						: __( 'Successfully added IP Address to whitelist.', 'loginpress-pro' );

					return new WP_REST_Response(
						array(
							'message' => $message,
							'action'  => $action,
						)
					);
				}

				if ( count( $exist_record ) === 0 ) {
					$wpdb->insert(
						$table,
						array(
							'ip'        => $ip,
							'whitelist' => 1,
							'datentime' => $current_time,
							'gateway'   => 'Manually',
						)
					);
					return new WP_REST_Response(
						array(
							'message' => __( 'Successfully added IP Address to whitelist.', 'loginpress-pro' ),
							'action'  => 'new_whitelist',
						)
					);
				}

				return new WP_REST_Response(
					array(
						'message' => __( 'IP Address already exists in whitelist.', 'loginpress-pro' ),
						'action'  => 'already_whitelist',
					)
				);
			}

			if ( $list_type === 'blacklist' ) {
				if ( count( $exist_record ) > 0 && $exist_record[0]->blacklist !== '1' ) {
					$wpdb->update(
						$table,
						array(
							'blacklist' => 1,
							'whitelist' => 0,
							'gateway'   => 'Manually',
						),
						array( 'ip' => $ip )
					);

					$action  = $exist_record[0]->whitelist === '1' ? 'move_white_to_black' : 'new_blacklist';
					$message = $action === 'move_white_to_black'
						? __( 'IP Address already existed, successfully moved from whitelist to blacklist.', 'loginpress-pro' )
						: __( 'Successfully added IP Address to blacklist.', 'loginpress-pro' );

					return new WP_REST_Response(
						array(
							'message' => $message,
							'action'  => $action,
						)
					);
				}

				if ( count( $exist_record ) === 0 ) {
					$wpdb->insert(
						$table,
						array(
							'ip'        => $ip,
							'blacklist' => 1,
							'datentime' => $current_time,
							'gateway'   => 'Manually',
						)
					);
					return new WP_REST_Response(
						array(
							'message' => __( 'Successfully added IP Address to blacklist.', 'loginpress-pro' ),
							'action'  => 'new_blacklist',
						)
					);
				}

				return new WP_REST_Response(
					array(
						'message' => __( 'IP Address already exists in blacklist.', 'loginpress-pro' ),
						'action'  => 'already_blacklist',
					)
				);
			}

			return new WP_REST_Response( array( 'message' => __( 'Invalid list type.', 'loginpress-pro' ) ), 400 );
		}

		/** * * * * * * * * * * * *
		 * LoginPress Addon updater
		 * * * * * * * * * * * * * */
		public function init_addon_updater() {

			if ( class_exists( 'LoginPress_AddOn_Updater' ) ) {

				$updater = new LoginPress_AddOn_Updater( 2328, LOGINPRESS_LIMIT_LOGIN_ROOT_FILE, $this->version );
			}
		}

		/** * * * * * *
		 * include files
		 *
		 * @since 3.0.0
		 * * * * * * * */
		public function includes() {

			include_once LOGINPRESS_LIMIT_LOGIN_DIR_PATH . 'classes/class-attempts.php';
			include_once LOGINPRESS_LIMIT_LOGIN_DIR_PATH . 'classes/class-ajax.php';
		}

		/**
		 * Load CSS and JS files at admin side on loginpress-settings page only.
		 *
		 * @param string $hook the Page ID.
		 * @return void
		 * @since  3.0.0
		 * @version 3.3.0
		 */
		public function admin_scripts( $hook ) {

			if ( 'toplevel_page_loginpress-settings' !== $hook ) {
				return;
			}

			wp_enqueue_style( 'loginpress_limit_login_stlye', LOGINPRESS_LIMIT_LOGIN_DIR_URL . 'assets/css/style.css', array(), LOGINPRESS_PRO_VERSION );
			wp_enqueue_style( 'loginpress_datatables_style', LOGINPRESS_PRO_DIR_URL . 'assets/css/jquery.dataTables.min.css', array(), LOGINPRESS_PRO_VERSION );
			wp_enqueue_script( 'loginpress_datatables_js', LOGINPRESS_PRO_DIR_URL . 'assets/js/jquery.dataTables.min.js', array( 'jquery' ), LOGINPRESS_PRO_VERSION, false );

			wp_enqueue_style( 'loginpress_data_tables_responsive', LOGINPRESS_PRO_DIR_URL . 'assets/css/rowReorder.dataTables.min.css', array(), LOGINPRESS_PRO_VERSION );

			wp_enqueue_script( 'loginpress_datatables_responsive_row', LOGINPRESS_PRO_DIR_URL . 'assets/js/dataTables.rowReorder.min.js', array( 'jquery' ), LOGINPRESS_PRO_VERSION, false );

			// wp_enqueue_script( 'loginpress_limit_main_js', LOGINPRESS_LIMIT_LOGIN_DIR_URL . 'assets/js/main.js', array( 'loginpress_datatables_js' ), LOGINPRESS_PRO_VERSION, false );
			wp_enqueue_style( 'datatables_buttons_css', 'https://cdn.datatables.net/buttons/2.3.6/css/buttons.dataTables.min.css', array(), '2.3.6' );
			wp_enqueue_script( 'datatables_buttons_js', 'https://cdn.datatables.net/buttons/2.3.6/js/dataTables.buttons.min.js', array( 'jquery' ), '2.3.6', true );
			wp_enqueue_script( 'datatables_buttons_html5_js', 'https://cdn.datatables.net/buttons/2.3.6/js/buttons.html5.min.js', array( 'jquery' ), '2.3.6', true );
			wp_enqueue_script( 'datatables_jszip_js', 'https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js', array(), '3.10.1', true );
		}


		/** * * * * * * * * * * * * * * * * * *
		 * Setting tab for Limit Login Attempts.
		 *
		 * @param  array $loginpress_tabs Rest of the settings tabs of LoginPress.
		 * @return array $limit_login_tab Limit Login Attempts tab.
		 * @since  3.0.0
		 * * * * * * * * * * * * * * * * * * * */
		public function loginpress_limit_login_attempts_tab( $loginpress_tabs ) {

			$_limit_login_tab = array(
				array(
					'id'         => 'loginpress_limit_login_attempts',
					'title'      => __( 'Limit Login Attempts', 'loginpress-pro' ),
					'sub-title'  => __( 'Limits for login attempts', 'loginpress-pro' ),
					/* translators: * %s: HTML tags */
					'desc'       => $this->tab_desc(),
					'video_link' => '1-L14gHC8R0',
				),
			);

			$limit_login_tab = array_merge( $loginpress_tabs, $_limit_login_tab );

			return $limit_login_tab;
		}

		/**
		 * Show the size of the login attempts log table in database based on the number of rows in a notification.
		 *
		 * @since 4.0.0
		 * @return string $size_in_mb The size of the table in MB
		 */
		public function loginpress_login_attempts_log_table_size() {
			$host              = isset( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : '';
			$request_uri       = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '';
			$current_page_url  = ( is_ssl() ? 'https://' : 'http://' ) . $host . $request_uri;
			$settings_page_url = home_url( '/wp-admin/admin.php?page=loginpress-settings' );

			// Only add filters if the user is logged out or on the settings page.
			if ( ! is_user_logged_in() || $current_page_url !== $settings_page_url ) {
				return;
			}
			global $wpdb;

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

			// Analyze the table to ensure accurate statistics
			$wpdb->query( "ANALYZE TABLE `{$table_name}`" );

			// Query to fetch the number of rows in the table
			$row_count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM `{$table_name}`" );

			// Define a threshold for the number of rows
			$row_threshold = 1000;

			// apply filters
			$row_threshold = apply_filters( 'loginpress_limit_login_attempts_row_threshold', $row_threshold );

			if ( $row_count < $row_threshold ) {
				return '';
			} else {
				return sprintf( // translators: Notice to optimize performance
					__( '%1$s Your logs table contains approximately %3$s%2$s rows %4$s. Consider clearing them to optimize database performance.%5$s', 'loginpress-pro' ),
					'<span class="loginpress_table_size_notify">',
					esc_html( number_format( $row_count ) ),
					'<strong>',
					'</strong>',
					'</span>'
				);
			}
		}

		/**
		 * The tab_desc description of the tab 'loginpress settings'
		 *
		 * @since 1.0.0
		 * @version 4.0.0
		 * @return html $html The tab description.
		 */
		public function tab_desc() {

			$notify = $this->loginpress_login_attempts_log_table_size();
			$html   = '';
			if ( ! empty( $notify ) ) {
				$html .= $notify; }
			// translators: Limit login attempts description
			$html .= sprintf( __( '%1$sThe Limit Login Attempts add-on helps you easily keep track of how many times each user tries to log in and limits the number of attempts they can make. This way, your website is protected from brute force attacks, when hackers try lots of passwords to get in. %2$s', 'loginpress-pro' ), '<p>', '</p>' );
			// translators: Tabs
			$html .= sprintf( __( '%1$s%3$sSettings%4$s %5$sAttempt Details%4$s %6$sWhitelist%4$s %7$sBlacklist%4$s%2$s', 'loginpress-pro' ), '<div class="loginpress-limit-login-tab-wrapper">', '</div>', '<a href="#loginpress_limit_login_settings" class="loginpress-limit-login-tab loginpress-limit-login-active">', '</a>', '<a href="#loginpress_limit_logs" class="loginpress-limit-login-tab">', '<a href="#loginpress_limit_login_whitelist" class="loginpress-limit-login-tab">', '<a href="#loginpress_limit_login_blacklist" class="loginpress-limit-login-tab">' );
			// Empty placeholders where content will be loaded dynamically
			$html .= '<div id="loginpress_limit_login_content"></div>';

			return $html;
		}

		/** * * * * * * * * * * * * * * * * * * * *
		 * Setting Fields for Limit Login Attempts.
		 *
		 * @param array $setting_array Settings fields of free version.
		 * @return array Limit Login Attempts settings fields.
		 * @since  3.0.0
		 * @version 6.0.0
		 * * * * * * * * * * * * * * * * * * * * * */
		public function loginpress_limit_login_attempts_settings_array( $setting_array ) {

			$_limit_login_settings = array(
				array(
					'name'    => 'attempts_allowed',
					'label'   => __( 'Attempts Allowed', 'loginpress-pro' ),
					'desc'    => __( 'Allowed Attempts In Numbers (How Many)', 'loginpress-pro' ),
					'type'    => 'number',
					'min'     => 1,
					'default' => '4',
				),
				array(
					'name'    => 'minutes_lockout',
					'label'   => __( 'Lockout Minutes', 'loginpress-pro' ),
					'desc'    => __( 'Lockout Minutes In Numbers (How Many)', 'loginpress-pro' ),
					'type'    => 'number',
					'min'     => 1,
					'default' => '20',
				),
				array(
					'name'              => 'lockout_message',
					'label'             => __( 'Lockout Message', 'loginpress-pro' ),
					'desc'              => __( 'Message for user(s) after reaching maximum login attempts.', 'loginpress-pro' ),
					'type'              => 'text',
					'default'           => '',
					'sanitize_callback' => 'sanitize_text',
				),
				array(
					'name'              => 'ip_add_remove',
					'label'             => __( 'IP Address', 'loginpress-pro' ),
					'type'              => 'text',
					'callback'          => array( $this, 'loginpress_ip_add_remove_callback' ),
					'sanitize_callback' => 'sanitize_text',
				),
				array(
					'name'  => 'disable_xml_rpc_request',
					'label' => __( 'Disable XML RPC Request', 'loginpress-pro' ),
					'desc'  => __( 'The XMLRPC is a system that allows remote updates to WordPress from other applications.', 'loginpress-pro' ),
					'type'  => 'checkbox',
				),
				array(
					'name'  => 'ip_intelligence',
					'label' => __( 'IP Intelligence', 'loginpress-pro' ),
					'desc'  => __( 'Enable IP Intelligence to detect brute force attacks and block suspicious IP addresses.', 'loginpress-pro' ),
					'type'  => 'checkbox',
				),
				// array( // Future setting.
				// 'name'  => 'disable_xml_ping_back',
				// 'label' => __( 'Disable Ping Back', 'loginpress-pro' ),
				// 'desc'  => __( 'Disable xml rpc ping back request', 'loginpress-pro' ),
				// 'type'  => 'checkbox',
				// ),.
				// array(
				// 'name'              => 'lockout_increase',
				// 'label'             => __( 'Lockout Increase lockout time to ', 'loginpress-pro' ),
				// 'desc'              => __( 'Description.', 'loginpress-pro' ),
				// 'type'              => 'number',
				// 'min'               => 0,
				// 'default'           => '3',
				// ).
			);

			$limit_login_settings = array( 'loginpress_limit_login_attempts' => $_limit_login_settings );

			return( array_merge( $limit_login_settings, $setting_array ) );
		}

		/** * * * * * * * * * * * * * * *
		 * Callback for Attempts log Tab.
		 *
		 * @since 3.0.0
		 * * * * * * * * * * * * * * * * */
		public function loginpress_limit_login_attempts_log_content() {

			$html = '<div id="loginpress_limit_logs">
			<div class="loginpress_llla_loader_inner"><img src="' . esc_url( LOGINPRESS_DIR_URL . 'img/loginpress-sniper.gif' ) . '" /></div>
			<div class="loginpress_limit_login_log_def">
				<div class="loginpress_limit_login_log_definition"><span class="loginpress-attempts-unlock"></span><p>' . __( 'Unlock/Deletes certain IP address from the database.', 'loginpress-pro' ) . '</p></div>
				<div class="loginpress_limit_login_log_definition"><span class="loginpress-attempts-whitelist"></span><p>' . __( 'Move certain IP address to whitelist so Login Attempts are not applied on them.', 'loginpress-pro' ) . '</p></div>
				<div class="loginpress_limit_login_log_definition"><span class="loginpress-attempts-blacklist"></span><p>' . __( 'Move certain IP address to blacklist so a certain IP address couldn\'t access your login page.', 'loginpress-pro' ) . '</p></div>
			</div>
				<div class="bulk_option_wrapper">
					<div class="bulk_option">
						<select id="loginpress_limit_bulk_blacklist">
							<option value="">' . __( 'Bulk Action', 'loginpress-pro' ) . '</option>
							<option value="unlock">' . __( 'Unlock', 'loginpress-pro' ) . '</option>
							<option value="white_list">' . __( 'White List', 'loginpress-pro' ) . '</option>
							<option value="black_list">' . __( 'Black List', 'loginpress-pro' ) . '</option>
						</select>
						<button id="loginpress_limit_bulk_blacklist_submit" class="button">' . esc_html__( 'submit', 'loginpress-pro' ) . '</button>
					</div>
					<div class="bulk_clear">
						<button id="loginpress_limit_bulk_attempts_submit" class="button">' . esc_html__( 'Clear All', 'loginpress-pro' ) . '</button>
					</div>
				</div>
				<div class="loginpress-edit-attempts-popup-containers llla_remove_all_popup">
				<div class="loginpress-edit-overlay"></div><div class="loginpress-edit-popup loginpress-link-duration-popup loginpress-llla-popup">
				<div class="llla_popup_heading"><img src="' . LOGINPRESS_LIMIT_LOGIN_DIR_URL . 'assets/img/llla_confirm.svg"><h3>' . esc_html__( 'Are you sure to delete all the entries?', 'loginpress-pro' ) . '</h3></div>
				<div class="loginpress-llla-duration-buttons">
					<button class="button button-primary loginpress_confirm_remove_all_attempts">' . esc_html__( 'Yes', 'loginpress-pro' ) . '</button>
					<button class="button button-primary limit-login-attempts-close-popup">' . esc_html__( 'No', 'loginpress-pro' ) . '</button>
				</div>
			</div>
				</div>
				<div class="row-per-page"><span>' . __( 'Show Entries', 'loginpress-pro' ) . '</span> <select id="loginpress_limit_login_log_select" class="selectbox"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select></div>
				<table id="loginpress_limit_login_log" class="display nowrap" cellspacing="0" width="100%">
        			<thead>
						<tr>
							<th><input type="checkbox" name="select_all" value="1" class="lla-select-all"></th>
							<th data-priority="1">' . __( 'IP', 'loginpress-pro' ) . '</th>
							<th>' . __( 'Date & Time', 'loginpress-pro' ) . '</th>
							<th>' . __( 'Username', 'loginpress-pro' ) . '</th>
							<th>' . __( 'Gateway', 'loginpress-pro' ) . '</th>
							<th data-priority="2">' . __( 'Action', 'loginpress-pro' ) . '</th>
						</tr>
          			</thead>
          			<tfoot>
						<tr>
							<th><input type="checkbox" name="select_all" value="1" class="lla-select-all"></th>
							<th>' . __( 'IP', 'loginpress-pro' ) . '</th>
							<th>' . __( 'Date & Time', 'loginpress-pro' ) . '</th>
							<th>' . __( 'Username', 'loginpress-pro' ) . '</th>
							<th>' . __( 'Gateway', 'loginpress-pro' ) . '</th>
							<th>' . __( 'Action', 'loginpress-pro' ) . '</th>
						</tr>
					</tfoot>
        			<tbody>';
			// if ( ! empty( $my_result ) ) {

			// foreach ( $my_result as $result ) {
			// $html .= '<tr id="loginpress_attempts_id_' . $result->id . '" data-login-attempt-user="' . $result->id . '" data-ip="' . $result->ip . '">';
			// $html .= '<th></th><td class="lg_attempts_ip"><div class="lp-tbody-cell">' . $result->ip . '</div></td>';
			// $html .= '<td class="loginpress_limit_login_log_dates"><div class="lp-tbody-cell">' . gmdate( 'm/d/Y H:i:s', (int) $result->datentime ) . '</div></td>';
			// $html .= '<td class="loginpress_limit_login_log_usernames"><div class="lp-tbody-cell"><span class="attempts-sniper"><img src="' . esc_url( LOGINPRESS_DIR_URL . 'img/loginpress-sniper.gif' ) . '" /></span>' . $result->username . '</div></td>';
			// $html .= '<td class="loginpress_limit_login_log_passwords"><div class="lp-tbody-cell">' . $result->password . '</div></td>';
			// $html .= '<td class="loginpress_limit_login_log_gateways"><div class="lp-tbody-cell">' . $result->gateway . '</div></td>';
			// $html .= '<td class="loginpress_limit_login_log_actions"><div class="lp-tbody-cell"> <div class="loginpress-attempts-unlock-wrapper"><input class="loginpress-attempts-unlock button button-primary" type="button" value="Unlock" /></div> <div class="loginpress-attempts-whitelist-wrapper"><input class="loginpress-attempts-whitelist button" type="button" value="Whitelist" /></div> <div class="loginpress-attempts-blacklist-wrapper"><input class="loginpress-attempts-blacklist button" type="button" value="Blacklist" /></div></div></td>';
			// $html .= '</tr>';

			// }
			// } else {
			// $html .= ''; // <h2>Not Found</h2>.
			// }
			$html .= '</tbody>
      			</table>
			</div>';
			echo $html; // @codingStandardsIgnoreLine.
		}

		function loginpress_load_limit_login_tabs() {
			check_ajax_referer( 'loginpress-user-llla-nonce', 'security' );

			if ( ! current_user_can( 'manage_options' ) ) {
				wp_die( 'No cheating, huh!' );
			}
			$html = '<div id="loginpress_limit_logs">
			<div class="loginpress_llla_loader_inner"><img src="' . esc_url( LOGINPRESS_DIR_URL . 'img/loginpress-sniper.gif' ) . '" /></div>
			<div class="loginpress_limit_login_log_def">
				<div class="loginpress_limit_login_log_definition"><span class="loginpress-attempts-unlock"></span><p>' . __( 'Unlock/Deletes certain IP address from the database.', 'loginpress-pro' ) . '</p></div>
				<div class="loginpress_limit_login_log_definition"><span class="loginpress-attempts-whitelist"></span><p>' . __( 'Move certain IP address to whitelist so Login Attempts are not applied on them.', 'loginpress-pro' ) . '</p></div>
				<div class="loginpress_limit_login_log_definition"><span class="loginpress-attempts-blacklist"></span><p>' . __( 'Move certain IP address to blacklist so a certain IP address couldn\'t access your login page.', 'loginpress-pro' ) . '</p></div>
			</div>
			<div class="bulk_option_wrapper">
				<div class="bulk_option">
					<select id="loginpress_limit_bulk_blacklist">
						<option value="">' . __( 'Bulk Action', 'loginpress-pro' ) . '</option>
						<option value="unlock">' . __( 'Unlock', 'loginpress-pro' ) . '</option>
						<option value="white_list">' . __( 'White List', 'loginpress-pro' ) . '</option>
						<option value="black_list">' . __( 'Black List', 'loginpress-pro' ) . '</option>
					</select>
					<button id="loginpress_limit_bulk_blacklist_submit" type="button" class="button">' . esc_html__( 'submit', 'loginpress-pro' ) . '</button>
				</div>
				<div class="bulk_clear">
					<button id="loginpress_limit_bulk_attempts_submit" type="button" class="button">' . esc_html__( 'Clear All', 'loginpress-pro' ) . '</button>
				</div>
			</div>
			<div class="loginpress-edit-attempts-popup-containers llla_remove_all_popup">
				<div class="loginpress-edit-overlay"></div>
				<div class="loginpress-edit-popup loginpress-link-duration-popup loginpress-llla-popup">
					<div class="llla_popup_heading"><img src="' . LOGINPRESS_LIMIT_LOGIN_DIR_URL . 'assets/img/llla_confirm.svg"><h3>' . esc_html__( 'Are you sure to delete all the entries?', 'loginpress-pro' ) . '</h3></div>
					<div class="loginpress-llla-duration-buttons">
						<button type="button" class="button button-primary loginpress_confirm_remove_all_attempts">' . esc_html__( 'Yes', 'loginpress-pro' ) . '</button>
						<button type="button" class="button button-primary limit-login-attempts-close-popup">' . esc_html__( 'No', 'loginpress-pro' ) . '</button>
					</div>
				</div>
			</div>
			<div class="row-per-page">
				<span>' . __( 'Show Entries', 'loginpress-pro' ) . '</span> 
				<select id="loginpress_limit_login_log_select" class="selectbox" style="width: 100px; height: 50px; margin: 5px;">
					<option value="10">10</option>
					<option value="25">25</option>
					<option value="50">50</option>
				</select>
			</div>
		</div>';

			// **Whitelist Tab Content**
			$html .= '<div id="loginpress_limit_login_whitelist_wrapper2">
		<div class="loginpress-edit-white-popup-containers llla_remove_all_popup">
		<div class="loginpress-edit-overlay"></div><div class="loginpress-edit-popup loginpress-link-duration-popup loginpress-llla-popup">
			<div class="llla_popup_heading"><img src="' . LOGINPRESS_LIMIT_LOGIN_DIR_URL . 'assets/img/llla_confirm.svg"><h3>' . esc_html__( 'Are you sure to delete all the entries?', 'loginpress-pro' ) . '</h3></div>
			<div class="loginpress-llla-duration-buttons">
				<button type="button" class="button button-primary loginpress_confirm_remove_all_whitelist">' . esc_html__( 'Yes', 'loginpress-pro' ) . '</button>
				<button type="button" class="button button-primary limit-login-attempts-close-popup">' . esc_html__( 'No', 'loginpress-pro' ) . '</button>
			</div>
		</div>
		</div>
		<div class="row-per-page"><span>' . __( 'Show Entries', 'loginpress-pro' ) . '</span> <select id="loginpress_limit_login_whitelist_select" class="selectbox" style="width: 100px; height: 50px; margin: 5px;"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select>
		<div class="bulk_option_wrapper">
			<button type="button" id="loginpress_limit_bulk_whitelists_submit" class="button">Clear All</button>
		</div>
		</div>
		</div>';

			// **Blacklist Tab Content**
			$html .= '<div id="loginpress_limit_login_blacklist_wrapper2">
		<div class="loginpress-edit-black-popup-containers llla_remove_all_popup">
		<div class="loginpress-edit-overlay"></div><div class="loginpress-edit-popup loginpress-link-duration-popup loginpress-llla-popup">
			<div class="llla_popup_heading"><img src="' . LOGINPRESS_LIMIT_LOGIN_DIR_URL . 'assets/img/llla_confirm.svg"><h3>' . esc_html__( 'Are you sure to delete all the entries?', 'loginpress-pro' ) . '</h3></div>
			<div class="loginpress-llla-duration-buttons">
				<button type="button" class="button button-primary loginpress_confirm_remove_all_blacklist">' . esc_html__( 'Yes', 'loginpress-pro' ) . '</button>
				<button type="button" class="button button-primary limit-login-attempts-close-popup">' . esc_html__( 'No', 'loginpress-pro' ) . '</button>
			</div>
		</div>
		</div>
		<div class="row-per-page"><span>' . __( 'Show Entries', 'loginpress-pro' ) . '</span> <select id="loginpress_limit_login_blacklist_select" class="selectbox" style="width: 100px; height: 50px; margin: 5px;"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select>
		<div class="bulk_option_wrapper">
			<button type="button" id="loginpress_limit_bulk_blacklists_submit" class="button">Clear All</button>
		</div>
		</div>';

			echo $html;
			wp_die();
		}

		/**
		 * Callback for blacklist tab.
		 *
		 * @since 3.0.0
		 * @version 3.3.0
		 */
		public function loginpress_limit_login_attempts_blacklist_callback() {

			check_ajax_referer( 'loginpress-user-llla-nonce', 'security' );

			if ( ! current_user_can( 'manage_options' ) ) {
				wp_die( 'No cheating, huh!' );
			}

			global $wpdb;

			$myblacklist = $wpdb->get_results( $wpdb->prepare( 'SELECT DISTINCT ip,blacklist FROM %1s WHERE `blacklist` = %d ORDER BY `datentime` DESC LIMIT 50', $this->llla_table, 1 ) );  // @codingStandardsIgnoreLine.
			$html        = '';
			// $html = '
			// <table id="loginpress_limit_login_blacklist" class="display" cellspacing="0" width="100%">

			// <thead>
			// <tr>
			// <th>' . __( 'IP', 'loginpress-pro' ) . '</th>
			// <th>' . __( 'Action', 'loginpress-pro' ) . '</th>
			// </tr>
			// </thead>
			// <tfoot>
			// <tr>
			// <th>' . __( 'IP', 'loginpress-pro' ) . '</th>
			// <th>' . __( 'Action', 'loginpress-pro' ) . '</th>
			// </tr>
			// </tfoot>
			// <tbody>';
			if ( $myblacklist ) {

				foreach ( $myblacklist as $blacklist ) {
					$html .= '<tr>';
					$html .= '<td class="loginpress_limit_login_blacklist_ips" data-blacklist-ip="' . $blacklist->ip . '"><div class="lp-tbody-cell">' . $blacklist->ip . '</div></td>';
					$html .= '<td class="loginpress_limit_login_blacklist_actions"><div class="lp-tbody-cell"><button class="loginpress-blacklist-clear button button-primary" type="button" value="Clear" ></button></div></td>';
					$html .= '</tr>';
				}
			} else {
				$html .= ''; // <h2>Not Found</h2>.
			}
			// $html .= '</tbody>
			// </table></div>';
			echo $html;  // @codingStandardsIgnoreLine.
			wp_die();
		}

		/** * * * * * * * * * * * * *
		 * Callback for Whitelist tab.
		 *
		 * @since 3.0.0
		 * @version 3.3.0
		 * * * * * * * * * * * * * * */
		public function loginpress_limit_login_attempts_whitelist_callback() {

			check_ajax_referer( 'loginpress-user-llla-nonce', 'security' );

			if ( ! current_user_can( 'manage_options' ) ) {
				wp_die( 'No cheating, huh!' );
			}

			global $wpdb;
			$my_whitelist = $wpdb->get_results( $wpdb->prepare( 'SELECT DISTINCT ip,whitelist FROM %1s WHERE `whitelist` = %d ORDER BY `datentime` DESC LIMIT 50', $this->llla_table, 1 ) );  // @codingStandardsIgnoreLine.
			$html         = '';
			// $html = '<table id="loginpress_limit_login_whitelist" class="display" cellspacing="0" width="100%">
			// <thead>
			// <tr>
			// <th>' . __( 'IP', 'loginpress-pro' ) . '</th>
			// <th>' . __( 'Action', 'loginpress-pro' ) . '</th>
			// </tr>
			// </thead>
			// <tfoot>
			// <tr>
			// <th>' . __( 'IP', 'loginpress-pro' ) . '</th>
			// <th>' . __( 'Action', 'loginpress-pro' ) . '</th>
			// </tr>
			// </tfoot>
			// <tbody>';
			if ( $my_whitelist ) {

				foreach ( $my_whitelist as $whitelist ) {
					$html .= '<tr>';
					$html .= '<td class="loginpress_limit_login_whitelist_ips" data-whitelist-ip="' . $whitelist->ip . '"><div class="lp-tbody-cell">' . $whitelist->ip . '</div></td>';
					$html .= '<td class="loginpress_limit_login_whitelist_actions"><div class="lp-tbody-cell"><button class="loginpress-whitelist-clear button button-primary" type="button" value="Clear" /></button></div></td>';
					$html .= '</tr>';
				}
			} else {
				$html .= ''; // <h2>Not Found</h2>.
			}
			// $html .= '</tbody>
			// </table></div>';
			echo $html; // @codingStandardsIgnoreLine.
			wp_die();
		}

		/**
		 * Callback for blacklist tab.
		 *
		 * @since 3.0.0
		 */
		public function loginpress_limit_login_attempts_blacklist_content() {

			// global $wpdb;

			// $myblacklist = $wpdb->get_results( $wpdb->prepare( 'SELECT DISTINCT ip,blacklist FROM %1s WHERE `blacklist` = %d ORDER BY `datentime` DESC LIMIT 50', $this->llla_table, 1 ) );  // @codingStandardsIgnoreLine.

			$html = '<div id="loginpress_limit_login_blacklist_wrapper2">
			<div class="loginpress-edit-black-popup-containers llla_remove_all_popup">
			<div class="loginpress-edit-overlay"></div><div class="loginpress-edit-popup loginpress-link-duration-popup loginpress-llla-popup">
				<div class="llla_popup_heading"><img src="' . LOGINPRESS_LIMIT_LOGIN_DIR_URL . 'assets/img/llla_confirm.svg"><h3>' . esc_html__( 'Are you sure to delete all the entries?', 'loginpress-pro' ) . '</h3></div>
				<div class="loginpress-llla-duration-buttons">
					<button class="button button-primary loginpress_confirm_remove_all_blacklist">' . esc_html__( 'Yes', 'loginpress-pro' ) . '</button>
					<button class="button button-primary limit-login-attempts-close-popup">' . esc_html__( 'No', 'loginpress-pro' ) . '</button>
				</div>
			</div>
			</div>
			<div class="row-per-page"><span>' . __( 'Show Entries', 'loginpress-pro' ) . '</span> <select id="loginpress_limit_login_blacklist_select" class="selectbox"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select>
			<div class="bulk_option_wrapper">
				<button id="loginpress_limit_bulk_blacklists_submit" class="button">Clear All</button>
			</div>
			</div>
			<table id="loginpress_limit_login_blacklist" class="display" cellspacing="0" width="100%">
			
				<thead>
					<tr>
						<th>' . __( 'IP', 'loginpress-pro' ) . '</th>
						<th>' . __( 'Action', 'loginpress-pro' ) . '</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<th>' . __( 'IP', 'loginpress-pro' ) . '</th>
						<th>' . __( 'Action', 'loginpress-pro' ) . '</th>
					</tr>
				</tfoot>
				<tbody>';
			// if ( $myblacklist ) {

			// foreach ( $myblacklist as $blacklist ) {
			// $html .= '<tr>';
			// $html .= '<td class="loginpress_limit_login_blacklist_ips" data-blacklist-ip="' . $blacklist->ip . '"><div class="lp-tbody-cell">' . $blacklist->ip . '</div></td>';
			// $html .= '<td class="loginpress_limit_login_blacklist_actions"><div class="lp-tbody-cell"><button class="loginpress-blacklist-clear button button-primary" type="button" value="Clear" ></button></div></td>';
			// $html .= '</tr>';
			// }
			// } else {
			// $html .= ''; // <h2>Not Found</h2>.
			// }
			$html .= '</tbody>
			</table></div>';
			echo $html;  // @codingStandardsIgnoreLine.
		}

		/** * * * * * * * * * * * * *
		 * Callback for Whitelist tab.
		 *
		 * @since 3.0.0
		 * * * * * * * * * * * * * * */
		public function loginpress_limit_login_attempts_whitelist_content() {

			// global $wpdb;
			// $my_whitelist = $wpdb->get_results( $wpdb->prepare( 'SELECT DISTINCT ip,whitelist FROM %1s WHERE `whitelist` = %d ORDER BY `datentime` DESC LIMIT 50', $this->llla_table, 1 ) );  // @codingStandardsIgnoreLine.

			$html = '<div id="loginpress_limit_login_whitelist_wrapper2">
			<div class="loginpress-edit-white-popup-containers llla_remove_all_popup">
			<div class="loginpress-edit-overlay"></div><div class="loginpress-edit-popup loginpress-link-duration-popup loginpress-llla-popup">
				<div class="llla_popup_heading"><img src="' . LOGINPRESS_LIMIT_LOGIN_DIR_URL . 'assets/img/llla_confirm.svg"><h3>' . esc_html__( 'Are you sure to delete all the entries?', 'loginpress-pro' ) . '</h3></div>
				<div class="loginpress-llla-duration-buttons">
					<button class="button button-primary loginpress_confirm_remove_all_whitelist">' . esc_html__( 'Yes', 'loginpress-pro' ) . '</button>
					<button class="button button-primary limit-login-attempts-close-popup">' . esc_html__( 'No', 'loginpress-pro' ) . '</button>
				</div>
			</div>
			</div>
			<div class="row-per-page"><span>' . __( 'Show Entries', 'loginpress-pro' ) . '</span> <select id="loginpress_limit_login_whitelist_select" class="selectbox"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select>
			<div class="bulk_option_wrapper">
				<button id="loginpress_limit_bulk_whitelists_submit" class="button">Clear All</button>
			</div>
			</div><table id="loginpress_limit_login_whitelist" class="display" cellspacing="0" width="100%">
				<thead>
					<tr>
						<th>' . __( 'IP', 'loginpress-pro' ) . '</th>
						<th>' . __( 'Action', 'loginpress-pro' ) . '</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<th>' . __( 'IP', 'loginpress-pro' ) . '</th>
						<th>' . __( 'Action', 'loginpress-pro' ) . '</th>
					</tr>
				</tfoot>
				<tbody>';
			// if ( $my_whitelist ) {

			// foreach ( $my_whitelist as $whitelist ) {
			// $html .= '<tr>';
			// $html .= '<td class="loginpress_limit_login_whitelist_ips" data-whitelist-ip="' . $whitelist->ip . '"><div class="lp-tbody-cell">' . $whitelist->ip . '</div></td>';
			// $html .= '<td class="loginpress_limit_login_whitelist_actions"><div class="lp-tbody-cell"><button class="loginpress-whitelist-clear button button-primary" type="button" value="Clear" /></button></div></td>';
			// $html .= '</tr>';
			// }
			// } else {
			// $html .= ''; // <h2>Not Found</h2>.
			// }
				$html .= '</tbody>
			</table></div>';
			echo $html; // @codingStandardsIgnoreLine.
		}

		/** * * * * * * * * * * * * * * *
		 * Callback for Attempts log Tab.
		 *
		 * @since 3.0.0
		 * @version 3.3.0
		 * * * * * * * * * * * * * * * * */
		public function loginpress_limit_login_attempts_log_callback() {

			check_ajax_referer( 'loginpress-user-llla-nonce', 'security' );

			if ( ! current_user_can( 'manage_options' ) ) {
				wp_die( 'No cheating, huh!' );
			}

			global $wpdb;
			// Get result from $this->llla_table where IP's aren't blaclisted or whitelisted.
			$my_result = $wpdb->get_results( $wpdb->prepare( "SELECT *, (whitelist+blacklist) as list FROM `{$this->llla_table}` HAVING list = %d ORDER BY `datentime` DESC LIMIT 50", 0 ) ); // @codingStandardsIgnoreLine.
			$html      = '';
			// $html = '
			// <table id="loginpress_limit_login_log" class="display nowrap" cellspacing="0" width="100%">
					// <thead>
					// <tr>
					// <th><input type="checkbox" name="select_all" value="1" class="lla-select-all"></th>
					// <th data-priority="1">' . __( 'IP', 'loginpress-pro' ) . '</th>
					// <th>' . __( 'Date & Time', 'loginpress-pro' ) . '</th>
					// <th>' . __( 'Username', 'loginpress-pro' ) . '</th>
					// <th>' . __( 'Gateway', 'loginpress-pro' ) . '</th>
					// <th data-priority="2">' . __( 'Action', 'loginpress-pro' ) . '</th>
					// </tr>
					// </thead>
					// <tfoot>
					// <tr>
					// <th><input type="checkbox" name="select_all" value="1" class="lla-select-all"></th>
					// <th>' . __( 'IP', 'loginpress-pro' ) . '</th>
					// <th>' . __( 'Date & Time', 'loginpress-pro' ) . '</th>
					// <th>' . __( 'Username', 'loginpress-pro' ) . '</th>
					// <th>' . __( 'Gateway', 'loginpress-pro' ) . '</th>
					// <th>' . __( 'Action', 'loginpress-pro' ) . '</th>
					// </tr>
					// </tfoot>
			// <tbody>';
			if ( ! empty( $my_result ) ) {

				foreach ( $my_result as $result ) {
					$html .= '<tr id="loginpress_attempts_id_' . $result->id . '" data-login-attempt-user="' . $result->id . '" data-ip="' . $result->ip . '">';
					$html .= '<th></th><td class="lg_attempts_ip"><div class="lp-tbody-cell">' . $result->ip . '</div></td>';
					$html .= '<td class="loginpress_limit_login_log_dates"><div class="lp-tbody-cell">' . gmdate( 'm/d/Y H:i:s', (int) $result->datentime ) . '</div></td>';
					$html .= '<td class="loginpress_limit_login_log_usernames"><div class="lp-tbody-cell"><span class="attempts-sniper"><img src="' . esc_url( LOGINPRESS_DIR_URL . 'img/loginpress-sniper.gif' ) . '" /></span>' . $result->username . '</div></td>';
					$html .= '<td class="loginpress_limit_login_log_gateways"><div class="lp-tbody-cell">' . $result->gateway . '</div></td>';
					$html .= '<td class="loginpress_limit_login_log_actions"><div class="lp-tbody-cell"> <div class="loginpress-attempts-unlock-wrapper"><input class="loginpress-attempts-unlock button button-primary" type="button" value="Unlock" /></div> <div class="loginpress-attempts-whitelist-wrapper"><input class="loginpress-attempts-whitelist button" type="button" value="Whitelist" /></div> <div class="loginpress-attempts-blacklist-wrapper"><input class="loginpress-attempts-blacklist button" type="button" value="Blacklist" /></div></div></td>';
					$html .= '</tr>';

				}
			} else {
				$html .= ''; // <h2>Not Found</h2>.
			}
			// $html .= '</tbody>
			// </table>
			// </div>';
			echo $html; // @codingStandardsIgnoreLine.
			wp_die();
		}

		/** * * * * * * * * *
		 * Main Instance
		 *
		 * @since 3.0.0
		 * @static
		 * @return object Main instance of the Class
		 * * * * * * * * * * */
		public static function instance() {

			if ( is_null( self::$llla_instance ) ) {
				self::$llla_instance = new self();
			}
			return self::$llla_instance;
		}

		/**
		 * Ip add or remove setting callback.
		 *
		 * @since 3.0.0
		 * @param array $args argument of setting.
		 * @return void $html
		 */
		public function loginpress_ip_add_remove_callback( $args ) {

			$size        = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
			$type        = isset( $args['type'] ) ? $args['type'] : 'text';
			$placeholder = empty( $args['placeholder'] ) ? '' : ' placeholder="' . $args['placeholder'] . '"';

			$whitelist = __( 'WhiteList', 'loginpress-pro' );
			$blacklist = __( 'BlackList', 'loginpress-pro' );
			$spinner   = '<span class="lla-spinner"><img src="' . esc_url( LOGINPRESS_DIR_URL . 'img/loginpress-sniper.gif' ) . '" /></span>';

			$html  = '<input type="' . $type . '" class="' . $size . '-text" id="' . $args['section'] . '[' . $args['id'] . ']" name="' . $args['section'] . '[' . $args['id'] . ']" value="" ' . $placeholder . '/>';
			$html .= '<p class="description"><button class="button loginpress-attempts-whitelist add_white_list" data-action="white_list" type="button">' . $whitelist . '</button><button class="button loginpress-attempts-blacklist add_black_list" data-action="black_list" type="button">' . $blacklist . ' </button>' . $spinner . '</p>';

			echo $html; // @codingStandardsIgnoreLine.
		}


		/**
		 * Limit concurrent sessions
		 *
		 * @since 6.0.0
		 * @return void
		 */
		public function loginpress_check_concurrent_sessions( $user, $username, $password ) {
			if ( is_wp_error( $user ) ) {
				return $user; // Skip if previous auth failed
			}

			$settings       = $this->attempts_settings;
			$user_roles     = $user->roles;
			$excluded_roles = ! empty( $settings['exclude_roles'] ) ? $settings['exclude_roles'] : array();

			$user_roles_lower     = array_map( 'strtolower', $user_roles );
			$excluded_roles_lower = array_map( 'strtolower', $excluded_roles );

			if ( array_intersect( $excluded_roles_lower, $user_roles_lower ) ) {
				return $user;
			}

			$max_sessions  = isset( $settings['max_session_count'] ) ? intval( $settings['max_session_count'] ) : 1;
			$sessions      = WP_Session_Tokens::get_instance( $user->ID );
			$session_count = count( $sessions->get_all() );
			if ( $session_count < $max_sessions ) {
				return $user; // Allow login
			}

			// Don't allow login
			return new WP_Error(
				'session_limit_exceeded',
				__( 'You have reached the maximum number of concurrent logins. Please log out from other devices/Screens to continue.', 'loginpress-pro' )
			);
		}
	}

endif;
