<?php
/**
* @package CembraPay Payment Gateway for WooCommerce
* @author  Adrian Emil Tudorache
* @license GPL-2.0+
* @link    https://www.tudorache.me/
*/

namespace CembraPayWoo;

if ( ! defined( 'ABSPATH' ) ) {
	header( 'Status: 403 Forbidden' );
	header( 'HTTP/1.1 403 Forbidden' );
	exit;
}

class CembraPay {

	private $gateway_settings;

	private $mode;

	private $request_type;

	private $request_types;

	private $token_scope;

	private $request_args;

	private $request_params;

	private $request_url;

	private $token;

	private $api_version;

	private $logs;

	private $order_id;

	private $order_number;
	
	private $order;

	private $currency;

	function __construct( int $order_id = 0, string $request_type = '', array $request_params = array() ) {

		$this->gateway_settings = Service::get_payment_gateway_settings();
		$this->mode = isset( $this->gateway_settings['mode'] ) ? $this->gateway_settings['mode'] : 1;

		$this->api_version = 'v1.0';
		
		$this->logs = new Logs;
		$this->order_id = $order_id;
		
		if( $order_id ) {
			$this->order = wc_get_order( $order_id );
		}
		
		$this->order_number = $this->get_order_number();
		$this->request_type   = $request_type;
		$this->request_params = $request_params;
		
		$currency = get_option('woocommerce_currency');
        $currency = $currency ? strtoupper( $currency ) : 'USD';

		$this->currency = $currency;

		$this->token_scope = $this->mode == 1 ? '59ff4c0b-7ce8-42f0-983b-306706936fa1/.default' : '80d0ac9d-9d5c-499c-876e-71dd57e436f2/.default';

		$this->request_types = array(
			'token' => array(
				'name' => 'TOK',
				'url'  => array(
					1 => 'https://login.microsoftonline.com/4c6a6b34-0bcf-4dff-b3a7-949dcb43a07e/oauth2/v2.0/token',
					2 => 'https://login.microsoftonline.com/4c6a6b34-0bcf-4dff-b3a7-949dcb43a07e/oauth2/v2.0/token'
				)
			),
			'checkout' => array(
				'name' => 'CHK',
				'url'  => array(
					1 => sprintf( 'https://ext-test.api.cembrapay.ch/%s/Checkout', $this->api_version ),
					2 => sprintf( 'https://api.cembrapay.ch/%s/Checkout', $this->api_version ),
				)
			),
			'direct'   => array(
				'name' => 'AUT',
				'url'  => array(
					1 => sprintf( 'https://ext-test.api.cembrapay.ch/%s/Transactions/authorize', $this->api_version ),
					2 => sprintf( 'https://api.cembrapay.ch/%s/Transactions/authorize', $this->api_version )
				)
			),
			'confirmation' => array(
				'name' => 'CFM',
				'url'  => array(
					1 => sprintf( 'https://ext-test.api.cembrapay.ch/%s/Transactions/confirm', $this->api_version ),
					2 => sprintf( 'https://api.cembrapay.ch/%s/Transactions/confirm', $this->api_version )
				)
			),
			'settlement' => array(
				'name' => 'SET',
				'url'  => array(
					1 => sprintf( 'https://ext-test.api.cembrapay.ch/%s/Transactions/settle', $this->api_version ),
					2 => sprintf( 'https://api.cembrapay.ch/%s/Transactions/settle', $this->api_version )
				)
			),
			'settlement_byjuno' => array(
				'name' => 'SET',
				'url'  => array(
					1 => sprintf( 'https://ext-test.api.cembrapay.ch/%s/Transactions/settle', $this->api_version ),
					2 => sprintf( 'https://api.cembrapay.ch/%s/Transactions/settle', $this->api_version )
				)
			),
			'cancel' => array(
				'name' => 'CAN',
				'url'  => array(
					1 => sprintf( 'https://ext-test.api.cembrapay.ch/%s/Transactions/cancel', $this->api_version ),
					2 => sprintf( 'https://api.cembrapay.ch/%s/Transactions/cancel', $this->api_version )
				)
			),
			'cancel_byjuno' => array(
				'name' => 'CAN',
				'url'  => array(
					1 => sprintf( 'https://ext-test.api.cembrapay.ch/%s/Transactions/cancel', $this->api_version ),
					2 => sprintf( 'https://api.cembrapay.ch/%s/Transactions/cancel', $this->api_version )
				)
			),
			'credit_note' => array(
				'name' => 'CNT',
				'url'  => array(
					1 => sprintf( 'https://ext-test.api.cembrapay.ch/%s/Transactions/credit', $this->api_version ),
					2 => sprintf( 'https://api.cembrapay.ch/%s/Transactions/credit', $this->api_version )
				)
			),
			'credit_note_byjuno' => array(
				'name' => 'CNT',
				'url'  => array(
					1 => sprintf( 'https://ext-test.api.cembrapay.ch/%s/Transactions/credit', $this->api_version ),
					2 => sprintf( 'https://api.cembrapay.ch/%s/Transactions/credit', $this->api_version )
				)
			),
			'status' => array(
				'name' => 'CST',
				'url'  => array(
					1 => sprintf( 'https://ext-test.api.cembrapay.ch/%s/Checkout/status', $this->api_version ),
					2 => sprintf( 'https://api.cembrapay.ch/%s/Checkout/status', $this->api_version ),
				)
			)
		);

		$this->token();

	}

	public function get_order_id(): int {
		return $this->order_id;
	}

	public function set_order_id( int $order_id ): void {
		$this->order_id = $order_id;
	}

	private function get_order_number(): string {

		if( 
			isset( $this->gateway_settings['order_id_source'] ) 
			&& $this->gateway_settings['order_id_source'] == 2
			&& isset( $this->gateway_settings['order_id_meta_key'] )
			&& $this->gateway_settings['order_id_meta_key']
		) {
			$order_id_meta_key = $this->gateway_settings['order_id_meta_key'];
			$order_id_meta_value = $this->order->get_meta( $order_id_meta_key );
			if( $order_id_meta_value ) {
				return $order_id_meta_value;
			}
		}

		return $this->order_id;

	}

	public function get_request_type(): string {
		return $this->request_type;
	}

	public function set_request_type( string $request_type ): void {
		$this->request_type = $request_type;
	}

	public function get_request_args(): array|object {
		return $this->request_args;
	}

	public function set_request_args( array $request_args ): void {
		$this->request_args = $request_args;
	}

	private function get_token(): array|object {
		return $this->token;
	}

	private function set_token( array|object $token ): void {
		$this->token = $token;
	}

	public function token() {

        $access_token = get_option( 'cembrapay_access_token' );
        
        if( $access_token ) {

            list($header, $payload, $signature) = explode('.', base64_decode($access_token));
            $jsonToken    = base64_decode( $payload );
            $decoded_token = json_decode( $jsonToken, true );

            if( $decoded_token && isset( $decoded_token['exp'] ) && $decoded_token['exp'] < time() ) {

                $this->refresh_token();

            } else {

                $token_type = get_option( 'cembrapay_token_type' );
                $token = array(
                    'token' => base64_decode( $access_token ),
                    'type'  => $token_type ? $token_type : 'Bearer'
                );
                
                $this->set_token( $token );

                return $token;

            }

        }

        $this->refresh_token();

    }

    public function refresh_token(): bool {

        $client_id     = isset( $this->gateway_settings['client_id'] ) ? $this->gateway_settings['client_id'] : '';
	    $client_secret = isset( $this->gateway_settings['client_secret'] ) ? $this->gateway_settings['client_secret'] : '';

        if( $client_id && $client_secret ) {

            $credentials = base64_encode( $client_id . ':' . $client_secret );

            $url  = $this->request_types['token']['url'][$this->mode];
			
            $args = array(
                'headers' => array(
                    'Authorization' => 'Basic ' . $credentials,
                    'Content-Type' => 'application/x-www-form-urlencoded'
                ),
                'body' => array(
                    'grant_type' => 'client_credentials',
                    'scope' => $this->token_scope,
                    'client_id' => $client_id,
                    'client_secret' => $client_secret
                )
            );

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

            if( is_wp_error( $response ) ) {
                return false;
            }

            $body = wp_remote_retrieve_body( $response );
            $body = json_decode( $body );

            if( isset( $body->access_token ) ) {
                update_option( 'cembrapay_access_token', base64_encode( $body->access_token ) );
            }

            if( isset( $body->token_type ) ) {
                update_option( 'cembrapay_token_type', $body->token_type );
            }

        }

        $this->token();

        return true;

    }

	private function process_order_id( \WC_Order $order ): string|int {

        $use_order_id_prefix = isset( $this->gateway_settings['use_order_id_prefix'] ) ? $this->gateway_settings['use_order_id_prefix'] : false;

        $order_id_prefix = '';

        if( $use_order_id_prefix ) {
            $order_id_prefix    = isset( $this->gateway_settings['order_id_prefix'] ) ? $this->gateway_settings['order_id_prefix'] . '_' : '';
        }

        $order_id_source = isset( $this->gateway_settings['order_id_source'] ) ? $this->gateway_settings['order_id_source'] : '';

        if( $order_id_source == 1 ) {
            return $order_id_prefix . $this->order_id;
        }

        if( $order_id_source == 2 ) {
            return $order_id_prefix . $this->order_number;
        }

        return $order_id_prefix . $this->order_id;

    }

    private function process_legacy_order_id(): string|int {

        $cembrapay_settings  = get_option( 'woocommerce_cembrapay_legacy_settings' );
        $use_order_id_prefix = isset( $cembrapay_settings['use_order_id_prefix'] ) ? $cembrapay_settings['use_order_id_prefix'] : false;
        $order_id_prefix     = '';

        if( $use_order_id_prefix ) {
            $order_id_prefix = isset( $cembrapay_settings['order_id_prefix'] ) ? $cembrapay_settings['order_id_prefix'] . '_' : '';
        }

        return $order_id_prefix ? $order_id_prefix . $this->order_number : $this->order_number;

    }

	public function request( array $args = array() ): array {

        global $wpdb;

        $date = new \DateTime();

		if( ! $this->maybe_send_request() ) {
			return array(
				'status' => 'ERROR',
				'errors' => 'Invalid request'
			);
		}

		$this->build_request_args();

		$request_args = array(
            'headers' => array(
                'Authorization' => $this->token['type'] . ' ' . $this->token['token'],
                'Content-Type'  => 'application/json'
            ),
            'timeout' => 60,
            'body'    => json_encode( $this->request_args )
        );

		$response = wp_remote_post( $this->request_types[$this->request_type]['url'][$this->mode], $request_args );
		$request_args['requestType'] = $this->request_type;

		$log_data = array(
			'order_id'     => $this->order_id,
			'url'          => $this->request_types[$this->request_type]['url'][$this->mode],
			'first_name'   => $this->order->get_billing_first_name(),
			'last_name'    => $this->order->get_billing_last_name(),
			'req_type'     => $this->request_types[$this->request_type]['name'],
			'proc_status'  => '',
			'request_args' => $request_args,
			'response'     => $response,
			'body'         => '',
			'datetime'     => $date->format('Y-m-d H:i:s')
		);

		if( ! is_wp_error( $response ) ) {

			$body = wp_remote_retrieve_body( $response );
            $body = $body ? (array) json_decode( $body ) : null;
            $body = $body ? json_decode(json_encode($body), true) : null;

			$log_data['body']        = $body;
			$log_data['proc_status'] = isset( $body['processingStatus'] ) && $body['processingStatus'] ? $body['processingStatus'] : '';

			if( $body ) {

				$this->process_response_body( $body, $request_args );

				if( isset( $body['processingStatus'] ) && $body['processingStatus'] == 'ERROR' && isset( $body['errors'] ) ) {

                    $order_errors = $this->order->get_meta( '_cembrapay_errors', true );
                    $order_errors = $order_errors ? $order_errors : array();
                    $order_errors[ time() ] = $body['errors'];
                    $this->order->update_meta_data( '_cembrapay_errors', $order_errors );

                    $this->order->save();

                    $this->logs->log_cembrapay_api_request( $log_data );

                    return array(
                        'status' => 'ERROR',
                        'errors' => $body['errors']
                    );

                }

				if( isset( $body['processingStatus'] ) && $body['processingStatus'] == 'DECLINED' ) {

                    $order_errors = $this->order->get_meta( '_cembrapay_errors', true );
                    $order_errors = $order_errors ? $order_errors : array();
                    $order_errors[ time() ] = $body['errors'];
                    $this->order->update_meta_data( '_cembrapay_errors', $order_errors );

                    $this->order->save();

                    $this->logs->log_cembrapay_api_request( $log_data );

                    return array(
                        'status' => 'DECLINED',
                        'errors' => $body['errors']
                    );

                }

			}

			if( ! $body ) {
				
				return array(
					'status' => 'DECLINED',
					'errors' => esc_html__( 'No response from API', 'cembrapay' )
				);

			}
            
		}

		$this->logs->log_cembrapay_api_request( $log_data );

		if( is_wp_error( $response ) ) {
            
			$order_errors = $this->order->get_meta( '_cembrapay_errors', true );
            $order_errors = $order_errors ? $order_errors : array();
            $order_errors[ time() ] = $response;
            $this->order->update_meta_data( '_cembrapay_errors', $order_errors );
            $this->order->save();

			return array(
                'status' => 'ERROR',
                'errors' => $response->get_error_message()
            );

        }

		// If all goes well, return success
		return array(
            'status' => 'SUCCESS',
            'redirect' => isset( $body['redirectUrlCheckout'] ) && $body['redirectUrlCheckout'] ? $body['redirectUrlCheckout'] : ''
        );

	}

	private function maybe_send_request(): bool {

		switch( $this->request_type ) {
			case 'confirmation':
				$confirmation = $this->order->get_meta( '_cembrapay_confirmation_response', true );
				if( $confirmation ) {
					return false;
				}
			break;
			case 'settlement':
				$settlement        = $this->order->get_meta( '_cembrapay_settlement', true );
				$checkout_response = $this->order->get_meta( '_cembrapay_checkout_response', true );
				if( $settlement || ! $checkout_response ) {
					return false;
				}
			break;
			case 'settlement_byjuno':
				$settlement = $this->order->get_meta( 's4_sent', true );
				if( $settlement ) {
					return false;
				}
			break;
			case 'credit_note':
				$settlement = $this->order->get_meta( '_cembrapay_settlement', true );
				if( ! $settlement ) {
					return false;
				}
			break;
			case 'cancel': case 'cancel_byjuno':
				$cancellation = $this->order->get_meta( '_cembrapay_cancellation', true );
				if( $cancellation ) {
					return false;
				}
			break;
		}

		return true;

	}

	private function process_response_body( array|object $body = array(), array|object $request_args = array() ): void {

		switch( $this->request_type ) {
			case 'direct':

                $this->order->update_meta_data( '_cembrapay_checkout_type', 'direct' );

				if( 
					isset( $body['processingStatus'] ) && $body['processingStatus'] == 'AUTHORIZED'
					|| isset( $body['processingStatus'] ) && $body['processingStatus'] == 'DECLINED'
				) {
					$this->order->update_meta_data( '_cembrapay_checkout_request', $request_args );
					$this->order->update_meta_data( '_cembrapay_checkout_response', $body );
				}

			break;
			case 'checkout':

				$this->order->update_meta_data( '_cembrapay_checkout_type', 'checkout' );

				if( isset( $body['processingStatus'] ) && $body['processingStatus'] == 'SUCCESS' ) {
					$this->order->update_meta_data( '_cembrapay_checkout_request', $request_args );
					$this->order->update_meta_data( '_cembrapay_checkout_response', $body );
				}

			break;
			case 'confirmation':

				if( isset( $body['processingStatus'] ) && $body['processingStatus'] == 'SUCCESS' ) {
					$this->order->update_meta_data( '_cembrapay_confirmation_request', $request_args );
					$this->order->update_meta_data( '_cembrapay_confirmation_response', $body );
				}

			break;
			case 'settlement': case 'settlement_byjuno':

				if( isset( $body['processingStatus'] ) && $body['processingStatus'] == 'SETTLED' ) {
					if( isset( $body['settlement'] ) && $body['settlement'] ) {
						$this->order->update_meta_data( '_cembrapay_settlement', $body['settlement'] );
					}
					$this->order->update_meta_data( '_cembrapay_settlement_request', $request_args );
					$this->order->update_meta_data( '_cembrapay_settlement_response', $body );
				}

			break;
			case 'cancel': case 'cancel_byjuno':

				if( isset( $body['processingStatus'] ) && $body['processingStatus'] == 'SUCCESS' ) {
					$this->order->update_meta_data( '_cembrapay_cancellation', $body );
				}

			break;
			case 'credit_note': case 'credit_note_byjuno':

				if( isset( $body['processingStatus'] ) && $body['processingStatus'] == 'SUCCESS' ) {

					$credit_notes = $this->order->get_meta( '_cembrapay_credit_notes', true );
					$credit_notes = $credit_notes ? $credit_notes : array();

					$credit_notes[ time() ] = $body;
					$this->order->update_meta_data( '_cembrapay_credit_notes', $credit_notes );
					
				}

			break;
			case 'status':

				$status_checks = $this->order->get_meta( '_cembrapay_status_checks', true );
				$status_checks = $status_checks ? $status_checks : array();

				if( isset( $body['processingStatus'] ) && $body['processingStatus'] == 'SUCCESS' ) {
					if( count( $status_checks ) > 10 ) {
						unset( $status_checks[ array_key_first( $status_checks ) ] ); // Keep only last 10 status checks
					}

					$status_checks[ time() ] = $body;

					$this->order->update_meta_data( '_cembrapay_status_checks', $status_checks );
				}

			break;
		}

		$this->order->save();

	}

	private function build_request_args() {

		$date = new \DateTime();

		switch( $this->request_type ) {

			case 'checkout': case 'direct':

				$success_url   = wc_get_endpoint_url( 'order-received', $this->order_id, wc_get_checkout_url() );
                $order_key     = $this->order->get_order_key();
                $success_url   = $success_url ? add_query_arg( array( 'key' => $order_key ), $success_url ) : site_url();

                $order_pay_url = $this->order->get_checkout_payment_url();
                $order_pay_url = $order_pay_url ? $order_pay_url : $success_url;

                $success_url   = base64_encode( add_query_arg( array( 'cembrapay' => 'success' ), $success_url ) );
                $error_url     = base64_encode( add_query_arg( array( 'cembrapay' => 'error' ), $order_pay_url ) );
                $cancel_url    = base64_encode( add_query_arg( array( 'cembrapay' => 'cancel' ), $order_pay_url ) );

                $user_data = Service::parse_order_addresses( $this->order );

				$payment_method = $this->order->get_meta( '_installment_type' );
                $payment_method = $payment_method ? $payment_method : ( $user_data['billing']['company'] ? 'SINGLE-INVOICE' : 'CEMBRAPAY-INVOICE' );

                $invoice_type   = $this->order->get_meta( '_invoice_type' );
                $invoice_type   = $invoice_type ? $invoice_type : 'EMAIL';

                $cembrapay_details = array(
                    'cembraPayPaymentMethod' => $payment_method,
                    'invoiceDeliveryType'    => $invoice_type
                );

				$billing_company = $user_data['billing']['company'];
				$customer_type   = $billing_company ? 'C' : 'P';

				$customer_details = array();

				$locale = explode( '_', get_locale() );
				if( $locale && is_array( $locale ) ) {
					$customer_details['language'] = $locale[0];
				}

				$customer_details['custType'] = $customer_type;

				$threatmetrix_session_id = Service::get_threatmetrix_session_id();

				switch( $customer_type ) {
					case 'C':
						$customer_details['companyName'] = $billing_company;
						$company_reg = $this->order->get_meta( '_company-reg' );
						if( $company_reg ) {
							$customer_details['companyRegNum'] = $company_reg;
						}
					break;
					case 'P':
						$customer_details['firstName'] = $user_data['billing']['first_name'];
						$customer_details['lastName']  = $user_data['billing']['last_name'];
					break;
				}

                $customer_id                         = $this->order->get_customer_id();
                $customer_details['merchantCustRef'] = $customer_id ? 'user' . $customer_id : 'guest' . time();
                $customer_details['loggedIn']        = is_user_logged_in();

                if( $this->request_type == 'direct' && $customer_type == 'P' ) {
					
					$birthdate = $this->order->get_meta('_user-birthdate');
					if( $birthdate ) {
                    	$customer_details['dateOfBirth'] = $this->order->get_meta('_user-birthdate');
					}

					$salutation = $this->order->get_meta('_user-salutation');
					if( $salutation ) {
                    	$customer_details['salutation']  = $salutation;
					}
                }

				$merchant_order_ref = $this->process_order_id( $this->order );

				$request_args = array(
                    'requestMsgId'       => Service::generate_uuid(),
                    'requestMsgDateTime' => $date->format('Y-m-d\TH:i:s\Z'),
                    'idempotencyKey'     => Service::generate_uuid(),
                    'merchantOrderRef'   => $merchant_order_ref,
                    'amount'             => number_format( floatval( $this->order->get_total() ) * 100, 0, '', '' ),
                    'currency'           => $this->currency,
                    'custDetails'        => $customer_details,
                    'custContacts'       => array(
                        'email'       => $user_data['billing']['email'],
                        'phoneMobile' => $user_data['billing']['phone']
                    ),
                    'cembraPayDetails'   => $cembrapay_details,
                    'customerConsents'   => array(
                        array(
                            'consentType'       => 'CEMBRAPAY-TC',
                            'consentProvidedAt' => 'MERCHANT',
                            'consentDate'       => $date->format('Y-m-d\TH:i:s\Z'),
                            'consentReference'  => 'Q1A='
                        )
                    ),
                    'billingAddr'        => array(
						'addrFirstLine'  => $user_data['billing']['address_1'],
						'addrSecondLine' => $user_data['billing']['address_2'],
						'postalCode'     => $user_data['billing']['postcode'],
						'town'           => $user_data['billing']['city'],
						'country'        => $user_data['billing']['country']
					),
                    'merchantDetails'    => array(
                        'returnUrlSuccess'  => $success_url,
                        'returnUrlError'    => $error_url,
                        'returnUrlCancel'   => $cancel_url,
                        'integrationModule' => CEMBRAPAYTITLE . ' ' . CEMBRAPAYVERSION
					)
				);

				if( $this->request_type == 'direct' ) {
					
					$request_args['sessionInfo'] = array(
						'tmxSessionId' => $threatmetrix_session_id,
						'sessionIp'    => Service::get_user_ip_address()
					);

				}

				if( $user_data['shipping_different'] ) {

					$request_args['deliveryDetails'] = array(
						'deliveryDetailsDifferent' => true,
						'deliveryFirstName'        => $user_data['shipping']['first_name'],
						'deliveryLastName'         => $user_data['shipping']['last_name'],
						'deliveryCompanyName'      => $user_data['shipping']['company'],
						'deliveryAddrFirstLine'    => $user_data['shipping']['address_1'],
						'deliveryAddrSecondLine'   => $user_data['shipping']['address_2'],
						'deliveryAddrPostalCode'   => $user_data['shipping']['postcode'],
						'deliveryAddrTown'         => $user_data['shipping']['city'],
						'deliveryAddrCountry'      => $user_data['shipping']['country']
					);

				}

                $this->set_request_args( $request_args );

			break;
			case 'confirmation':

                $checkout_response = $this->order->get_meta( '_cembrapay_checkout_response', true );

                $this->set_request_args( array(
                    'requestMsgId'       => $checkout_response['requestMsgId'],
                    'requestMsgDateTime' => $checkout_response['requestMsgDateTime'],
                    'transactionId'      => $checkout_response['transactionId']
                ) );

            break;
			case 'settlement':

                $checkout_response = $this->order->get_meta( '_cembrapay_checkout_response', true );

				$merchant_invoice_ref = $this->process_order_id( $this->order );

                $amount = $this->order->get_total() - $this->order->get_total_refunded();

                $this->set_request_args( array(
                    'transactionId'      => $checkout_response['transactionId'],
                    'merchantOrderRef'   => $checkout_response['merchantOrderRef'],
                    'settlementDetails'  => array(
                        'merchantInvoiceRef' => $merchant_invoice_ref,
                        'isFinal'            => true
                    ),
                    'amount'             => number_format( floatval( $amount ) * 100, 0, '', '' ),
                    'currency'           => $this->currency,
                    'requestMsgId'       => $checkout_response['requestMsgId'],
                    'requestMsgDateTime' => $checkout_response['requestMsgDateTime']
                ) );

            break;
			case 'settlement_byjuno':

                $this->order->add_order_note( esc_html__( 'The order has initially been paid with Byjuno, but the settlement has been sent to CembraPay', 'cembrapay' ) );

				$request_args = array(
					'merchantOrderRef'   => $this->process_legacy_order_id(),
					// 'merchantOrderRef'   => $this->order_number,
					'requestMsgId'       => Service::generate_uuid(),
					'requestMsgDateTime' => $date->format('Y-m-d\TH:i:s\Z'),
					'amount'             => number_format( floatval( $this->order->get_total() ) * 100, 0, '', '' ),
					'currency'           => $this->currency,
					'settlementDetails'  => array(
						'merchantInvoiceRef' => $this->order_number,
						// 'isFinal'            => true
					)
				);

                $this->set_request_args( $request_args );

            break;
			case 'cancel':

                $checkout_response = $this->order->get_meta( '_cembrapay_checkout_response', true );

				$amount = $this->order->get_meta( '_initial_total', true );
				$amount = $amount ? number_format( floatval( $amount ) * 100, 0, '', '' ) : 0;

				if( ! $amount ) {
					$order_total = floatval( $this->order->get_total() ) * 100;
					$amount = isset( $this->request_params['amount'] ) ? number_format( floatval( $this->request_params['amount'] ) * 100, 0, '', '' ) : $order_total;
				}

                $this->set_request_args( array(
                    'transactionId'      => $checkout_response['transactionId'],
                    'merchantOrderRef'   => $checkout_response['merchantOrderRef'],
                    'amount'             => $amount,
                    'currency'           => $this->currency,
                    'requestMsgId'       => $checkout_response['requestMsgId'],
                    'requestMsgDateTime' => $checkout_response['requestMsgDateTime'],
                    'isFullCancelation'  => true
                ) );

            break;

            case 'cancel_byjuno':

				$this->order->add_order_note( esc_html__( 'The order has initially been paid with Byjuno, but the cancellation request has been sent to CembraPay', 'cembrapay' ) );

                $order_total = floatval( $this->order->get_total() ) * 100;

                $amount = isset( $this->request_params['amount'] ) ? number_format( floatval( $this->request_params['amount'] ) * 100, 0, '', '' ) : $order_total;

                $is_full_cancellation = $order_total == $amount ? true : false;

                $request_args = array(
					'merchantOrderRef'   => $this->process_legacy_order_id(),
					'requestMsgId'       => Service::generate_uuid(),
					'requestMsgDateTime' => $date->format('Y-m-d\TH:i:s\Z'),
					'amount'             => $amount,
					'currency'           => $this->currency,
					'isFullCancelation'  => $is_full_cancellation
				);

                $this->set_request_args( $request_args );

            break;

            case 'credit_note':

                $checkout_response = $this->order->get_meta( '_cembrapay_checkout_response', true );

                $order_total = floatval( $this->order->get_total() ) * 100;

                $amount = isset( $this->request_params['amount'] ) ? number_format( floatval( $this->request_params['amount'] ) * 100, 0, '', '' ) : $order_total;

                $request_args = array(
                    'transactionId'      => $checkout_response['transactionId'],
                    'merchantOrderRef'   => $checkout_response['merchantOrderRef'],
                    'amount'             => $amount,
                    'currency'           => $this->currency,
                    'requestMsgId'       => $checkout_response['requestMsgId'],
                    'requestMsgDateTime' => $checkout_response['requestMsgDateTime']
                );

                $settlement_data = $this->order->get_meta('_cembrapay_settlement', true);
                if( $settlement_data ) {
                    $request_args['settlementDetails'] = $settlement_data;
                }

				$this->set_request_args( $request_args );

            break;

            case 'credit_note_byjuno':

				$this->order->add_order_note( esc_html__( 'The order has initially been paid with Byjuno, but the credit note request has been sent to CembraPay', 'cembrapay' ) );

                $request_args = array(
					'merchantOrderRef'   => $this->process_legacy_order_id(),
					'requestMsgId'       => Service::generate_uuid(),
					'requestMsgDateTime' => $date->format('Y-m-d\TH:i:s\Z'),
					'amount' 		     => isset( $this->request_params['amount'] ) ? 
                    number_format( floatval( $this->request_params['amount'] ) * 100, 0, '', '' ) : 
                    number_format( floatval( $this->order->get_total() ) * 100, 0, '', '' ),
					'currency'           => $this->currency,
					'settlementDetails'  => array(
						'merchantInvoiceRef' => $this->order_number
					)
				);

                $this->set_request_args( $request_args );

            break;
            case 'status':

                $checkout_response = $this->order->get_meta( '_cembrapay_checkout_response', true );

                $this->set_request_args( array(
                    'requestMsgId'       => $checkout_response['requestMsgId'] ?? '',
                    'requestMsgDateTime' => $checkout_response['requestMsgDateTime'] ?? '',
                    'checkoutProcessId'  => $checkout_response['checkoutProcessId'] ?? ''
                ) );

            break;

		}
	}

}
?>