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

	if ( ! class_exists( 'SftcyWordformPaymentAuthorizenet' ) ) {
	class SftcyWordformPaymentAuthorizenet {

		protected static function get_first_item( $value ) {
			if ( ! is_array( $value ) ) {
				return $value;
			}

			$first = reset( $value );
			return is_array( $first ) ? $first : $value;
		}

		protected static function decode_api_response_body( $response_body = '' ) {
			if ( empty( $response_body ) ) {
				return null;
			}

			// Authorize.Net can prepend a UTF-8 BOM. Remove it before decoding.
			$response_body = preg_replace( '/^\xEF\xBB\xBF/', '', (string) $response_body );
			$response_body = trim( $response_body );

			$decoded_body = json_decode( $response_body, true );
			if ( JSON_ERROR_NONE === json_last_error() && is_array( $decoded_body ) ) {
				return $decoded_body;
			}

			if ( function_exists( 'simplexml_load_string' ) ) {
				libxml_use_internal_errors( true );
				$xml = simplexml_load_string( $response_body, 'SimpleXMLElement', LIBXML_NOCDATA );
				if ( false !== $xml ) {
					$decoded_body = json_decode( wp_json_encode( $xml ), true );
					libxml_clear_errors();
					if ( is_array( $decoded_body ) ) {
						if ( isset( $decoded_body['createTransactionResponse'] ) && is_array( $decoded_body['createTransactionResponse'] ) ) {
							return $decoded_body['createTransactionResponse'];
						}
						return $decoded_body;
					}
				}
				libxml_clear_errors();
			}

			return null;
		}

		public static function get_settings() {
			$settings = SftcyWordformBase::wordform_settings_page_payment_config();

			return array(
				'enabled'         => isset( $settings['authorizenet_enabled'] ) ? sanitize_text_field( $settings['authorizenet_enabled'] ) : 'no',
				'mode'            => isset( $settings['authorizenet_mode'] ) ? sanitize_text_field( $settings['authorizenet_mode'] ) : 'sandbox',
				'api_login_id'    => isset( $settings['authorizenet_api_login_id'] ) ? trim( sanitize_text_field( $settings['authorizenet_api_login_id'] ) ) : '',
				'client_key'      => isset( $settings['authorizenet_client_key'] ) ? trim( sanitize_text_field( $settings['authorizenet_client_key'] ) ) : '',
				'transaction_key' => isset( $settings['authorizenet_transaction_key'] ) ? trim( sanitize_text_field( $settings['authorizenet_transaction_key'] ) ) : '',
				'currency'        => isset( $settings['payment_currency'] ) ? strtoupper( sanitize_text_field( $settings['payment_currency'] ) ) : 'USD',
			);
		}

		public static function get_acceptjs_url() {
			$settings = self::get_settings();
			return ( isset( $settings['mode'] ) && 'live' === $settings['mode'] ) ? 'https://js.authorize.net/v1/Accept.js' : 'https://jstest.authorize.net/v1/Accept.js';
		}

		public static function get_api_endpoint() {
			$settings = self::get_settings();
			return ( isset( $settings['mode'] ) && 'live' === $settings['mode'] ) ? 'https://api2.authorize.net/xml/v1/request.api' : 'https://apitest.authorize.net/xml/v1/request.api';
		}

		public static function create_transaction( $amount = 0, $data_descriptor = '', $data_value = '', $form_id = '', $form_name = '', $customer_email = '' ) {
			$settings = self::get_settings();

			if ( 'yes' !== $settings['enabled'] ) {
				return array(
					'status'  => 'fail',
					'reason'  => 'Authorize.Net is disabled.',
					'comment' => __( 'Enable Authorize.Net in Payment settings first.', 'wordform-pro' ),
				);
			}

			if ( empty( $settings['api_login_id'] ) || empty( $settings['transaction_key'] ) || empty( $settings['client_key'] ) ) {
				return array(
					'status'  => 'fail',
					'reason'  => 'Authorize.Net credentials missing.',
					'comment' => __( 'Authorize.Net API Login ID, Client Key, or Transaction Key is missing.', 'wordform-pro' ),
				);
			}

			$amount          = max( 0, (float) $amount );
			$data_descriptor = sanitize_text_field( $data_descriptor );
			$data_value      = sanitize_text_field( $data_value );

			if ( $amount <= 0 ) {
				return array(
					'status'  => 'fail',
					'reason'  => 'Invalid Authorize.Net amount.',
					'comment' => __( 'Payment amount must be greater than zero.', 'wordform-pro' ),
				);
			}

			if ( empty( $data_descriptor ) || empty( $data_value ) ) {
				return array(
					'status'  => 'fail',
					'reason'  => 'Opaque payment data missing.',
					'comment' => __( 'Authorize.Net payment token is missing.', 'wordform-pro' ),
				);
			}

			$request_body = array(
				'createTransactionRequest' => array(
					'merchantAuthentication' => array(
						'name'           => $settings['api_login_id'],
						'transactionKey' => $settings['transaction_key'],
					),
					'refId' => sanitize_text_field( $form_id ),
					'transactionRequest' => array(
						'transactionType' => 'authCaptureTransaction',
						'amount'          => number_format( $amount, 2, '.', '' ),
						'payment'         => array(
							'opaqueData' => array(
								'dataDescriptor' => $data_descriptor,
								'dataValue'      => $data_value,
							),
						),
						'order'           => array(
							'invoiceNumber' => sanitize_text_field( $form_id ),
							'description'   => sprintf(
								/* translators: 1: form name, 2: form id */
								__( 'WordForm payment for %1$s (%2$s)', 'wordform-pro' ),
								sanitize_text_field( $form_name ),
								sanitize_text_field( $form_id )
							),
						),
					),
				),
			);

			if ( ! empty( $customer_email ) && is_email( $customer_email ) ) {
				$request_body['createTransactionRequest']['transactionRequest']['customer'] = array(
					'email' => sanitize_email( $customer_email ),
				);
			}

			$response = wp_remote_post(
				self::get_api_endpoint(),
				array(
					'timeout' => 45,
					'headers' => array(
						'Content-Type' => 'application/json',
						'Accept'       => 'application/json',
					),
					'body'    => wp_json_encode( $request_body ),
				)
			);

			if ( is_wp_error( $response ) ) {
				return array(
					'status'  => 'fail',
					'reason'  => 'Authorize.Net transaction request failed.',
					'comment' => $response->get_error_message(),
				);
			}

			$response_code = (int) wp_remote_retrieve_response_code( $response );
			$response_body = wp_remote_retrieve_body( $response );
			$decoded_body  = self::decode_api_response_body( $response_body );
			$txn_response  = isset( $decoded_body['transactionResponse'] ) ? $decoded_body['transactionResponse'] : array();
			$result_code   = isset( $decoded_body['messages']['resultCode'] ) ? strtoupper( sanitize_text_field( $decoded_body['messages']['resultCode'] ) ) : '';
			$response_code_num = isset( $txn_response['responseCode'] ) ? sanitize_text_field( $txn_response['responseCode'] ) : '';

			if ( $response_code < 200 || $response_code >= 300 || 'OK' !== $result_code || '1' !== $response_code_num || empty( $txn_response['transId'] ) ) {
				$error_message = __( 'Authorize.Net transaction could not be completed.', 'wordform-pro' );
				$error_item    = ! empty( $txn_response['errors']['error'] ) ? self::get_first_item( $txn_response['errors']['error'] ) : ( ! empty( $txn_response['errors'][0] ) ? self::get_first_item( $txn_response['errors'][0] ) : array() );
				$message_item  = ! empty( $decoded_body['messages']['message'] ) ? self::get_first_item( $decoded_body['messages']['message'] ) : array();

				if ( is_array( $error_item ) && ! empty( $error_item['errorText'] ) ) {
					$error_message = sanitize_text_field( $error_item['errorText'] );
				} elseif ( is_array( $message_item ) && ! empty( $message_item['text'] ) ) {
					$error_message = sanitize_text_field( $message_item['text'] );
				}

				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
					error_log(
						'WordForm Authorize.Net failure: ' . wp_json_encode(
							array(
								'http_status' => $response_code,
								'result_code' => $result_code,
								'response_code' => $response_code_num,
								'error_message' => $error_message,
								'raw' => $decoded_body,
								'raw_body' => $response_body,
							)
						)
					);
				}

				return array(
					'status'  => 'fail',
					'reason'  => 'Authorize.Net transaction failed.',
					'comment' => $error_message,
					'raw'     => $decoded_body,
				);
			}

			return array(
				'status'        => 'success',
				'paymentStatus' => 'APPROVED',
				'transactionId' => isset( $txn_response['transId'] ) ? sanitize_text_field( $txn_response['transId'] ) : '',
				'responseCode'  => $response_code_num,
				'authCode'      => isset( $txn_response['authCode'] ) ? sanitize_text_field( $txn_response['authCode'] ) : '',
				'amount'        => number_format( $amount, 2, '.', '' ),
				'currency'      => $settings['currency'],
				'accountNumber' => isset( $txn_response['accountNumber'] ) ? sanitize_text_field( $txn_response['accountNumber'] ) : '',
				'accountType'   => isset( $txn_response['accountType'] ) ? sanitize_text_field( $txn_response['accountType'] ) : '',
				'raw'           => $decoded_body,
			);
		}
	}
}
