<?php





/**





 * SensFRX API Calls Class of App





 *





 */





namespace SensFRX\Common;





/**





 * Class ApiCalls





 *





 * @package ApiCalls





 */





class ApiCalls {





	private $property_id;





	private $property_secret;





	private $apiURL;





	public function __construct($property_id,$property_secret,$app_url) {





		$this->property_id = $property_id;





		$this->property_secret = $property_secret;





		$this->apiURL = $app_url;





	}





	private function getAPIUrl($path) {





		return $this->apiURL . $path;





	}





	public function callAPI ($method, $url, $data=[]) {





		try {





			$headers = array();





			$headers['ip'] = $this->get_client_ip();





			if (isset($_SERVER['HTTP_USER_AGENT'])) {





				$headers['ua'] = sanitize_text_field($_SERVER['HTTP_USER_AGENT']);





			} else {





				$headers['ua'] = "";





			}





			if (isset($_SERVER['HTTP_HOST'])) {





				$headers['ho'] = sanitize_text_field($_SERVER['HTTP_HOST']);





			} else {





				$headers['ho'] = "";





			}



			if (isset($_SERVER['HTTP_REFERER'])) {



				$headers['rf'] = sanitize_text_field($_SERVER['HTTP_REFERER']);



			} else {



				$headers['rf'] = "";



			}





			$headers['ac'] = isset($_SERVER['HTTP_ACCEPT_CHARSET'])?sanitize_text_field($_SERVER['HTTP_ACCEPT_CHARSET']):''; // $this->getAcceptString($_SERVER);





			$headers['url'] = sanitize_url($this->getPageUrl($_SERVER));



			$data['h'] = $headers;





			$url = $this->getAPIUrl($url);





			$apiKey = base64_encode($this->property_id . ':' . $this->property_secret);



			$secret = '9d1b7f5568f4c4eb0ffb8c33b3a3a0ed9fa4e3ae9f9a6c9cbb2289ec0fc5b1f1';



			$payload = json_encode($data, JSON_UNESCAPED_SLASHES);



			$signature = hash_hmac('sha256', $payload, $secret);



			$headers = [



				'authorization' => 'Basic ' . $apiKey,



				'content-type' => 'application/json',



			];





			if ( 'POST' == $method ) {



				$payload = wp_json_encode($data, JSON_UNESCAPED_SLASHES);

				$signature = hash_hmac('sha256', $payload, $secret);

				$headers['x-signature'] = $signature;

				$jsonData = wp_json_encode($data);

				

				$args = [





					'method'  => $method,





					'timeout'     => 20,





					'headers' => $headers,





					'body'    => $jsonData,





				];

				$response = wp_remote_post($url, $args);



				



			} else if ( 'GET' == $method ) {



				$payload = '{}';

				$signature = hash_hmac('sha256', $payload, $secret);

				$headers['x-signature'] = $signature;

				$jsonData = wp_json_encode($data);





				$args = [





					'method'  => $method,





					'timeout'     => 20,





					'headers' => $headers,





				];





				// $url = $url . '?' . $jsonData;



			if (

				strpos($url, 'trans-stats') !== false ||

				strpos($url, 'ato-stats') !== false ||

				strpos($url, 'reg-stats') !== false ||

				strpos($url, 'bot-stats') !== false ||

				strpos($url, 'review-stats') !== false ||

				strpos($url, 'protection-stats') !== false ||

				strpos($url, 'trans-review') !== false ||

				strpos($url, 'reg-review') !== false

			) {



				// Append query params

				$url = $url; // . '?' . $queryParams;



			} else {



				// Default behaviour for other APIs

				$url = $url . '?' . $jsonData;

			}





			$response = wp_remote_get($url, $args);





			} 





		if (is_wp_error($response)) {





			$error_message = $response->get_error_message();





			// Log the error for debugging

			error_log(sprintf(

				'[Sensfrx SDK] API Error: %s | URL: %s | Time: %s',

				$error_message,

				$url,

				current_time('mysql')

			));





			// Return safe default to prevent checkout crashes

			// When API is down, allow transactions (fail-open approach)

			return array(

				'status' => 'allow',

				'severity' => 'low',

				'error' => true,

				'error_message' => $error_message

			);





		} else {





				$http_code = wp_remote_retrieve_response_code($response);

	

				if (200 === $http_code) {





					if (false !== strpos($url, '/export-policies')) {





						$body = $response;





						ob_clean();





						flush();





						header("Content-Type: application/json");         





						header("Content-Disposition: attachment; filename=policy.json"); 





						header("Content-Length: " . strlen($body));    





						header("Pragma: no-cache");





						header("Expires: 0"); 





						echo wp_kses_post( $body );





						exit; 





					} else {





						$return_res = array();





						$return_res = $response['body'];





						$return_res = json_decode($return_res, true); // Decode as associative array





						return $return_res;





					}





			} else {





				// Non-200 HTTP status code received

				$response_body = wp_remote_retrieve_body($response);

				

				// Parse the response body to extract actual error message

				$parsed_response = json_decode($response_body, true);

				

				// Extract actual error message if available

				$actual_error_message = 'API returned HTTP ' . $http_code;

				if (is_array($parsed_response)) {

					if (isset($parsed_response['message'])) {

						$actual_error_message = $parsed_response['message'];

					} elseif (isset($parsed_response['error_message'])) {

						$actual_error_message = $parsed_response['error_message'];

					}

				}

				

				// Log the error for debugging

				error_log(sprintf(

					'[Sensfrx SDK] Non-200 Response: HTTP %d | URL: %s | Message: %s | Time: %s',

					$http_code,

					$url,

					$actual_error_message,

					current_time('mysql')

				));



				// Determine if this is a configuration endpoint or transaction endpoint

				// Configuration endpoints should return actual errors

				// Transaction endpoints should fail-open to prevent blocking customers

				$is_config_endpoint = (

					strpos($url, '/blacklist') !== false ||

					strpos($url, '/whitelist') !== false ||

					strpos($url, '/policy') !== false ||

					strpos($url, '/advance') !== false

				);



				if ($is_config_endpoint) {

					// Return actual error for settings/configuration operations

					// Users need to see the real error message to fix issues

					return array(

						'status' => 'error',

						'message' => $actual_error_message,

						'http_code' => $http_code,

						'error' => true

					);

				} else {

					// Return safe default to prevent checkout crashes

					// When API returns non-200 for transactions, allow them (fail-open approach)

					return array(

						'status' => 'allow',

						'severity' => 'low',

						'error' => true,

						'http_code' => $http_code,

						'error_message' => $actual_error_message

					);

				}





			}





			}





	} catch (Exception $e) {





		// Log the exception for debugging

		error_log(sprintf(

			'[Sensfrx SDK] Exception: %s | File: %s | Line: %d | Time: %s',

			$e->getMessage(),

			$e->getFile(),

			$e->getLine(),

			current_time('mysql')

		));





		// Return safe default to prevent checkout crashes

		return array(

			'status' => 'allow',

			'severity' => 'low',

			'error' => true,

			'error_message' => 'Exception: ' . $e->getMessage()

		);





	}





	}





	// Function to get the client IP address





	public function get_client_ip() {





		$ipaddress = '';





		if (getenv('HTTP_CLIENT_IP')) {





			$ipaddress = getenv('HTTP_CLIENT_IP');





		} else if (getenv('HTTP_X_FORWARDED_FOR')) {





			$ipaddress = getenv('HTTP_X_FORWARDED_FOR');





		} else if (getenv('HTTP_X_FORWARDED')) {





			$ipaddress = getenv('HTTP_X_FORWARDED');





		} else if (getenv('HTTP_FORWARDED_FOR')) {





			$ipaddress = getenv('HTTP_FORWARDED_FOR');





		} else if (getenv('HTTP_FORWARDED')) {





			$ipaddress = getenv('HTTP_FORWARDED');





		} else if (getenv('REMOTE_ADDR')) {





			$ipaddress = getenv('REMOTE_ADDR');





		} else {





			$ipaddress = 'UNKNOWN';





		}





		return $ipaddress;





	}





	private function getPageOrigin( $srv, $use_forwarded_host = false ) {





		// check if SSL





		$ssl      = ( !empty($srv['HTTPS']) && 'on' == $srv['HTTPS'] );





		$srvp     = strtolower( $srv['SERVER_PROTOCOL'] );





		$srvpro   = substr( $srvp, 0, strpos( $srvp, '/' ) ) . ( ( $ssl ) ? 's' : '' );





		if (isset($_SERVER['SERVER_PORT'])) {





			$port = sanitize_text_field($_SERVER['SERVER_PORT']);





		} else {





			$port = ''; 





		}





		$serverName = isset($_SERVER['SERVER_NAME']) ? sanitize_text_field($_SERVER['SERVER_NAME']) : ''; // Replace 'default_server_name' with a relevant default value





		$port     = ( ( !$ssl && '80' == $port ) || ( $ssl && '443' == $port ) ) ? '' : ':' . $port;





		$host     = ( $use_forwarded_host && isset( $srv['HTTP_X_FORWARDED_HOST'] ) ) ? $srv['HTTP_X_FORWARDED_HOST'] : ( isset( $srv['HTTP_HOST'] ) ? $srv['HTTP_HOST'] : '' );





		$host     = isset( $host ) ? $host : $serverName . $port;





		return $srvpro . '://' . $host;





	}





	private function getPageUrl( $srv, $use_forwarded_host = false ) {





		return $this->getPageOrigin( $srv, $use_forwarded_host ) . $srv['REQUEST_URI'];





	}





	public function getAcceptString($srv) {





		$retData = array();





		if (isset($srv['HTTP_ACCEPT'])) {





			$retData['a'] = isset($_SERVER['HTTP_ACCEPT']) ? sanitize_text_field($_SERVER['HTTP_ACCEPT']) : '';





		} else {





			$retData['a'] = "Index 'HTTP_ACCEPT' is not set in \$_SERVER.";





		}





		if (isset($srv['HTTP_ACCEPT_CHARSET'])) {





			$retData['ac'] = isset($_SERVER['HTTP_ACCEPT_CHARSET']) ? sanitize_text_field($_SERVER['HTTP_ACCEPT_CHARSET']) : '';





		} else {





			$retData['ac'] = "Index 'HTTP_ACCEPT_CHARSET' is not set \$_SERVER.";





		}





		if (isset($srv['HTTP_ACCEPT_ENCODING'])) {





			$retData['ae'] = isset($_SERVER['HTTP_ACCEPT_ENCODING']) ? sanitize_text_field($_SERVER['HTTP_ACCEPT_ENCODING']) : '';





		} else {





			$retData['ae'] = "Index 'HTTP_ACCEPT_ENCODING' is not set \$_SERVER.";





		}





		if (isset($srv['HTTP_ACCEPT_LANGUAGE'])) {





			$retData['al'] = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? sanitize_text_field($_SERVER['HTTP_ACCEPT_LANGUAGE']) : '';





		} else {





			$retData['al'] = "Index 'HTTP_ACCEPT_LANGUAGE' is not set \$_SERVER.";





		}





		return $retData;





	}



	/**

	 * OAuth API call with HMAC-SHA256 signature

	 * Used for onboarding OAuth flow (send-otp, verify-otp, resend-otp)

	 * 

	 * @param string $endpoint API endpoint (e.g., '/onboarding/oauth/send-otp')

	 * @param array $data Payload data

	 * @return array API response

	 */

	public function postOAuthApiFinal($endpoint, $data = array()) {



		try {



			// OAuth secret for signature generation

			$oauth_secret = '9d1b7f5568f4c4eb0ffb8c33b3a3a0ed9fa4e3ae9f9a6c9cbb2289ec0fc5b1f1';



			// Prepare payload JSON (JSON_UNESCAPED_SLASHES is critical for signature matching)

			$payload_json = json_encode($data, JSON_UNESCAPED_SLASHES);



			// Generate HMAC-SHA256 signature

			$signature = hash_hmac('sha256', $payload_json, $oauth_secret);



			// Prepare request URL

			$url = $this->getAPIUrl($endpoint);



			// Prepare request arguments

			$args = array(

				'method'  => 'POST',

				'headers' => array(

					'Content-Type' => 'application/json',

					'x-signature'  => $signature,

				),

				'body'    => $payload_json,

				'timeout' => 30,

			);



			// Make the request

			$response = wp_remote_post($url, $args);



			// Handle errors

			if (is_wp_error($response)) {



				error_log('SensFRX OAuth API Error: ' . $response->get_error_message());



				return array(

					'status'  => 'error',

					'message' => 'Failed to connect to Sensfrx API: ' . $response->get_error_message()

				);



			}



			// Check HTTP response code

			$http_code = wp_remote_retrieve_response_code($response);

			

			// Parse response

			$body = wp_remote_retrieve_body($response);



			$result = json_decode($body, true);



			if ($result === null) {

				error_log('SensFRX OAuth API: Invalid JSON response. HTTP Code: ' . $http_code . ', Body: ' . $body);

				return array(

					'status'  => 'error',

					'message' => 'Invalid response from API'

				);



			}

			

			// If HTTP code is not 200, include it in the response

			if ($http_code !== 200) {

				error_log('SensFRX OAuth API: Non-200 HTTP Code: ' . $http_code . ', Response: ' . print_r($result, true));

				if (!isset($result['status'])) {

					$result['status'] = 'error';

				}

				if (!isset($result['message'])) {

					$result['message'] = 'API returned HTTP ' . $http_code;

				}

			}



			return $result;



		} catch (Exception $e) {



			error_log('SensFRX OAuth API Exception: ' . $e->getMessage());



			return array(

				'status'  => 'error',

				'message' => 'API call failed: ' . $e->getMessage()

			);



		}



	}





}





