<?php
/**
 * EverestForms Mollie processing class.
 *
 * @package EverestForms\Pro\Addons\Mollie\Process
 * @since   1.7.7
 */

namespace EverestForms\Pro\Addons\Mollie\Process;

use EverestForms\Pro\Addons\Mollie\Helpers;
use Mollie\Api;

/**
 * Mollie Post Processing Process.
 */
class Process {

	/**
	 * Primary class constructor.
	 */
	public function __construct() {
		add_action( 'init', array( $this, 'evf_mollie_payment_update' ), 20 );
		add_action( 'everest_forms_process_complete', array( $this, 'process_entry' ), 20, 4 );
	}

	/**
	 * Process entry for PayPal Standard.
	 *
	 * @param  array   $fields    Fields for the entry processing.
	 * @param  array   $entry     Entry object itself.
	 * @param  array   $form_data Form data for mapping purpose.
	 * @param  integer $entry_id  Entry id fetched from form task.
	 */
	public function process_entry( $fields, $entry, $form_data, $entry_id ) {
		if ( ! Helpers::is_mollie_enabled( $form_data ) ) {
			return false;
		}

		$data           = array();
		$payment_fields = evf_get_payment_items( $fields, $entry, $form_data );
		$total_amount   = evf_sanitize_amount( evf_get_total_payment( $fields, $entry, $form_data ) );
		$process        = apply_filters( 'everest_forms_entry_payment_process', true, $fields, $form_data, 'mollie', 'connection_1' );
		$discount       = apply_filters( 'everest_forms_coupon_discount', 0, $total_amount, $fields, $form_data );
		$total_amount  -= $discount;

		if ( $total_amount <= 0 || ! $process || empty( $entry_id ) || empty( $payment_fields ) || empty( $total_amount ) ) {

			return false;

		} else {
			// Update entry to include payment details.
			$entry_data = array(
				'status' => 'Pending',
				'type'   => 'payment',
				'meta'   => wp_json_encode(
					array(
						'payment_gateway'  => 'mollie',
						'payment_discount' => $discount,
						'payment_total'    => $total_amount,
						'payment_currency' => get_option( 'everest_forms_currency' ),
						'payment_mode'     => Helpers::get_mollie_mode(),
					)
				),
			);

			evf_payment_entries( $entry_id, $entry_data );
		}

		$mollie         = new \Mollie\Api\MollieApiClient();
		$mollie_api_key = Helpers::get_mollie_api_key();
		$mollie->setApiKey( $mollie_api_key );

		$webhook_url = Helpers::get_mollie_webhook_url( $form_data )
		? add_query_arg( array( 'everest_forms_mollie_webhook' => 'webhook' ), Helpers::get_mollie_webhook_url( $form_data ) )
		: '';

		// Build the return URL with hash.
		$query_args = 'form_id=' . $form_data['id'] . '&entry_id=' . $entry_id . '&hash=' . wp_hash( $form_data['id'] . ',' . $entry_id );
		if ( isset( $form_data['payments']['mollie']['redirect_url'] ) && ! empty( $form_data['payments']['mollie']['redirect_url'] ) ) {
			$return_url = $form_data['payments']['mollie']['redirect_url'];
			$return_url = esc_url_raw(
				add_query_arg(
					array(
						'everest_forms_return' => base64_encode( $query_args ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
					),
					apply_filters( 'everest_forms_mollie_return', $return_url, $form_data )
				)
			);
		} else {
			$return_url  = is_ssl() ? 'https:// ' : 'http://';
			$return_url .= $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
			if ( ! empty( $form_data['settings']['ajax_form_submission'] ) && ! empty( $_SERVER['HTTP_REFERER'] ) ) {
				$return_url = $_SERVER['HTTP_REFERER']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
			}
			$return_url = esc_url_raw(
				add_query_arg(
					array(
						'everest_forms_return' => base64_encode( $query_args ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
					),
					apply_filters( 'everest_forms_mollie_return', $return_url, $form_data )
				)
			);

		}

		if ( isset( $form_data['payments']['mollie']['enable_mollie_recurring'] ) && '1' === $form_data['payments']['mollie']['enable_mollie_recurring'] ) {
			try {
				$form_title   = isset( $form_data['settings']['form_title'] ) ? $form_data['settings']['form_title'] : '';
				$total_amount = $total_amount . '.00'; // As mollie accepts payment only in double.

				// Get the plan name.
				$evf_plan_name = isset( $form_data['payments']['mollie']['subscription_description'] ) ? $form_data['payments']['mollie']['subscription_description'] : $form_title . ' Subscription';

				// Extracting the names of the mapped fields.
				$customer_email_field      = isset( $form_data['payments']['mollie']['recurring']['email'] ) ? $form_data['payments']['mollie']['recurring']['email'] : '';
				$customer_first_name_field = isset( $form_data['payments']['mollie']['recurring']['customer_first_name'] ) ? $form_data['payments']['mollie']['recurring']['customer_first_name'] : '';
				$customer_last_name_field  = isset( $form_data['payments']['mollie']['recurring']['customer_last_name'] ) ? $form_data['payments']['mollie']['recurring']['customer_last_name'] : '';

				// Assigning the values for the customer creation.
				$customer_email      = isset( $entry['form_fields'][ $customer_email_field ] ) ? $entry['form_fields'][ $customer_email_field ] : '';
				$customer_first_name = isset( $entry['form_fields'][ $customer_first_name_field ] ) ? $entry['form_fields'][ $customer_first_name_field ] : '';
				$customer_last_name  = isset( $entry['form_fields'][ $customer_last_name_field ] ) ? $entry['form_fields'][ $customer_last_name_field ] : '';

				$customer_name = $customer_first_name . ' ' . $customer_last_name;

				// Create the customer in the mollie.
				$customer = $mollie->customers->create(
					array(
						'name'  => $customer_name,
						'email' => $customer_email,
					)
				);

				// Create a payment for mandate authorization.
				$payment = $mollie->payments->create(
					array(
						'amount'       => array(
							'currency' => get_option( 'everest_forms_currency', 'USD' ),
							'value'    => $total_amount,
						),
						'description'  => $evf_plan_name,
						'redirectUrl'  => $return_url,
						'webhookUrl'   => $webhook_url,
						'metadata'     => array(
							'entry_id' => $entry_id
						),
						'sequenceType' => \Mollie\Api\Types\SequenceType::SEQUENCETYPE_FIRST,
						'customerId'   => $customer->id,
					)
				);

				$payment_id                        = $payment->id;
				$mollie_entry                      = evf_get_entry( $entry_id );
				$payment_meta                      = json_decode( $mollie_entry->meta['meta'] );
				$payment_meta->payment_transaction = $payment_id;
				$entry_data                        = array(
					'meta' => wp_json_encode( $payment_meta )
				);

				evf_payment_entries( $entry_id, $entry_data, true );

				// Redirect the customer to the payment page to authorize the mandate.
				header( 'Location: ' . $payment->getCheckoutUrl() );
			} catch ( \Mollie\Api\Exceptions\ApiException $exception ) {
				evf_get_logger()->notice( print_r( $exception->getMessage(), true ) );
			}
		} else {
			try {
				$form_title   = isset( $form_data['settings']['form_title'] ) ? $form_data['settings']['form_title'] : '';
				$total_amount = $total_amount . '.00'; // As mollie accepts payment only in double.
				$response     = $mollie->payments->create(
					array(
						'amount'      => array(
							'currency' => get_option( 'everest_forms_currency', 'USD' ),
							'value'    => $total_amount,
						),
						'description' => $form_title,
						'method'      => 'creditcard',
						'redirectUrl' => $return_url,
						'webhookUrl'  => $webhook_url,
						'metadata'    => array(
							'entry_id' => $entry_id
						)
					)
				);

				$payment_id                        = $response->id;
				$mollie_entry                      = evf_get_entry( $entry_id );
				$payment_meta                      = json_decode( $mollie_entry->meta['meta'] );
				$payment_meta->payment_transaction = $payment_id;
				$entry_data                        = array(
					'meta' => wp_json_encode( $payment_meta )
				);

				evf_payment_entries( $entry_id, $entry_data, true );

				// Redirect the customer to the payment page to authorize the mandate.
				header( 'Location: ' . $response->getCheckoutUrl() );
				$payment_response = $mollie->payments->get( $payment_id );
			} catch ( \Mollie\Api\Exceptions\ApiException $exception ) {
				evf_get_logger()->notice( print_r( $exception->getMessage(), true ) );
			}
		}
	}

	/**
	 * Updates the payment status accordingly.
	 *
	 * @since 1.7.7
	 */
	public function evf_mollie_payment_update() {
		if ( ! isset( $_GET['everest_forms_return'] ) && empty( $_GET['everest_forms_return'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
			return '';
		}
		$evf_mollie_data = wp_unslash( $_GET['everest_forms_return'] ); //phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
		$evf_mollie_data = base64_decode( $evf_mollie_data );
		wp_parse_str( $evf_mollie_data, $mollie_data );
		$form_id   = isset( $mollie_data['form_id'] ) ? absint( $mollie_data['form_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
		$form_obj  = EVF()->form->get( $form_id );
		$form_data = ( ! empty( $form_obj->post_content ) ) ? evf_decode( $form_obj->post_content ) : '';
		if ( isset( $_GET['everest_forms_return'] ) && Helpers::is_mollie_enabled( $form_data ) ) { // phpcs:ignore WordPress.Security.NonceVerification
			$mollie_entry_id = isset( $mollie_data['entry_id'] ) ? $mollie_data['entry_id'] : '0';
			// Extracting the entry details to get payment_id.
			$mollie_details = evf_get_entry( absint( $mollie_entry_id ) );
			$payment_meta   = json_decode( $mollie_details->meta['meta'] );
			$payment_id     = $payment_meta->payment_transaction;

			// Creating object to mollie to manipulate the data from mollie payment side.
			$mollie         = new \Mollie\Api\MollieApiClient();
			$mollie_api_key = Helpers::get_mollie_api_key();
			$mollie->setApiKey( $mollie_api_key );

			// Mollie payment response.
			$mollie_response = $mollie->payments->get( $payment_id );

			$mollie_payment_status = $mollie_response->status;

			if ( '1' === $form_data['payments']['mollie']['enable_mollie'] && $form_data['payments']['mollie']['enable_mollie_recurring'] ) {
				$transaction          = $mollie->payments->get( $payment_id );
				$evf_plan_name        = isset( $form_data['payments']['mollie']['subscription_description'] ) ? $form_data['payments']['mollie']['subscription_description'] : $form_title . ' Subscription';
				$recurring_start_date = gmdate( 'Y-m-d' );

				$recurring_payment_type = isset( $form_data['payments']['mollie']['interval'] ) ? $form_data['payments']['mollie']['interval'] : 'YEARS';
				$recurring_duration     = isset( $form_data['payments']['mollie']['interval_count'] ) ? $form_data['payments']['mollie']['interval_count'] : '1';

				$recurring_interval_type = $recurring_duration . ' ' . evf_strtolower( $recurring_payment_type );

				if ( ! isset( $recurring_interval_type ) && empty( $recurring_payment_type ) ) {
					return '';
				}

				switch ( $recurring_payment_type ) {
					case 'DAYS':
						$days           = 1 * absint( $recurring_duration );
						$recurring_time = floor( 365 / $days );
						break;

					case 'WEEKS':
						$days_in_week   = 7 * absint( $recurring_duration );
						$recurring_time = floor( 365 / $days_in_week );
						break;

					case 'MONTHS':
						$month_in_days  = 30 * absint( $recurring_duration );
						$recurring_time = floor( 365 / $month_in_days );
						break;

					case 'YEARS':
					default:
						$days_in_year   = 365 * absint( $recurring_duration );
						$recurring_time = floor( 365 / $days_in_year );
						break;
				}

				$customer = $mollie->customers->get( $mollie_response->customerId );
				try {
					$customer_subscription = $customer->createSubscription(
						array(
							'amount'      => array(
								'currency' => get_option( 'everest_forms_currency', 'USD' ),
								'value'    => $mollie_response->amount->value,
							),
							'times'       => $recurring_time,
							'interval'    => $recurring_interval_type,
							'startDate'   => $recurring_start_date,
							'description' => $evf_plan_name,
							'webhookUrl'  => '',
						)
					);
				} catch ( \Mollie\Api\Exceptions\ApiException $exception ) {
					evf_get_logger()->notice( print_r( $exception->getMessage(), true ) );
				}
			}
			$payment_details_url               = $mollie_response->_links->dashboard->href;
			$payment_meta->payment_details_url = $payment_details_url;
			switch ( $mollie_payment_status ) {
				case 'paid':
					evf_payment_entries(
						$mollie_entry_id,
						array(
							'status' => 'complete',
							'meta'   => wp_json_encode( $payment_meta )
						),
						true
					);
					break;
				case 'open':
					evf_payment_entries(
						$mollie_entry_id,
						array(
							'status' => 'pending',
						),
						true
					);
					break;
				default:
					evf_payment_entries(
						$mollie_entry_id,
						array(
							'status' => 'failed',
						),
						true
					);
					break;
			}
		} else {
			return '';
		}
	}
}
