<?php
/**
 * RadiusBooking API Route Registrar
 *
 * This class is responsible for registering API routes dynamically with the WordPress REST API.
 * It supports CRUD operations and allows for middleware to be applied globally or per route.
 *
 * @package RadiusTheme\RadiusBooking\Core\Api\Routes
 */

namespace RadiusTheme\RadiusBooking\Core\Api\Middleware;

use RadiusTheme\RadiusBooking\Core\Api\ApiResponse;
use WP_REST_Request;
use WP_REST_Response;
if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}
/**
 * Core/Api/Middleware/PermissionMiddleware.php
 * Permission-based middleware
 */
class PermissionMiddleware implements MiddlewareInterface {
	/**
	 * The capability required for the user to access the endpoint.
	 * This is typically a WordPress capability like 'edit_posts', 'manage_options', etc.
	 *
	 * @var string
	 */
	private string $capability;

	/**
	 * Constructor method for initializing the class with a capability.
	 *
	 * @param string $capability The capability to be set for the class.
	 *
	 * @return void
	 */
	public function __construct( string $capability ) {
		$this->capability = $capability;
	}

	/**
	 * Handles the incoming REST request and checks user permissions.
	 *
	 * @param WP_REST_Request $request The incoming REST request instance.
	 * @param callable $next The next middleware or handler to process the request.
	 */
	public function handle( WP_REST_Request $request, callable $next ) {

		/**
		 * 1. Check REST nonce
		 * This ensures request comes from your WordPress site frontend.
		 */
		$nonce = $request->get_header( 'x-wp-nonce' );

		if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
			return ApiResponse::forbidden( 'Invalid nonce' )->send();
		}

		/**
		 * 2. Check referer to confirm request originates from your domain
		 */
		$referer        = $request->get_header( 'referer' );
		$allowed_domain = home_url();

		if ( empty( $referer ) || strpos( $referer, $allowed_domain ) !== 0 ) {
			return ApiResponse::forbidden( 'Invalid request source' )->send();
		}

		if ( $this->checkAppointmentRoute( $request, $next ) ) {
			return $this->byPassRequest( $request, $next );
		}

		/**
		 * 3. Check user capability
		 */
		if ( ! current_user_can( $this->capability ) ) {
			return ApiResponse::forbidden( 'Insufficient permissions' )->send();
		}

		/**
		 * If all checks pass, continue
		 */
		return $next( $request );
	}

	/**
	 * Handles bypassing a request and passes it to the next callable.
	 *
	 * @param WP_REST_Request $request The current REST request object.
	 * @param callable $next The next callable to process the request.
	 *
	 * @return mixed The result of the next callable.
	 */
	public function byPassRequest( WP_REST_Request $request, callable $next ) {
		return $next( $request );
	}

	/**
	 * Checks if the request corresponds to the '/radius-booking/v1/appointments' route with the 'GET' or 'POST' method.
	 *
	 * @param object $request The HTTP request object containing method and route information.
	 * @param callable $next Middleware callback for processing the request further.
	 **/
	public function checkAppointmentRoute( $request, $next ) {
		$method = $request->get_method();
		$route  = $request->get_route();

		// Bypass capability check for public booking routes.
		if ( ( 'GET' === $method || 'POST' === $method ) && $route === '/radius-booking/v1/appointments' ) {
			return true;
		}

		// Bypass for payment config (needed by Stripe/PayPal on public booking pages).
		if ( 'GET' === $method && $route === '/radius-booking/v1/appointments/config' ) {
			return true;
		}

		// Bypass for payment routes (used by public booking forms).
		$public_post_routes = array(
			'/radius-booking/v1/appointments/create-intent',
			'/radius-booking/v1/appointments/verify-intent',
			'/radius-booking/v1/appointments/paypal/create-order',
			'/radius-booking/v1/appointments/paypal/capture-order',
		);
		if ( 'POST' === $method && in_array( $route, $public_post_routes, true ) ) {
			return true;
		}

		return false;
	}
}
