<?php
/**
 * Google Pay
 */

namespace WkwcAdyen\Includes\Payment_Methods;

// prevent direct access data leaks
use Automattic\WooCommerce\StoreApi\Utilities\NoticeHandler;

defined( 'ABSPATH' ) || exit;

use WkwcAdyen\Helper\Common\Wkwc_Adyen_Service_Util;

use WkwcAdyen\Helper\Common\Wkwc_Adyen_Checkout_Action;

class Wkwc_Adyen_Googlepay extends Wkwc_Adyen_Abstract_Gateway {

	/**
	 * Checkout action instance
	 *
	 * @var Wkwc_Adyen_Checkout_Action
	 */
	public $checkout_action;

	/**
	 * Constructor of this class.
	 *
	 * @param bool $init_hooks
	 * @since 1.0.4
	 * @since 1.1.0 - add support for subscriptions
	 */
	public function __construct( $init_hooks = true ) {

		parent::__construct( $init_hooks );
		$this->checkout_action = new Wkwc_Adyen_Checkout_Action();
		$this->has_fields      = true;
	}


	/**
	 * Gets default payment method title.
	 *
	 * @since 1.0.4
	 * @return string
	 */
	public function get_default_title() {
		return __( 'Adyen - Google Pay', 'wkwc-adyen' );
	}


	/**
	 * Gets default payment method description.
	 *
	 * @since 1.1.0 - display supported countries
	 * @since 1.0.4
	 * @return string
	 */
	public function get_default_description() {
		return $this->show_supported_country();
	}


	/**
	 * Gets default description set in settings.
	 *
	 * @since 1.0.4
	 * @return string
	 */
	public function get_settings_description() {
		$this->description = ( $this->settings['description'] ) ? $this->settings['description'] : __( 'Pay with google pay', 'wkwc-adyen' );
		return $this->description;
	}


	/**
	 * Type of the payment method (e.g ideal, scheme. bcmc).
	 *
	 * @since 1.0.4
	 * @return string
	 */
	public function payment_method_type() {

		$google_method = get_transient( WKWC_ADN_PREFIX . '_google_method' );

		if ( empty( $google_method ) ) {

			$methods = array( 'paywithgoogle', 'googlepay' );

			foreach ( $this->checkout_action->wkwc_adyen_get_payment_methods() as $item ) {

				$method_type = $item['type'];

				if ( in_array( $method_type, $methods ) ) {
					$google_method = $method_type;
					set_transient( WKWC_ADN_PREFIX . '_google_method', $method_type, \HOUR_IN_SECONDS );
				}
			}
		}

		if ( empty( $google_method ) ) {
			$google_method = 'googlepay';
			set_transient( WKWC_ADN_PREFIX . '_google_method', $google_method, \HOUR_IN_SECONDS );
		}

		return $google_method;
	}


	/**
	 * Returns the payment method to be used for recurring payments
	 *
	 * @since 1.1.0 - add recurring method type
	 * @since 1.0.4
	 * @return string
	 */
	public function recurring_payment_method() {
		return $this->payment_method_type();
	}


	/**
	 * Adds extra fields.
	 *
	 * @since 1.0.4
	 * @return void
	 */
	public function payment_fields() {

		parent::payment_fields();

		echo $this->generate_extra_fields_html();
	}


	/**
	 * Generates extra fields HTML.
	 *
	 * @since 1.0.4
	 * @return string
	 */
	public function generate_extra_fields_html() {

		$description = WC()->session->get( $this->id . '_description' );
		$token       = WC()->session->get( $this->id . '_token' );
		$show_desc   = ! empty( $description ) && ! empty( $token ) ? 'display: block;' : '';
		?>
		<div id="<?php echo esc_attr( WKWC_ADN_PREFIX . '-googlepay-container' ); ?>">
			<div id="<?php echo esc_attr( $this->id . '_button' ); ?>"></div>
			<div class="googlepay-description" style="<?php echo esc_attr( $show_desc ); ?>"><?php echo esc_html( $description ); ?></div>
			<input type="hidden" id="<?php echo esc_attr( $this->id . '_token' ); ?>" name="<?php echo esc_attr( $this->id . '_token' ); ?>" value='<?php echo esc_attr( $token ); ?>'>
			<input type="hidden" id="<?php echo esc_attr( $this->id . '_description' ); ?>" name="<?php echo esc_attr( $this->id . '_description' ); ?>" value="<?php echo esc_attr( $description ); ?>">

			<input type="hidden" id="<?php echo esc_attr( $this->id . '_merchant_identifier' ); ?>" value="<?php echo esc_attr( $this->get_option( 'merchant_identifier' ) ); ?>">
			<input type="hidden" id="<?php echo esc_attr( $this->id . '_testmode' ); ?>" value="<?php echo esc_attr( $this->get_option( 'testmode', 'yes' ) ); ?>">
		</div>
		<?php
	}


	/**
	 * Validates extra added fields.
	 *
	 * @since 1.0.4
	 * @return bool
	 */
	public function validate_fields() {

		$is_valid = parent::validate_fields();
		$token    = $_POST[ $this->id . '_token' ];

		if ( empty( $token ) ) {
			$google_token_error = $this->get_option( 'google_token_error' );
			wc_add_notice( $google_token_error, 'error' );
			$is_valid = false;
		}

		return $is_valid;
	}


	/**
	 * Builds the required payment payload
	 *
	 * @since 1.1.0 - use parent function to get common data
	 * @since 1.0.4
	 * @param \WC_Order $order
	 * @param string    $reference
	 * @return array
	 */
	public function build_payment_payload( \WC_Order $order, $reference ) {

		$token_raw        = $_POST[ $this->id . '_token' ];
		$is_strip_slashes = isset( $_POST[ $this->id . '_is_strip_slashes' ] ) ? $_POST[ $this->id . '_is_strip_slashes' ] : true;

		if ( $is_strip_slashes ) {

			$token = stripslashes( $token_raw );

		} else {

			$token = $token_raw;

		}

		$token = json_decode( $token );

		$payload = parent::build_payment_payload( $order, $reference );

		$payment_method = $this->payment_method_type();

		$payload['paymentMethod'][ $payment_method . '.token' ] = $token;

		return $payload;
	}


	/**
	 * Processes the payment.
	 *
	 * @since 1.1.0 - add support for subscriptions
	 * @since 1.0.4
	 * @param int $order_id
	 * @return array
	 */
	public function process_payment( $order_id ) {

		parent::process_payment( $order_id );

		$order     = wc_get_order( $order_id );
		$reference = $order_id;
		$payload   = $this->build_payment_payload( $order, $reference );

		$response = $this->checkout_action->send_payment( $payload );
		wkwc_adn_log( "Adyen Google pay payment response for order id: $order_id: " . print_r( $response, true ) );
		if ( $response->status == 200 ) {

			return $this->process_payment_result( $response, $order );

		} else {

			wc_add_notice( $response->body['message'], 'error' );

			NoticeHandler::convert_notices_to_exceptions( 'woocommerce_rest_payment_error' );

		}

		return array( 'result' => 'failure' );
	}


	/**
	 * Processes the payment result.
	 *
	 * @since 1.3.0
	 * @param object    $response
	 * @param \WC_Order $order
	 * @return array
	 */
	protected function process_payment_result( $response, $order ) {
		$body_response = $this->adyen_helper::wkwc_adyen_obj_to_arr( $response->body );
		$order_id      = $order->get_id();
		wkwc_adn_log( "Adyen Google pay process payment result response for order id: $order_id: " . print_r( $body_response, true ) );
		$result_code = $body_response['resultCode'];
		$reference   = $body_response['pspReference'];
		$action      = isset( $body_response['action'] ) ? $body_response['action'] : '';

		$result = array(
			'result'   => 'success',
			'redirect' => Wkwc_Adyen_Service_Util::get_return_page_url( $order, $result_code ),
		);

		$order->read_meta_data();

		$order_psp_reference = $order->get_meta( '_' . WKWC_ADN_PREFIX . '_payment_pspReference' );

		wkwc_adn_log( "Adyen Google pay _payment_pspReference for order id: $order_id: " . $order_psp_reference );

		if ( $order_psp_reference !== $reference ) {

			$order->update_meta_data( '_' . WKWC_ADN_PREFIX . '_payment_pspReference', $reference );

			if ( $this->adyen_config->wkwc_adyen_is_capture_immediately() ) {
				$order->update_meta_data( '_wkwc_adyen_payment_captured', 'yes' );
			}
		}

		$order->update_meta_data( '_' . WKWC_ADN_PREFIX . '_payment_resultCode', $result_code );
		$order->update_meta_data( '_' . WKWC_ADN_PREFIX . '_payment_action', $action );
		$order->save();

		// clear the token from the cart session
		WC()->session->__unset( $this->id . '_token' );
		WC()->session->__unset( $this->id . '_description' );

		if ( 'RedirectShopper' == $result_code ) {

			// redirect to process payment action via Web Component
			$result = array(
				'result'   => 'success',
				'redirect' => add_query_arg(
					array(
						WKWC_ADN_PREFIX . '_payment_method' => $this->payment_method_type(),
						WKWC_ADN_PREFIX . '_order_id' => $order->get_id(),
					),
					Wkwc_Adyen_Service_Util::get_checkout_url( $order )
				),
			);

		}

		// Payment went through.
		if ( 'Authorised' === $result_code ) {
			$order->update_meta_data( '_woocommerce_' . $this->payment_method_type() . '_payment_data', $body_response );

			if ( $this->adyen_config->wkwc_adyen_is_capture_immediately() ) {
				$order->update_meta_data( '_wkwc_adyen_payment_captured', 'yes' );
				$order->payment_complete();
				/* translators: %s: is Transaction reference */
				$order->set_transaction_id( $reference );
				$order->add_order_note( sprintf( __( 'Payment was complete via Adyen (PSP Reference: %s)', 'wkwc-adyen' ), $this->adyen_helper->wkwc_adyen_get_adyen_transaction_url( $reference ) ) );
				$order->save();
			} else {
				$order->update_status( 'on-hold', __( 'Payment was successful via Adyen', 'wkwc-adyen' ) );
			}
		}

		return $result;
	}



	/**
	 * Adds an array of fields to be displayed on the gateway's settings screen.
	 *
	 * @since 1.0.4
	 * @return void
	 */
	public function init_form_fields() {

		$is_enabled = parent::init_form_fields();

		if ( $is_enabled === false ) {
			return;
		}

		$desc = sprintf( __( '1. Check your Google Pay Developer Profile to retrieve your Google merchant ID. If you don’t have one yet, %1$srequest it here%2$s.', 'wkwc-adyen' ), '<a href="https://developers.google.com/pay/api/web/guides/test-and-deploy/request-prod-access" target="_blank">', '</a>' ) . '</br>';

		$desc .= __( '2. Register your fully qualified domains that will access the Google Pay API.', 'wkwc-adyen' ) . '</br>';

		if ( in_array( $this->payment_method_type(), array( 'paywithgoogle', 'googlepay' ) ) ) {
			$this->form_fields = array_merge(
				$this->form_fields,
				array(
					'testmode'            => array(
						'title'   => __( 'Test mode', 'wkwc-adyen' ),
						'label'   => __( 'Enable/Disable', 'wkwc-adyen' ),
						'default' => 'yes',
						'type'    => 'checkbox',
					),
					'merchant_identifier' => array(
						'title'       => __( 'Merchant Identifier', 'wkwc-adyen' ),
						'type'        => 'text',
						'description' => $desc,
					),
					'google_token_error'  => array(
						'title'       => __( 'Token Error', 'wkwc-adyen' ),
						'type'        => 'text',
						'description' => __( 'Provide a token error message to display as an error for the Google token', 'wkwc-adyen' ),
					),
				)
			);
		}
	}
}
