<?php
/**
 * Token AJAX handler module for SiteStaffr widget.
 *
 * @package SiteStaffr
 */

class SiteStaffr_Widget_Token_Handler {

	/**
	 * AJAX handler for token generation.
	 *
	 * Generates a fresh JWT token for WebSocket authentication.
	 * Uses admin-ajax.php instead of REST API for better compatibility
	 * with caching plugins and security plugins.
	 *
	 * Protected with multiple security layers: nonce verification, honeypot,
	 * rate limiting, and pattern detection to prevent bot attacks.
	 *
	 * @since    0.12.15
	 * @since    0.13.55 Added nonce verification, honeypot, global rate limit, and pattern detection.
	 *
	 * @param SiteStaffr_Widget $widget Widget instance.
	 * @param string           $ip_address Client IP address.
	 * @return void
	 */
	public static function ajax_get_token( SiteStaffr_Widget $widget, $ip_address ) {
		// Security guards: nonce, honeypot, ban (rate limits stay below admin bypass).
		SiteStaffr_Public_Request_Guards::enforce_public_guards( array(
			'nonce_action' => 'sitestaffr_widget_token',
			'ip'           => $ip_address,
			'honeypot'     => true,
			'ban_check'    => true,
		) );

		// 3. Skip rate limiting for logged-in administrators (allows testing)
		if ( current_user_can( 'manage_options' ) ) {
			// Admin user - skip directly to token generation
			if ( ! class_exists( 'SiteStaffr_Auth_Token' ) ) {
				require_once SITESTAFFR_PLUGIN_DIR . 'includes/class-sitestaffr-auth-token.php';
			}
			$site_id = get_site_url();
			$user_id = get_current_user_id();
			$token = SiteStaffr_Auth_Token::generate_token( $site_id, $user_id, 600 );

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				SiteStaffr_Logger::legacy( sprintf(
					'SiteStaffr Widget Token (AJAX): Admin bypass - generated token for user_id=%d, IP=%s',
					$user_id,
					$ip_address
				) );
			}

			wp_send_json_success( array(
				'token'      => $token,
				'site_id'    => $site_id,
				'expires_in' => 600,
			) );
			return;
		}

		// 4. Global rate limiting (distributed attack protection)
		$global_limit_key = 'sitestaffr_token_global_limit';
		if ( ! SiteStaffr_Public_Request_Guards::allow_rate_limited_request( $global_limit_key, 100, 60 ) ) {
			SiteStaffr_Logger::legacy( 'SiteStaffr Widget Token (AJAX): Global rate limit exceeded (100/minute)' );
			SiteStaffr_Public_Request_Guards::send_json_error( array(
				'message' => SiteStaffr_Public_Middleware_Client::msg_service_temporarily_unavailable_try_again_later(),
				'retry_after' => 60,
				'code'        => 'rate_limited',
			), 503 );
			return;
		}

		// 5. Per-IP rate limiting (10 per minute)
		$ip_hash = hash( 'sha256', $ip_address );
		$rate_limit_key = 'sitestaffr_token_ip_v2_' . $ip_hash;
		if ( ! SiteStaffr_Public_Request_Guards::allow_rate_limited_request( $rate_limit_key, 10, 60 ) ) {
			// Rate limit exceeded
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				SiteStaffr_Logger::legacy( sprintf(
					'SiteStaffr Widget Token (AJAX): Per-IP rate limit exceeded for IP %s',
					$ip_address
				) );
			}
			SiteStaffr_Public_Request_Guards::send_json_error( array(
				'message' => SiteStaffr_Public_Middleware_Client::msg_too_many_requests_try_again_minute(),
				'retry_after' => 60,
				'code'        => 'rate_limited',
			), 429 );
			return;
		}

		// 6. Suspicious pattern detection (8+ requests in 10 seconds)
		$pattern_key = 'sitestaffr_token_pattern_v2_' . $ip_hash;
		$timestamps = get_transient( $pattern_key );

		if ( $timestamps === false ) {
			$timestamps = array();
		}

		// Remove timestamps older than 10 seconds
		$current_time = time();
		$timestamps = array_filter( $timestamps, function( $ts ) use ( $current_time ) {
			return ( $current_time - $ts ) < 10;
		} );

		// Add current timestamp
		$timestamps[] = $current_time;

		// Check if suspicious pattern detected
		if ( count( $timestamps ) >= 8 ) {
			// Block IP for 2 minutes
			set_transient( 'sitestaffr_token_blocked_v2_' . $ip_hash, true, 120 );
			SiteStaffr_Logger::legacy( sprintf(
				'SiteStaffr Widget Token (AJAX): Suspicious pattern detected - blocking IP %s for 2 minutes',
				$ip_address
			) );
			wp_send_json_error( array(
				'message' => SiteStaffr_Public_Middleware_Client::msg_too_many_requests_try_again_minute(),
				'retry_after' => 120,
				'code'        => 'rate_limited',
			), 429 );
			return;
		}

		// Save timestamps
		set_transient( $pattern_key, $timestamps, 10 );

		// Check if IP is blocked
		if ( get_transient( 'sitestaffr_token_blocked_v2_' . $ip_hash ) ) {
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				SiteStaffr_Logger::legacy( sprintf(
					'SiteStaffr Widget Token (AJAX): Request from blocked IP %s',
					$ip_address
				) );
			}
			wp_send_json_error( array(
				'message' => SiteStaffr_Public_Middleware_Client::msg_too_many_requests_try_again_minute(),
				'retry_after' => 120,
				'code'        => 'rate_limited',
			), 429 );
			return;
		}

		// Load auth token class if not already loaded
		if ( ! class_exists( 'SiteStaffr_Auth_Token' ) ) {
			require_once SITESTAFFR_PLUGIN_DIR . 'includes/class-sitestaffr-auth-token.php';
		}

		// Generate fresh JWT token (10-minute expiry for security)
		$site_id = get_site_url();
		$user_id = get_current_user_id(); // 0 for guests
		$token = SiteStaffr_Auth_Token::generate_token( $site_id, $user_id, 600 ); // 10 minutes

		// Log token generation (only in development)
		if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
			SiteStaffr_Logger::legacy( sprintf(
				'SiteStaffr Widget Token (AJAX): Generated token for site_id=%s, user_id=%d (guest=%s), IP=%s',
				$site_id,
				$user_id,
				$user_id === 0 ? 'yes' : 'no',
				$ip_address
			) );
		}

		wp_send_json_success( array(
			'token'      => $token,
			'site_id'    => $site_id,
			'expires_in' => 600, // 10 minutes
		) );
	}
}
