<?php


namespace Fliegerlogin\WpAdmin\Pages;


use Fliegerlogin\Options;
use Fliegerlogin\RateLimiter;


/**
 * Settings for the IP rate limiting that ships with every edition.
 *
 * The limiter guards the Vereinsflieger request quota the whole plugin depends
 * on, so it belongs to the free feature set - and everything it can do is
 * configurable right here.
 */
class Security extends AbstractPage {

	public static function getSlug(): string {
		return 'fliegerlogin-security';
	}

	public static function getTitle(): string {
		return 'Fliegerlogin - ' . __('Security', 'sso-for-vereinsflieger');
	}

	public static function getMenuTitle(): string {
		return __('Security', 'sso-for-vereinsflieger');
	}

	public static function setup(): void {
		self::setupMenuItem(self::getTitle(), self::getMenuTitle(), self::getCapability(), self::getSlug());
	}

	public function processRequest(): void {
		if (array_key_exists('fliegerlogin_unblock_ip', $_POST)) {
			check_admin_referer('fliegerlogin_security', 'fliegerlogin_security_nonce');

			$ip = sanitize_text_field(wp_unslash($_POST['fliegerlogin_unblock_ip']));
			RateLimiter::clearFailuresForIp($ip);
			$this->addMessage('success', __('The address was unblocked.', 'sso-for-vereinsflieger'));

			return;
		}

		if (!array_key_exists('fliegerlogin_security_submit', $_POST)) {
			return;
		}

		check_admin_referer('fliegerlogin_security', 'fliegerlogin_security_nonce');

		$maxAttempts    = (int) sanitize_text_field(wp_unslash($_POST['fliegerlogin_rate_limit_max_attempts'] ?? ''));
		$lockoutMinutes = (int) sanitize_text_field(wp_unslash($_POST['fliegerlogin_rate_limit_lockout_minutes'] ?? ''));

		if ($maxAttempts < 1 || $maxAttempts > 1000 || $lockoutMinutes < 1 || $lockoutMinutes > 1440) {
			$this->addMessage('error', __('Some inputs are incorrect. Please check.', 'sso-for-vereinsflieger'));

			return;
		}

		Options::setRateLimitEnabled(array_key_exists('fliegerlogin_rate_limit_enabled', $_POST));
		Options::setRateLimitAllLoginsEnabled(array_key_exists('fliegerlogin_rate_limit_all_logins', $_POST));
		Options::setRateLimitMaxAttempts($maxAttempts);
		Options::setRateLimitLockoutSeconds($lockoutMinutes * 60);

		$this->addMessage('success', __('Your changes were saved successfully.', 'sso-for-vereinsflieger'));
	}

	public function printPage(): void {
		$enabled        = RateLimiter::isEnabled();
		$allLogins      = RateLimiter::appliesToAllLogins();
		$maxAttempts    = RateLimiter::getMaxAttempts();
		$lockoutMinutes = max(1, (int) round(RateLimiter::getLockoutSeconds() / 60));
		$blockedIps     = RateLimiter::getBlockedIps();
		$activeIps      = RateLimiter::getActiveFailureIps();

		?>
		<div class="wrap">
		<?php $this->printHeader(__('Security', 'sso-for-vereinsflieger')); ?>
		<?php $this->printMessages(); ?>

		<p>
			<?php esc_html_e('Vereinsflieger allows a limited number of API requests per day and per app key. Rate limiting stops brute force attempts from spending that quota, which would lock your whole club out.', 'sso-for-vereinsflieger'); ?>
		</p>

		<form method="post">
			<?php wp_nonce_field('fliegerlogin_security', 'fliegerlogin_security_nonce'); ?>
			<table class="form-table">
				<tr>
					<th><?php esc_html_e('Rate limiting', 'sso-for-vereinsflieger'); ?></th>
					<td>
						<label>
							<input name="fliegerlogin_rate_limit_enabled" type="checkbox" value="1" <?php checked($enabled); ?>>
							<?php esc_html_e('Block an address temporarily after repeated failed logins', 'sso-for-vereinsflieger'); ?>
						</label>
					</td>
				</tr>
				<tr>
					<th><?php esc_html_e('Failed attempts', 'sso-for-vereinsflieger'); ?></th>
					<td>
						<input class="small-text" name="fliegerlogin_rate_limit_max_attempts" type="number" min="1" max="1000" value="<?php echo esc_attr((string) $maxAttempts); ?>">
						<p class="description">
							<?php esc_html_e('How many rejected logins from one address trigger the block.', 'sso-for-vereinsflieger'); ?>
						</p>
					</td>
				</tr>
				<tr>
					<th><?php esc_html_e('Lockout duration', 'sso-for-vereinsflieger'); ?></th>
					<td>
						<input class="small-text" name="fliegerlogin_rate_limit_lockout_minutes" type="number" min="1" max="1440" value="<?php echo esc_attr((string) $lockoutMinutes); ?>">
						<?php esc_html_e('minutes', 'sso-for-vereinsflieger'); ?>
						<p class="description">
							<?php esc_html_e('Further attempts during the lockout extend it.', 'sso-for-vereinsflieger'); ?>
						</p>
					</td>
				</tr>
				<tr>
					<th><?php esc_html_e('Coverage', 'sso-for-vereinsflieger'); ?></th>
					<td>
						<label>
							<input name="fliegerlogin_rate_limit_all_logins" type="checkbox" value="1" <?php checked($allLogins); ?>>
							<?php esc_html_e('Apply to every WordPress login, not only to Vereinsflieger logins', 'sso-for-vereinsflieger'); ?>
						</label>
						<p class="description">
							<?php esc_html_e('Off by default: only logins that reach the Vereinsflieger API spend quota.', 'sso-for-vereinsflieger'); ?>
						</p>
					</td>
				</tr>
			</table>
			<p class="submit">
				<input type="submit" name="fliegerlogin_security_submit" class="button button-primary" value="<?php esc_attr_e('Save changes', 'sso-for-vereinsflieger'); ?>">
			</p>
		</form>

		<h2><?php esc_html_e('Blocked addresses', 'sso-for-vereinsflieger'); ?></h2>
		<?php if (!$blockedIps && !$activeIps) { ?>
			<p><?php esc_html_e('No address is currently blocked or counting failed attempts.', 'sso-for-vereinsflieger'); ?></p>
		<?php } else { ?>
			<table class="widefat striped" style="max-width:40em">
				<thead>
					<tr>
						<th><?php esc_html_e('Address', 'sso-for-vereinsflieger'); ?></th>
						<th><?php esc_html_e('Failed attempts', 'sso-for-vereinsflieger'); ?></th>
						<th><?php esc_html_e('Status', 'sso-for-vereinsflieger'); ?></th>
						<th></th>
					</tr>
				</thead>
				<tbody>
				<?php foreach (array_merge($blockedIps, $activeIps) as $entry) {
					$ip       = is_array($entry) ? ($entry['ip'] ?? '') : (string) $entry;
					$attempts = is_array($entry) ? (int) ($entry['attempts'] ?? 0) : RateLimiter::getAttemptsForIp($ip);
					$isBlocked = $attempts >= $maxAttempts;
					?>
					<tr>
						<td><code><?php echo esc_html($ip); ?></code></td>
						<td><?php echo esc_html((string) $attempts); ?></td>
						<td>
							<?php echo $isBlocked
								? esc_html__('blocked', 'sso-for-vereinsflieger')
								: esc_html__('counting', 'sso-for-vereinsflieger'); ?>
						</td>
						<td>
							<form method="post">
								<?php wp_nonce_field('fliegerlogin_security', 'fliegerlogin_security_nonce'); ?>
								<input type="hidden" name="fliegerlogin_unblock_ip" value="<?php echo esc_attr($ip); ?>">
								<button type="submit" class="button button-small">
									<?php esc_html_e('Unblock', 'sso-for-vereinsflieger'); ?>
								</button>
							</form>
						</td>
					</tr>
				<?php } ?>
				</tbody>
			</table>
		<?php } ?>
		</div>
		<?php
	}

}
