<?php
/**
 * URL Call Handler Class
 *
 * This class handles all API calls to the miniOrange server using WordPress HTTP API.
 * It provides methods for customer management, OTP operations, and notifications.
 *
 * @package miniorange-sms-order-notification-otp-verification/helper
 * @since   1.0.0
 */

namespace WCSMSOTP\Helper;

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

use WCSMSOTP\Objects\NotificationSettings;
use WCSMSOTP\Helper\MoConstants;
/**
 * URL Call Handler Class
 *
 * This class handles all API calls to the miniOrange server using WordPress HTTP API.
 * It provides methods for customer management, OTP operations, and notifications.
 */
if ( ! class_exists( 'MocURLCall' ) ) {
	/**
	 * URL Call Handler Class
	 *
	 * This class handles all API calls to the miniOrange server using WordPress HTTP API.
	 * It provides methods for customer management, OTP operations, and notifications.
	 */
	class MocURLCall {

		/**
		 * Create customer.
		 *
		 * Creates a new customer account on the miniOrange server.
		 *
		 * @param string $email      Email address.
		 * @param string $company   Company name.
		 * @param string $password  Password of user.
		 * @param string $phone     Phone number of user. Default empty string.
		 * @param string $first_name First name of user. Default empty string.
		 * @param string $last_name  Last name of user. Default empty string.
		 * @return string Response from the API.
		 */
		public static function create_customer( $email, $company, $password, $phone = '', $first_name = '', $last_name = '' ) {
			$email        = sanitize_email( $email );
			$company      = sanitize_text_field( $company );
			$password     = sanitize_text_field( $password );
			$phone        = is_string( $phone ) ? sanitize_text_field( $phone ) : '';
			$first_name   = is_string( $first_name ) ? sanitize_text_field( $first_name ) : '';
			$last_name    = is_string( $last_name ) ? sanitize_text_field( $last_name ) : '';
			$url          = MoConstants::HOSTNAME . '/moas/rest/customer/add';
			$customer_key = MoConstants::DEFAULT_CUSTOMER_KEY;
			$api_key      = MoConstants::DEFAULT_API_KEY;
			$fields       = array(
				'companyName'    => $company,
				'areaOfInterest' => MoConstants::AREA_OF_INTEREST,
				'firstname'      => $first_name,
				'lastname'       => $last_name,
				'email'          => $email,
				'phone'          => $phone,
				'password'       => $password,
			);
			$json         = wp_json_encode( $fields );
			$auth_header  = self::create_auth_header( $customer_key, $api_key );
			$response     = self::call_api( $url, $json, $auth_header );
			return is_string( $response ) ? $response : '';
		}

		/**
		 * Get customer key.
		 *
		 * Retrieves the customer key from the miniOrange server.
		 *
		 * @param string $email    Email address.
		 * @param string $password Password of user.
		 * @return string Response from the API.
		 */
		public static function get_customer_key( $email, $password ) {
			if ( ! is_string( $email ) || ! is_string( $password ) ) {
				return '';
			}
			$email        = sanitize_email( $email );
			$password     = sanitize_text_field( $password );
			$url          = MoConstants::HOSTNAME . '/moas/rest/customer/key';
			$customer_key = MoConstants::DEFAULT_CUSTOMER_KEY;
			$api_key      = MoConstants::DEFAULT_API_KEY;
			$fields       = array(
				'email'    => $email,
				'password' => $password,
			);
			$json         = wp_json_encode( $fields );
			$auth_header  = self::create_auth_header( $customer_key, $api_key );
			$response     = self::call_api( $url, $json, $auth_header );
			return is_string( $response ) ? $response : '';
		}

		/**
		 * Check customer.
		 *
		 * Checks if a customer exists on the miniOrange server.
		 *
		 * @param string $email Email address.
		 * @return string Response from the API.
		 */
		public static function check_customer( $email ) {
			if ( ! is_string( $email ) ) {
				return '';
			}
			$email = sanitize_email( $email );

			if ( ! class_exists( 'MoConstants' ) ) {
				return '';
			}
			$url          = MoConstants::HOSTNAME . '/moas/rest/customer/check-if-exists';
			$customer_key = MoConstants::DEFAULT_CUSTOMER_KEY;
			$api_key      = MoConstants::DEFAULT_API_KEY;
			$fields       = array(
				'email' => $email,
			);
			$json         = wp_json_encode( $fields );
			$auth_header  = self::create_auth_header( $customer_key, $api_key );
			$response     = self::call_api( $url, $json, $auth_header );
			return is_string( $response ) ? $response : '';
		}

		/**
		 * Send OTP token.
		 *
		 * Sends an OTP token to the user's phone or email.
		 *
		 * @param string $auth_type Authentication type - either SMS or Email.
		 * @param string $email     Email address. Default empty string.
		 * @param string $phone     Phone number of user. Default empty string.
		 * @return string Response from the API.
		 */
		public static function mo_send_otp_token( $auth_type, $email = '', $phone = '' ) {
			if ( ! is_string( $auth_type ) ) {
				return '';
			}
			$auth_type    = sanitize_text_field( $auth_type );
			$email        = is_string( $email ) ? sanitize_email( $email ) : '';
			$phone        = is_string( $phone ) ? sanitize_text_field( $phone ) : '';
			$email        = 'SMS' === $auth_type ? null : $email;
			$url          = MoConstants::HOSTNAME . '/moas/api/auth/challenge';
			$customer_key = ! MoUtility::is_blank( get_mo_wc_option( 'admin_customer_key' ) )
							? get_mo_wc_option( 'admin_customer_key' ) : MoConstants::DEFAULT_CUSTOMER_KEY;
			$api_key      = ! MoUtility::is_blank( get_mo_wc_option( 'admin_api_key' ) )
							? get_mo_wc_option( 'admin_api_key' ) : MoConstants::DEFAULT_API_KEY;
			if ( ! is_numeric( $customer_key ) || ! is_string( $api_key ) ) {
				return '';
			}
			$fields      = array(
				'customerKey'     => sanitize_text_field( $customer_key ),
				'email'           => $email,
				'phone'           => $phone,
				'authType'        => $auth_type,
				'transactionName' => MoConstants::AREA_OF_INTEREST,
			);
			$json        = wp_json_encode( $fields );
			$auth_header = self::create_auth_header( $customer_key, $api_key );
			$response    = self::call_api( $url, $json, $auth_header );
			return is_string( $response ) ? $response : '';
		}

		/**
		 * Validate OTP token.
		 *
		 * Validates the OTP token with the miniOrange server.
		 *
		 * @param string $transaction_id Transaction ID.
		 * @param string $otp_token      OTP token.
		 * @return string Response from the API.
		 */
		public static function validate_otp_token( $transaction_id, $otp_token ) {
			$transaction_id = sanitize_text_field( $transaction_id );
			$otp_token      = sanitize_text_field( $otp_token );
			$url            = MoConstants::HOSTNAME . '/moas/api/auth/validate';
			$customer_key   = ! MoUtility::is_blank( get_mo_wc_option( 'admin_customer_key' ) )
							? get_mo_wc_option( 'admin_customer_key' ) : MoConstants::DEFAULT_CUSTOMER_KEY;
			$api_key        = ! MoUtility::is_blank( get_mo_wc_option( 'admin_api_key' ) )
							? get_mo_wc_option( 'admin_api_key' ) : MoConstants::DEFAULT_API_KEY;
			if ( ! is_string( $customer_key ) || ! is_string( $api_key ) ) {
				return '';
			}
			$fields      = array(
				'txId'  => $transaction_id,
				'token' => $otp_token,
			);
			$json        = wp_json_encode( $fields );
			$auth_header = self::create_auth_header( $customer_key, $api_key );
			$response    = self::call_api( $url, $json, $auth_header );
			return is_string( $response ) ? $response : '';
		}

		/**
		 * Submit contact us form.
		 *
		 * Submits a contact us query to the miniOrange server.
		 *
		 * @param string $q_email Email address.
		 * @param string $q_phone Phone number of user.
		 * @param string $query   Query of user.
		 * @return bool True on success, false on failure.
		 */
		public static function submit_contact_us( $q_email, $q_phone, $query ) {
			if ( ! is_string( $q_email ) || ! is_string( $q_phone ) || ! is_string( $query ) ) {
				return false;
			}
			$q_email = sanitize_email( $q_email );
			$q_phone = sanitize_text_field( $q_phone );
			$query   = sanitize_textarea_field( $query );

			$mo_current_user = wp_get_current_user();
			if ( ! is_object( $mo_current_user ) || ! isset( $mo_current_user->ID ) ) {
				return false;
			}
			$mo_user = get_mo_wc_option( 'admin_email' );
			$mo_user = is_string( $mo_user ) ? sanitize_email( $mo_user ) : '';

			$url          = MoConstants::HOSTNAME . '/moas/rest/customer/contact-us';
			$query        = '[' . MoConstants::QUERY_NAME . '(' . MoConstants::PLUGIN_TYPE . ') ](' . esc_html( $mo_user ) . '): ' . $query;
			$customer_key = ! MoUtility::is_blank( get_mo_wc_option( 'admin_customer_key' ) )
							? get_mo_wc_option( 'admin_customer_key' ) : MoConstants::DEFAULT_CUSTOMER_KEY;
			$api_key      = ! MoUtility::is_blank( get_mo_wc_option( 'admin_api_key' ) )
							? get_mo_wc_option( 'admin_api_key' ) : MoConstants::DEFAULT_API_KEY;
			if ( ! is_string( $customer_key ) || ! is_string( $api_key ) ) {
				return false;
			}

			$first_name   = isset( $mo_current_user->user_firstname ) && is_string( $mo_current_user->user_firstname ) ? sanitize_text_field( $mo_current_user->user_firstname ) : '';
			$last_name    = isset( $mo_current_user->user_lastname ) && is_string( $mo_current_user->user_lastname ) ? sanitize_text_field( $mo_current_user->user_lastname ) : '';
			$company      = isset( $_SERVER['SERVER_NAME'] ) && is_string( $_SERVER['SERVER_NAME'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_NAME'] ) ) : '';
			$fields       = array(
				'firstName' => $first_name,
				'lastName'  => $last_name,
				'company'   => $company,
				'email'     => $q_email,
				'ccEmail'   => MoConstants::FEEDBACK_EMAIL,
				'phone'     => $q_phone,
				'query'     => $query,
			);
			$field_string = wp_json_encode( $fields );
			$auth_header  = self::create_auth_header( $customer_key, $api_key );
			$response     = self::call_api( $url, $field_string, $auth_header );
			return is_string( $response ) && ! empty( $response );
		}

		/**
		 * Forgot password.
		 *
		 * Sends a password reset request to the miniOrange server.
		 *
		 * @param string $email Email address.
		 * @return string Response from the API.
		 */
		public static function forgot_password( $email ) {
			if ( ! is_string( $email ) ) {
				return '';
			}
			$email = sanitize_email( $email );

			$url          = MoConstants::HOSTNAME . '/moas/rest/customer/password-reset';
			$customer_key = get_mo_wc_option( 'admin_customer_key' );
			$api_key      = get_mo_wc_option( 'admin_api_key' );
			if ( ! is_string( $customer_key ) || ! is_string( $api_key ) ) {
				return '';
			}

			$fields = array(
				'email' => $email,
			);

			$json        = wp_json_encode( $fields );
			$auth_header = self::create_auth_header( $customer_key, $api_key );
			$response    = self::call_api( $url, $json, $auth_header );
			return is_string( $response ) ? $response : '';
		}

		/**
		 * Check customer license.
		 *
		 * Checks the customer license on the miniOrange server.
		 *
		 * @param string $customer_key Customer key for internal use.
		 * @param string $api_key     API key of user.
		 * @param string $app_name    Plugin name of user.
		 * @param string $license_type License type of customer. Default 'DEMO'.
		 * @return string Response from the API.
		 */
		public static function check_customer_ln( $customer_key, $api_key, $app_name, $license_type = 'DEMO' ) {
			if ( ! is_string( $customer_key ) || ! is_string( $api_key ) || ! is_string( $app_name ) ) {
				return '';
			}
			$customer_key = sanitize_text_field( $customer_key );
			$api_key      = sanitize_text_field( $api_key );
			$app_name     = sanitize_text_field( $app_name );
			$license_type = is_string( $license_type ) ? sanitize_text_field( $license_type ) : 'DEMO';

			$url    = MoConstants::HOSTNAME . '/moas/rest/customer/license';
			$fields = array(
				'customerId'      => $customer_key,
				'applicationName' => $app_name,
				'licenseType'     => $license_type,
			);

			$json        = wp_json_encode( $fields );
			$auth_header = self::create_auth_header( $customer_key, $api_key );
			$response    = self::call_api( $url, $json, $auth_header );
			return is_string( $response ) ? $response : '';
		}

		/**
		 * Create authentication header.
		 *
		 * Creates an authentication header for API requests.
		 *
		 * @param string $customer_key Customer key for internal use.
		 * @param string $api_key      API key of user.
		 * @return array<string, string> Authentication header array.
		 */
		public static function create_auth_header( $customer_key, $api_key ) {
			if ( ! is_string( $customer_key ) || ! is_string( $api_key ) ) {
				return array( 'Content-Type' => 'application/json' );
			}
			$customer_key = sanitize_text_field( $customer_key );
			$api_key      = sanitize_text_field( $api_key );

			$current_timestamp_in_millis = self::get_timestamp();
			if ( MoUtility::is_blank( $current_timestamp_in_millis ) || ! is_string( $current_timestamp_in_millis ) ) {
				$current_timestamp_in_millis = round( microtime( true ) * 1000 );
				$current_timestamp_in_millis = number_format( $current_timestamp_in_millis, 0, '', '' );
			}
			$string_to_hash = $customer_key . $current_timestamp_in_millis . $api_key;
			$auth_header    = hash( 'sha512', $string_to_hash );

			$header = array(
				'Content-Type'  => 'application/json',
				'Customer-Key'  => $customer_key,
				'Timestamp'     => is_string( $current_timestamp_in_millis ) ? $current_timestamp_in_millis : '',
				'Authorization' => $auth_header,
			);
			return $header;
		}

		/**
		 * Get timestamp.
		 *
		 * Retrieves the current timestamp from the miniOrange server.
		 *
		 * @return string Timestamp from the server or empty string on failure.
		 */
		public static function get_timestamp() {
			if ( ! class_exists( 'MoConstants' ) ) {
				return '';
			}
			$url      = MoConstants::HOSTNAME . '/moas/rest/mobile/get-timestamp';
			$response = self::call_api( $url, null, null );
			return is_string( $response ) ? $response : '';
		}

		/**
		 * Call API.
		 *
		 * Uses WordPress HTTP API to make API calls to miniOrange server.
		 *
		 * Arguments that can be passed:
		 * - 'timeout'     => 5
		 * - 'redirection' => 5
		 * - 'httpversion' => '1.0'
		 * - 'user-agent'  => 'WordPress/' . $wp_version . '; ' . home_url()
		 * - 'blocking'    => true
		 * - 'headers'     => array()
		 * - 'cookies'     => array()
		 * - 'body'        => null
		 * - 'compress'    => false
		 * - 'decompress'  => true
		 * - 'sslverify'   => true
		 * - 'stream'      => false
		 * - 'filename'    => null
		 *
		 * @param string $url         URL to post to.
		 * @param string $json_string JSON encoded post data.
		 * @param array  $headers    Headers to be passed in the call. Default array with Content-Type.
		 * @param string $method      GET or POST or PUT HTTP method. Default 'POST'.
		 * @return string Response body from the API or empty string on failure.
		 */
		public static function call_api( $url, $json_string, $headers = array( 'Content-Type' => 'application/json' ), $method = 'POST' ) {
			if ( ! is_string( $url ) || empty( $url ) ) {
				return '';
			}
			$url = esc_url_raw( $url );
			if ( ! is_string( $method ) ) {
				$method = 'POST';
			}
			$method = sanitize_text_field( $method );
			if ( ! in_array( strtoupper( $method ), array( 'GET', 'POST', 'PUT', 'DELETE' ), true ) ) {
				$method = 'POST';
			}
			if ( ! is_array( $headers ) ) {
				$headers = array( 'Content-Type' => 'application/json' );
			}

			$ssl_verify = defined( 'MOV_WC_SSL_VERIFY' ) ? (bool) MOV_WC_SSL_VERIFY : true;
			$args       = array(
				'method'      => $method,
				'body'        => $json_string,
				'timeout'     => 30,
				'redirection' => 5,
				'httpversion' => '1.0',
				'blocking'    => true,
				'headers'     => $headers,
				'sslverify'   => $ssl_verify,
			);

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

			if ( is_wp_error( $response ) ) {
				$error_message = $response->get_error_message();
				$error_message = is_string( $error_message ) ? esc_html( $error_message ) : esc_html__( 'Unknown error occurred', 'miniorange-sms-order-notification-otp-verification' );
				wp_die(
					wp_kses_post( esc_html__( 'Something went wrong:', 'miniorange-sms-order-notification-otp-verification' ) . '<br/>' . $error_message ),
					esc_html__( 'API Error', 'miniorange-sms-order-notification-otp-verification' ),
					array( 'response' => 500 )
				);
				return '';
			}
			$response_code = wp_remote_retrieve_response_code( $response );
			if ( 200 !== $response_code ) {
				return '';
			}
			$body = wp_remote_retrieve_body( $response );
			return is_string( $body ) ? $body : '';
		}

		/**
		 * Send notification.
		 *
		 * Sends notification email or SMS to either customer or user.
		 *
		 * @param NotificationSettings $settings Settings object.
		 * @return string Response from the gateway.
		 */
		public static function send_notif( NotificationSettings $settings ) {
			if ( ! is_object( $settings ) || ! ( $settings instanceof NotificationSettings ) ) {
				return '';
			}
			if ( ! class_exists( 'WCSMSOTP\Helper\GatewayFunctions' ) ) {
				return '';
			}
			$gateway = GatewayFunctions::instance();
			if ( ! is_object( $gateway ) || ! method_exists( $gateway, 'mo_send_notif' ) ) {
				return '';
			}
			return $gateway->mo_send_notif( $settings );
		}
	}
}
