<?php
namespace Manage\Modules\Api\Classes;

use Manage\Classes\Client;
use Manage\Classes\Jwks_Decoder;
use Manage\Classes\System_User;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

abstract class Route {

	const NAMESPACE = 'manage/v1';

	abstract public function register_routes();

	public function __construct() {
		add_action( 'rest_api_init', [ $this, 'register_routes' ] );
	}

	public function token_authentication( $request ) {
		if ( $this->is_authentication_skipped() ) {
			return true;
		}

		$auth_header = $request->get_header( 'authorization' );

		if ( ! $auth_header ) {
			return new \WP_Error( 'no_auth_header', 'Authorization header missing.', [ 'status' => \WP_Http::UNAUTHORIZED ] );
		}

		if ( ! preg_match( '/Bearer\s(\S+)/', $auth_header, $matches ) ) {
			return new \WP_Error( 'invalid_token', 'Invalid or missing token.', [ 'status' => \WP_Http::FORBIDDEN ] );
		}

		$token = $matches[1];

		$jwt_payload = Jwks_Decoder::decode( $token );
		if ( is_wp_error( $jwt_payload ) ) {
			return new \WP_Error( $jwt_payload->get_error_code(), $jwt_payload->get_error_message(), [ 'status' => \WP_Http::FORBIDDEN ] );
		}

		if ( empty( $jwt_payload['sub'] ) || Client::get_client_id() !== $jwt_payload['sub'] ) {
			return new \WP_Error( 'invalid_site_id', 'Invalid site ID in token.', [ 'status' => \WP_Http::FORBIDDEN ] );
		}

		$system_user = System_User::get_system_user();

		if ( ! $system_user ) {
			return new \WP_Error( 'system_user_not_exists', 'System user does not exist.', [ 'status' => \WP_Http::FORBIDDEN ] );
		}

		$user_status = System_User::get_user_status( $system_user );

		if ( System_User::STATUS_USER_NO_PERMISSIONS === $user_status ) {
			return new \WP_Error( 'system_user_no_permissions', 'System user does not have admin permissions.', [ 'status' => \WP_Http::FORBIDDEN ] );
		}

		wp_set_current_user( $system_user->ID );

		return true;
	}

	private function is_authentication_skipped(): bool {
		if ( ! defined( 'MANAGE_DEV_MODE' ) || ! MANAGE_DEV_MODE ) {
			return false;
		}

		if ( ! $this->is_local_ip() ) {
			return false;
		}

		return true;
	}

	private function is_local_ip(): bool {
		if ( ! empty( $_SERVER['REMOTE_ADDR'] ) && in_array( $_SERVER['REMOTE_ADDR'], [ '127.0.0.1', '::1' ], true ) ) {
			return true;
		}

		return false;
	}
}
