<?php


class WPB_Routes_Handler extends WPB_Routes
{
	private  $controller_path;

	public function __construct() {
		$this->controller_path = IQWPB_PLUGIN_PATH . 'core/admin/classes/controllers/';
		parent::__construct();
		$this->event_Handler();	
	}

	public function event_Handler() {
		add_action( "wp_ajax_wpb_ajax_post", [ $this, 'wpb_ajax_post' ] );
		add_action( "wp_ajax_nopriv_wpb_ajax_post", [ $this, 'wpb_ajax_post' ] );

		add_action( "wp_ajax_wpb_ajax_get", [ $this, 'wpb_ajax_get' ] );
		add_action( "wp_ajax_nopriv_wpb_ajax_get", [ $this, 'wpb_ajax_get' ] );
	}

	public function wpb_ajax_post() {
		try {
			//check if request method is post method
			if ( isset($_SERVER['REQUEST_METHOD']) && strtolower( sanitize_textarea_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) ) !== 'post' ) :
				$error = __( 'Method is not allowed', 'wpbookit');
				throw new Exception($error, 405);
			endif;

            $this->routes();

			// Sanitize route_name once
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is for Settings display, not processing form data
			$route_name = isset($_REQUEST['route_name']) ? sanitize_text_field(wp_unslash($_REQUEST['route_name'])) : '';

			//check if request route key exists in route array
			if (!empty($route_name) && $this->has_route($route_name)) :
				//get request route value from route array
				$route = $this->get_route($route_name);

				//check if request route method is same as required method
				if (strtolower($route['method']) !== 'post') :
					$error = __( 'Method is not allowed', 'wpbookit' );
					throw new Exception($error, 405);
				endif;

				//check route value have nonce if not set nonce to 100
				if (!isset($route['nonce'])) :
					$route['nonce'] = 1;
				endif;

			if ($route['nonce'] === 1) :
				// Routes requiring nonce must also require authentication
				// Nonces are user-specific and cannot be verified for non-authenticated users
				if ( ! is_user_logged_in() ) {
					$error = __('Authentication required.', 'wpbookit');
					throw new Exception($error, 401);
				}
				
				//verify request nonce
				$nonce = isset($_REQUEST['_ajax_nonce']) ? sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])) : '';
				if (empty($nonce) || !wp_verify_nonce($nonce, 'wpb_ajax_nonce')) :
					$error = __('Invalid nonce in request', 'wpbookit');
					throw new Exception($error, 419);
				endif;
			endif;

            // Check for permissions if defined in the route
            if (isset($route['permission']) && !empty($route['permission'])) {
                if (!current_user_can($route['permission'])) {
                    $error = __('You do not have permission to perform this action.', 'wpbookit');
                    throw new Exception($error, 403);
                }
            }

				//call function
				$this->call($route);
			else :
				$error = __('Route not found', 'wpbookit');
				throw new Exception($error, 404);
			endif;
		} catch (Exception $e) {

			$code    = $e->getCode();
			$message = $e->getMessage();

			header("Status: $code $message");

			wp_send_json(
				array(
					'status'  => false,
					'message' => $e->getMessage()
				)
			);
		}
		wp_die();
	}

	public function wpb_ajax_get() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is for Settings display, not processing form data
		if ( empty( $_REQUEST ) ) {
			$_REQUEST = json_decode(file_get_contents("php://input"), true);
		}

		try {
			//check if request method is get method
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is for Settings display, not processing form data
			if ( isset($_SERVER['REQUEST_METHOD']) && strtolower(sanitize_textarea_field(wp_unslash($_SERVER['REQUEST_METHOD']))) !== 'get' ) :
				$error =  __('Method is not allowed', 'wpbookit');
				throw new Exception($error, 405);
			endif;

            $this->routes();

			// Sanitize route_name once
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is for Settings display, not processing form data
			$route_name = isset($_REQUEST['route_name']) ? sanitize_text_field(wp_unslash($_REQUEST['route_name'])) : '';

			//check if request route key exists in route array
			if (!empty($route_name) && $this->has_route($route_name)) :
				//get request route value from route array
				$route = $this->get_route($route_name);

				//check if request route method is same as required method
				if (strtolower($route['method']) !== 'get') :
					$error = __('Method is not allowed', 'wpbookit');
					throw new Exception($error, 405);
				endif;

				// Verify nonce if required
				if (isset($route['nonce']) && $route['nonce'] === 1) :
					if ( ! is_user_logged_in() ) {
						$error = __('Authentication required.', 'wpbookit');
						throw new Exception($error, 401);
					}

					$nonce = isset($_REQUEST['_ajax_nonce']) ? sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])) : '';
					if (empty($nonce) || !wp_verify_nonce($nonce, 'wpb_ajax_nonce')) :
						$error = __('Invalid nonce in request', 'wpbookit');
						throw new Exception($error, 419);
					endif;
				endif;

                // Check for permissions if defined in the route
                if (isset($route['permission']) && !empty($route['permission'])) {
                    if (!is_user_logged_in() || !current_user_can($route['permission'])) {
                        $error = __('You do not have permission to perform this action.', 'wpbookit');
                        throw new Exception($error, 403);
                    }
                }

				//call function
				$this->call($route);
			else :
				$error = __('Route not found', 'wpbookit');
				throw new Exception($error, 404);
			endif;
		} catch (Exception $e) {

			$code    = $e->getCode();
			$message = $e->getMessage();

			header("Status: $code $message");

			wp_send_json([
				'status'  => false,
				'message' => $e->getMessage()
			]);
		}
	}

	public function call($route) {
	
		list($class, $method) = explode('@', $route['action']);
		
		require_once IQWPB_PLUGIN_PATH . 'core/includes/classes/class.wpb-cache-handler.php';
		if( isset( $route['dependency'] ) && !empty( $route['dependency'] ) ) :
			$dependencys = apply_filters( 'wpbookit_include_dependency_file_' . ($route['module']??''), ($route['dependency']??''), $route );
	
			foreach( $dependencys as $dependency ) :
				if( file_exists( $dependency ) ) :
					require_once $dependency;
				else :
					wp_send_json(
						array( 
							'success'    => false,
							'message'    => sprintf( 
								// translators: Dependency Name placeholder:0
								__( '%s dependency file not found at the desired location ', 'wpbookit' ),
								$dependency
							),
						)
					);    
				endif;
			endforeach;
		endif;
		
		if( isset( $route['module'] ) ) :
			require_once apply_filters( 'wpbookit_include_controller_file',$this->controller_path .'class.wpb-'. $route['module'].'.php',$route['module']) ;
		endif;
	
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is for Settings display, not processing form data
		$request_method = isset($_SERVER['REQUEST_METHOD']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_METHOD'])) : 'GET';
		$request    = new WP_REST_Request( $request_method, $method );
		$req_method    = $request_method === 'GET' ? 'set_query_params' : 'set_body_params';
	
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is for Settings display, not processing form data
		$request->$req_method($_REQUEST);
		if( "set_body_params" === $req_method ):
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- This is for Settings display, not processing form data
			$request->set_file_params($_FILES);
		endif;

        if( class_exists( $class ) ) {
            (new $class)->$method($request);
        }else{
            wpbookit_error_log( 'Class '. $class .' not found' );
            $response = array(
                'status'  => 'error',
                'message' => __('Internal server error.', 'wpbookit'),
                'data'     => array(),
            );
            wp_send_json($response, 503 );
        }
	}
}
