<?php
/**
 * Twint
 *
 * Payment type     : Twint
 * Countries        : CH
 * Currencies       : CHF
 */

namespace WkwcAdyen\Includes\Payment_Methods;

// prevent direct access data leaks
defined( 'ABSPATH' ) || exit;

use Automattic\WooCommerce\StoreApi\Utilities\NoticeHandler;

use WkwcAdyen\Helper\Common\Wkwc_Adyen_Service_Util;

use WkwcAdyen\Helper\Common\Wkwc_Adyen_Checkout_Action;

class Wkwc_Adyen_Twint extends Wkwc_Adyen_Abstract_Gateway {

	/**
	 * $checkout_action
	 *
	 * @var Wkwc_Adyen_Checkout_Action
	 */
	public $checkout_action;

	/**
	 * Constructor of this class.
	 *
	 * @param bool $init_hooks
	 * @since 1.1.0
	 */
	public function __construct( $init_hooks = true ) {

		parent::__construct( $init_hooks );

		$this->has_fields = false;

		$this->supports = array(
			'products',
			'refunds',
		);

		$this->checkout_action = new Wkwc_Adyen_Checkout_Action();
	}

	/**
	 * List of countries where is available.
	 *
	 * @return array
	 */
	public function available_countries() {

		return array(
			'CH' => array(
				'currencies' => array( 'CHF' ),
				'recurring'  => true,
			),
		);
	}


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


	/**
	 * Gets default payment method description.
	 *
	 * @return string
	 */
	public function get_default_description() {

		$output = sprintf( __( 'Shoppers can pay with Twint when shopping online or in-store using our terminals. %s', 'wkwc-adyen' ), '<br/>' . $this->show_supported_country() );

		return $output;
	}


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

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

	/**
	 * Display the countries which support recurring payments.
	 *
	 * @since 1.2.0
	 * @return array
	 */
	public function show_rec_supported_country() {

		$output    = '';
		$countries = array();

		foreach ( $this->available_countries() as $country_code => $data ) {

			$country_code = '_ANY_' === $country_code ? __( 'ANY', 'wkwc-adyen' ) : $country_code;

			if ( $data['recurring'] === true ) {
				if ( empty( $data['currencies'] ) ) {
					$countries[] = $country_code;
				} else {
					$currencies  = $data['currencies'];
					$countries[] = $country_code . ' (' . implode( ', ', $currencies ) . ')';
				}
			}
		}

		if ( ! empty( $countries ) ) {
			$output = sprintf( __( '%1$sSupported country for recurring payments:%2$s %3$s', 'wkwc-adyen' ), '<b>', '</b>', implode( ', ', $countries ) );
		}

		return $output;
	}

	/**
	 * Type of the payment method (e.g ideal, scheme. bcmc).
	 *
	 * @return string
	 */
	public function payment_method_type() {
		return 'twint';
	}

	/**
	 * Validates extra added fields.
	 *
	 * @since 1.1.0
	 * @return bool
	 */
	public function validate_fields() {
		return parent::validate_fields();
	}

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

		parent::init_form_fields();
	}


	/**
	 * Builds the required payment payload
	 *
	 * @since 1.1.0
	 * @param \WC_Order $order
	 * @param string    $reference
	 * @return array
	 */
	public function build_payment_payload( \WC_Order $order, $reference ) {
		return parent::build_payment_payload( $order, $reference );
	}

	/**
	 * Processes the payment.
	 *
	 * @since 1.1.0
	 * @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 );

		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.2.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 );
		$result_code   = $body_response['resultCode'];
		$reference     = isset( $body_response['pspReference'] ) ? $body_response['pspReference'] : '';
		$action        = $body_response['action'];

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

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

		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 )
				),
			);

		}

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

			if ( $this->adyen_config->wkwc_adyen_is_capture_immediately() ) {
				$order->update_meta_data( '_wkwc_adyen_payment_captured', 'yes' );
				$order->set_transaction_id( $reference );
				$order->payment_complete();
				/* translators: %s: is Transaction 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 ) ) );
			} else {
				$order->update_status( 'on-hold', __( 'Payment was successful via Adyen', 'wkwc-adyen' ) );
			}
		}

		return $result;
	}
}
