<?php
declare(strict_types=1);

namespace WPUltimateSecurity\UltimateSecurity\Modules\Authentication;

use WPUltimateSecurity\UltimateSecurity\Support\Helpers\Utils;
use WPUltimateSecurity\UltimateSecurity\Modules\TestMode\TestModeService;
use WPUltimateSecurity\UltimateSecurity\Support\Helpers\PluginDetection;
use WPUltimateSecurity\UltimateSecurity\Modules\Base\AbstractModule;

class LoginControl extends AbstractModule
{
	/**
	 * Module identifier.
	 */
	public const MODULE_ID = 'auth.login_control';

	/**
	 * Module version.
	 */
	protected const VERSION = '2.0.0';

	private static $is_login_page;

	/**
	 * Get the unique module identifier.
	 *
	 * @return string
	 */
	public static function getId(): string
	{
		return self::MODULE_ID;
	}

	/**
	 * Get the human-readable module name.
	 *
	 * @return string
	 */
	public static function getName(): string
	{
		return __('Login Control', 'ultimate-security');
	}

	/**
	 * Get the module domain.
	 *
	 * @return string
	 */
	public static function getDomain(): string
	{
		return 'authentication';
	}

	/**
	 * Boot the module (registers hooks and handlers).
	 *
	 * @return void
	 */
	public static function boot(): void
	{
		add_action('login_footer', [self::class, 'login_validation_script'], 9999);
		$ultimate_security_options = Utils::ultimate_security_get_option();

		$custom_login_url_enable = $ultimate_security_options['security']['login_security']['custom_login_url_enable'] ?? '0';

		$custom_login_url = (isset($ultimate_security_options['security']['login_security']['custom_login_url']) && sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['custom_login_url']))
		) ? sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['custom_login_url'])) : '';

		$current_banner_content_enable = (isset($ultimate_security_options['security']['login_security']['current_banner_content_enable']) && sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['current_banner_content_enable']))
		) ? sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['current_banner_content_enable'])) : 0;
		if ($custom_login_url_enable === '1' && isset($custom_login_url) && !empty($custom_login_url)) {
			add_filter('site_url', array(self::class, 'ultimate_security_login_control_site_url'), 10, 4);
			add_filter('network_site_url', array(self::class, 'ultimate_security_login_control_network_site_url'), 10, 3);
			add_filter('wp_redirect', array(self::class, 'ultimate_security_login_control_wp_redirect'), 10, 2);
			add_filter('site_option_ultimate_security_welcome_email_content', array(self::class, 'ultimate_security_welcome_email_content'));
			add_filter('user_request_action_email_content', array(self::class, 'ultimate_security_user_request_action_email_content'), 999, 2);
			remove_action('template_redirect', 'wp_redirect_admin_locations', 1000);
			add_filter('login_url', array(self::class, 'ultimate_security_login_control_login_url'), 10, 3);
			// Use early priority (1) to intercept login requests before WordPress processes them
			add_action('init', array(self::class, 'ultimate_security_is_login_check'), 1);
			add_action('wp_loaded', array(self::class, 'ultimate_security_redirect_user'));
		}
		if (isset($current_banner_content_enable) && $current_banner_content_enable) {
			add_action('login_form', array(self::class, 'ultimate_security_insert_banner_markup'), 50, 1);
			add_shortcode('ultimate-security-gdpr-banner', array(self::class, 'ultimate_security_banner_shortcode'));
		}

		add_filter('wpseo_exclude_from_sitemap_by_url', function ($urls) {
			$options = Utils::ultimate_security_get_option();
			$custom_login_slug = isset($options['security']['login_security']['custom_login_url'])
				? sanitize_text_field(wp_unslash($options['security']['login_security']['custom_login_url']))
				: '';
			if ($custom_login_slug) {
				$urls[] = home_url('/' . $custom_login_slug);
			}
			return $urls;
		});
	}
	public static function ultimate_security_is_login_check()
	{
		$ultimate_security_options = Utils::ultimate_security_get_option();

		$custom_login_url = (
			isset($ultimate_security_options['security']['login_security']['custom_login_url']) &&
			sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['custom_login_url']))
		) ? sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['custom_login_url'])) : '';

		$request = isset($_SERVER['REQUEST_URI']) ? wp_parse_url(rawurldecode(sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])))) : '';
		$request_string = isset($_SERVER['REQUEST_URI']) ? rawurldecode(sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI']))) : '';
		global $pagenow;


		if (!empty($custom_login_url)) {
			if (!is_multisite() && (strpos($request_string, 'wp-signup.php') !== false || strpos($request_string, 'wp-activate.php') !== false)) {
				// Test Mode: Log simulation instead of blocking
				if (TestModeService::shouldSimulate()) {
					TestModeService::logSimulation(
						'login_control',
						'signup_blocked',
						sprintf(
							esc_html__('Blocked access to %s or %s', 'ultimate-security'),
							'wp-signup.php',
							'wp-activate.php',
						),
						['request_uri' => $request_string]
					);
					return;
				}
				wp_die();
			}

			if ((strpos($request_string, 'wp-login.php') !== false || (isset($request['path']) && untrailingslashit($request['path']) === site_url('wp-login', 'relative'))) && !is_admin()) {
				// Test Mode: Log simulation instead of blocking
				if (TestModeService::shouldSimulate()) {
					TestModeService::logSimulation(
						'login_control',
						'login_hidden',
						sprintf(
							esc_html__('Hidden %s access attempt', 'ultimate-security'),
							'wp-login.php',
						),
						['request_uri' => $request_string, 'custom_login_url' => $custom_login_url]
					);
					return;
				}
				self::$is_login_page = true;
				$_SERVER['REQUEST_URI'] = self::ultimate_security_context_trailingslashit('/' . str_repeat('-/', 10));
				$pagenow = 'index.php'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited

			} elseif ((isset($request['path']) && untrailingslashit($request['path']) === home_url(self::ultimate_security_custom_login_slug(), 'relative')) || (!get_option('permalink_structure') && isset($_GET[self::ultimate_security_custom_login_slug()]) && empty($_GET[self::ultimate_security_custom_login_slug()]))) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
				$pagenow = 'wp-login.php'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited

			} elseif ((strpos($request_string, 'wp-register.php') !== false || (isset($request['path']) && untrailingslashit($request['path']) === site_url('wp-register', 'relative'))) && !is_admin()) {
				// Test Mode: Log simulation instead of blocking
				if (TestModeService::shouldSimulate()) {
					TestModeService::logSimulation(
						'login_control',
						'register_hidden',
						sprintf(
							esc_html__('Hidden %s access attempt', 'ultimate-security'),
							'wp-register.php',
						),
						['request_uri' => $request_string]
					);
					return;
				}
				self::$is_login_page = true;
				$_SERVER['REQUEST_URI'] = self::ultimate_security_context_trailingslashit('/' . str_repeat('-/', 10));
				$pagenow = 'index.php'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
			}
		}
	}


	public static function ultimate_security_redirect_user()
	{
		global $pagenow;
		$ultimate_security_options = Utils::ultimate_security_get_option();
		$custom_login_url = (isset($ultimate_security_options['security']['login_security']['custom_login_url']) && sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['custom_login_url']))
		) ? sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['custom_login_url'])) : '';

		$custom_login_redirect = (isset($ultimate_security_options['security']['login_security']['custom_login_redirect']) && sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['custom_login_redirect']))
		) ? sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['custom_login_redirect'])) : '';
		$request = isset($_SERVER['REQUEST_URI']) ? wp_parse_url(rawurldecode(sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])))) : '';

		if (!empty($custom_login_url)) {
			// Serve the login page when custom login URL is accessed
			$request_path = isset($request['path']) ? untrailingslashit($request['path']) : '';
			$custom_login_path = untrailingslashit(home_url(self::ultimate_security_custom_login_slug(), 'relative'));

			// Check for permalink structure
			if (get_option('permalink_structure')) {
				// With permalinks: /custom-slug/
				if ($request_path === $custom_login_path || $request_path === '/' . $custom_login_path) {
					// Serve the WordPress login page
					global $error, $interim_login, $action, $user_login;
					$wp_login_file = ABSPATH . 'wp-login.php';
					if (file_exists($wp_login_file)) {
						include_once $wp_login_file;
					}
					die;
				}
			} else {
				// Without permalinks: ?custom-slug
				if (isset($_GET[$custom_login_url]) && empty($_GET[$custom_login_url])) {
					// Serve the WordPress login page
					global $error, $interim_login, $action, $user_login;
					$wp_login_file = ABSPATH . 'wp-login.php';
					if (file_exists($wp_login_file)) {
						include_once $wp_login_file;
					}
					die;
				}
			}

			// Redirect unauthenticated users from wp-admin to old login page redirect URL
			if (is_admin() && !is_user_logged_in() && !defined('DOING_AJAX')) {
				// Test Mode: Log simulation instead of redirecting
				if (TestModeService::shouldSimulate()) {
					TestModeService::logSimulation(
						'login_control',
						'admin_redirect',
						esc_html__('Redirected unauthenticated user from admin area', 'ultimate-security'),
						['redirect_to' => $custom_login_redirect ?: '/']
					);
					return;
				}
				if (empty($custom_login_redirect) || !$custom_login_redirect) {
					wp_safe_redirect(home_url('/'));
				} else {
					wp_safe_redirect(home_url('/' . rtrim($custom_login_redirect, '/')));
				}
				die();
			}

			// Redirect from old wp-login.php to old login page redirect URL
			if ('wp-login.php' === $pagenow && get_option('permalink_structure')) {
				$query_string = !empty($_SERVER['QUERY_STRING']) ? sanitize_text_field(wp_unslash($_SERVER['QUERY_STRING'])) : '';
				$redirect_url = !empty($custom_login_redirect) ? home_url('/' . rtrim($custom_login_redirect, '/')) : home_url('/');
				if ($query_string) {
					$redirect_url = esc_url_raw($redirect_url . '?' . $query_string);
				}
				wp_safe_redirect($redirect_url);
				die;
			}

			// Redirect from old wp-login.php without permalinks to old login page redirect URL
			if (!get_option('permalink_structure') && 'wp-login.php' === $pagenow) {
				$query_string = !empty($_SERVER['QUERY_STRING']) ? sanitize_text_field(wp_unslash($_SERVER['QUERY_STRING'])) : '';
				$redirect_url = !empty($custom_login_redirect) ? home_url('/' . rtrim($custom_login_redirect, '/')) : home_url('/');
				if ($query_string) {
					$redirect_url = esc_url_raw($redirect_url . '&' . $query_string);
				}
				wp_safe_redirect($redirect_url);
				die;
			} elseif (self::$is_login_page) {
				// Check for wp-activate.php referer (multisite activation flow)
				$referer_url = wp_get_referer();

				if ($referer_url && is_string($referer_url)) {
					$referer_parts = wp_parse_url($referer_url);

					if (
						strpos($referer_url, 'wp-activate.php') !== false &&
						!empty($referer_parts['query'])
					) {
						$referer_query = [];
						parse_str($referer_parts['query'], $referer_query);

						if (!empty($referer_query['key'])) {
							$activation_key = sanitize_text_field($referer_query['key']);
							$result = wpmu_activate_signup($activation_key);

							if (
								is_wp_error($result) &&
								in_array($result->get_error_code(), ['already_active', 'blog_taken'], true)
							) {
								$redirect_url = self::custom_login_url();

								if (!empty($_SERVER['QUERY_STRING'])) {
									$query_string = sanitize_text_field(wp_unslash($_SERVER['QUERY_STRING']));
									$redirect_url = add_query_arg(null, null, $redirect_url . '?' . $query_string);
								}

								wp_safe_redirect($redirect_url);
								exit;
							}
						}
					}
				}

				// Direct access to hidden login page - redirect to configured URL or home
				// Test Mode: Log simulation instead of redirecting
				if (TestModeService::shouldSimulate()) {
					TestModeService::logSimulation(
						'login_control',
						'login_page_redirect',
						esc_html__('Redirected from hidden login page', 'ultimate-security'),
						['redirect_to' => $custom_login_redirect ?: '/']
					);
					return;
				}
				if (empty($custom_login_redirect) || !$custom_login_redirect) {
					wp_safe_redirect(home_url('/'));
				} else {
					wp_safe_redirect(home_url('/' . rtrim($custom_login_redirect, '/')));
				}
				die();
			}
		}
	}

	private static function ultimate_security_load_login_template()
	{
		global $pagenow;
		$pagenow = 'index.php'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
		if (!defined('WP_USE_THEMES')) {
			define('WP_USE_THEMES', true);
		}
		wp();
		if (isset($_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_URI'] === self::ultimate_security_context_trailingslashit(str_repeat('-/', 10))) {
			$_SERVER['REQUEST_URI'] = self::ultimate_security_context_trailingslashit('/wp-login-php/');
		}
		include_once ABSPATH . WPINC . '/template-loader.php';
		die;
	}

	private static function ultimate_security_trailing_slashes_needed()
	{
		return '/' === substr(get_option('permalink_structure'), -1, 1);
	}


	private static function ultimate_security_context_trailingslashit($incoming_string)
	{
		return self::ultimate_security_trailing_slashes_needed() ? trailingslashit($incoming_string) : untrailingslashit($incoming_string);
	}

	private static function ultimate_security_custom_login_slug()
	{
		$ultimate_security_options = Utils::ultimate_security_get_option();
		$slug = (isset($ultimate_security_options['security']['login_security']['custom_login_url']) && sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['custom_login_url']))
		) ? sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['custom_login_url'])) : '';

		if (is_multisite() && is_plugin_active_for_network(ULTIMATE_SECURITY_NAME)) {
			return $slug;
		} else {
			return $slug;
		}
	}

	public static function custom_login_url($scheme = null)
	{
		if (get_option('permalink_structure')) {
			return self::ultimate_security_context_trailingslashit(home_url('/', $scheme) . self::ultimate_security_custom_login_slug());
		} else {
			return home_url('/', $scheme) . '?' . self::ultimate_security_custom_login_slug();
		}
	}

	public static function ultimate_security_login_control_login_url_filter($url, $scheme = null)
	{
		if (strpos($url, 'wp-login.php') !== false) {
			if (is_ssl()) {
				$scheme = 'https';
			}
			$args = explode('?', $url);
			if (isset($args[1])) {
				parse_str($args[1], $args);
				$url = esc_url_raw(add_query_arg($args, self::custom_login_url($scheme)));
			} else {
				$url = self::custom_login_url($scheme);
			}
		}
		return $url;
	}

	public static function ultimate_security_login_control_site_url($url, $path, $scheme, $blog_id)
	{
		return self::ultimate_security_login_control_login_url_filter($url, $scheme);
	}

	public static function ultimate_security_login_control_network_site_url($url, $path, $scheme)
	{
		return self::ultimate_security_login_control_login_url_filter($url, $scheme);
	}

	public static function ultimate_security_login_control_wp_redirect($location, $status)
	{
		return self::ultimate_security_login_control_login_url_filter($location);
	}

	public static function ultimate_security_login_control_login_url($login_url, $redirect, $force_reauth)
	{
		if (is_404()) {
			return '#';
		}

		if (false === $force_reauth) {
			return $login_url;
		}

		if (empty($redirect)) {
			return $login_url;
		}

		$redirect = explode('?', $redirect);

		if (isset($redirect[0]) && admin_url('options.php') === $redirect[0]) {
			$login_url = admin_url();
		}

		return $login_url;
	}


	public static function ultimate_security_welcome_email_content($value)
	{
		$ultimate_security_options = Utils::ultimate_security_get_option();
		$custom_login_url = (isset($ultimate_security_options['security']['login_security']['custom_login_url']) && sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['custom_login_url']))
		) ? sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['custom_login_url'])) : '';
		return str_replace('wp-login.php', trailingslashit($custom_login_url), $value);
	}

	public static function ultimate_security_user_request_action_email_content($email_text, $email_data)
	{
		$ultimate_security_options = Utils::ultimate_security_get_option();
		$custom_login_url = (isset($ultimate_security_options['security']['login_security']['custom_login_url']) && sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['custom_login_url']))
		) ? sanitize_text_field(wp_unslash($ultimate_security_options['security']['login_security']['custom_login_url'])) : '';
		if (!empty($custom_login_url)) {
			$email_text = str_replace('###CONFIRM_URL###', esc_url_raw(str_replace(rtrim($custom_login_url, '/') . '/', 'wp-login.php', $email_data['confirm_url'])), $email_text);
		}

		return $email_text;
	}

	public static function gdpr_banner_markup($style_needed = false)
	{
		$ultimate_security_options = Utils::ultimate_security_get_option();

		$current_banner_content = (isset($ultimate_security_options['security']['login_security']['current_banner_content']) && wp_kses_post(wp_unslash($ultimate_security_options['security']['login_security']['current_banner_content']))
		) ? wp_kses_post(wp_unslash($ultimate_security_options['security']['login_security']['current_banner_content'])) : esc_html__('By logging in to this website you are consenting this website to process the IP address and browser information for security purposes.', 'ultimate-security');

		$markup = '<div><input id="gdpr-accept" type="checkbox" required/>' . $current_banner_content . '</div>';

		return $markup;
	}

	public static function ultimate_security_insert_banner_markup()
	{
		echo self::gdpr_banner_markup(true); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
	}

	public static function ultimate_security_banner_shortcode()
	{
		return self::gdpr_banner_markup();
	}

	public static function login_validation_script()
	{
		?>
		<script type="text/javascript">
			jQuery(document).ready(function ($) {
				// Disable HTML5 validation
				$('#loginform').attr('novalidate', 'novalidate');

				// Submit handler
				$('#loginform').on('submit', function (e) {
					var isValid = true;

					// Clear previous errors
					$('.custom-login-error').remove();
					$('input').css('border-color', '');

					// Validate username
					if ($('#user_login').val().trim() === '') {
						$('#user_login').addClass('has-error');
						showError($('#user_login'), 'Username or email is required');
						isValid = false;
					}

					// Validate password
					if ($('#user_pass').val().trim() === '') {
						$('#user_pass').addClass('has-error');
						showError($('#user_pass'), 'Password is required');
						isValid = false;
					}

					// Validate GDPR checkbox if it exists
					if ($('#gdpr-accept').length && !$('#gdpr-accept').is(':checked')) {
						$('#gdpr-accept').closest('p, div').addClass('gdpr-accept-container');
						showError($('#gdpr-accept').closest('p, div'), 'You must accept the terms to continue');
						isValid = false;
					}
					// Clear GDPR error when checked
					$('#gdpr-accept').on('change', function () {
						if ($(this).is(':checked')) {
							$(this).closest('.gdpr-accept-container').next('.custom-login-error').remove();
						}
					});

					if (!isValid) {
						e.preventDefault();
					}
				});

				// Clear errors when typing/checking
				$('#user_login, #user_pass').on('input', function () {
					$(this).next('.custom-login-error').remove();
					$(this).css('border-color', '');
					$(this).removeClass('has-error');
				});

				// Clear GDPR error when checked
				$('#gdpr-accept').on('change', function () {
					$(this).closest('p, div').find('.custom-login-error').remove();
				});

				// Function to display error messages
				function showError($element, message) {
					// For checkbox, we highlight the container
					if ($element.is(':checkbox')) {
						$element = $element.closest('p, div');
						$element.css('border', '1px solid #dc3232').css('padding', '10px');
					} else {
						$element.css('border-color', '#dc3232');
					}

					$element.after(
						$('<div/>', {
							'class': 'custom-login-error',
							'text': message
						}).css({
							'color': '#dc3232',
							'font-size': '13px',
							'margin-bottom': '5px',
							'display': 'block'
						})
					);
				}
			});
		</script>
		<style>
			.login input[type=text].input.has-error,
			.login input[type=password].input.has-error {
				margin-bottom: 5px;
			}
		</style>
		<?php
	}
	public function set_no_cache_headers()
	{
		if (PluginDetection::is_litespeed_active()) {
			header('X-LiteSpeed-Cache-Control: no-cache');
		}
		// Also for other caching plugins
		if (!defined('DONOTCACHEPAGE')) {
			define('DONOTCACHEPAGE', true);
		}
		nocache_headers();
	}
}
