<?php
/**
 * YITH_Pre_Order_WC_Stripe integration with WooCommerce Stripe Plugin
 *
 * @class   YITH_Pre_Order_WC_Stripe
 * @package YITH\PreOrder\Gateways
 * @since   2.0.0
 * @author  YITH <plugins@yithemes.com>
 */

if ( ! defined( 'ABSPATH' ) || ! defined( 'YITH_WCPO_VERSION' ) ) {
	exit; // Exit if accessed directly.
}

//use SkyVerge\WooCommerce\PluginFramework\v5_10_7 as Framework;
//use SkyVerge\WooCommerce\PluginFramework\v5_10_7\SV_WC_Helper;
use SkyVerge\WooCommerce\PluginFramework\v5_10_7\SV_WC_Payment_Gateway;
//use SkyVerge\WooCommerce\PluginFramework\v5_10_7\SV_WC_Payment_Gateway_Direct;
//use SkyVerge\WooCommerce\PluginFramework\v5_10_7\SV_WC_Payment_Gateway_Exception;
//use SkyVerge\WooCommerce\PluginFramework\v5_10_7\SV_WC_Payment_Gateway_Helper;
//use SkyVerge\WooCommerce\PluginFramework\v5_10_7\SV_WC_Plugin_Exception;

/**
 * Integration class for WooCommerce Gateway Stripe.
 *
 * @extends WC_Gateway_Stripe
 */
class YITH_Pre_Order_SV_WC_Payment_Gateway_Integration extends SkyVerge\WooCommerce\PluginFramework\v5_10_7\SV_WC_Payment_Gateway_Integration_Pre_Orders {

	/**
	 * Bootstrap class
	 *
	 * @since 4.1.0
	 *
	 * @param SV_WC_Payment_Gateway|SV_WC_Payment_Gateway_Direct $gateway gateway object.
	 */
	public function __construct( SV_WC_Payment_Gateway $gateway ) {

		parent::__construct( $gateway );

		// add hooks
		$this->add_support();
	}


	/**
	 * Adds support for pre-orders by hooking in some necessary actions
	 *
	 * @since 4.1.0
	 */
	public function add_support() {

		$this->get_gateway()->add_support( array( 'pre-orders' ) );

		// force tokenization when needed
		add_filter( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_tokenization_forced', array( $this, 'maybe_force_tokenization' ) );

		// add pre-orders data to the order object
		add_filter( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_get_order', array( $this, 'get_order' ) );

		// process pre-order initial payment as needed
		add_filter( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_process_payment', array( $this, 'process_payment' ), 10, 2 );

		// complete a successful pre-order initial payment
		add_filter( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_complete_payment', array( $this, 'complete_payment' ), 10, 2 );

		// process batch pre-order payments
		add_action( 'ywpo_process_pre_order_release_payment_' . $this->get_gateway()->get_id(), array( $this, 'process_release_payment' ) );
	}


	/**
	 * Forces tokenization for pre-orders.
	 *
	 * @see SV_WC_Payment_Gateway::tokenization_forced()
	 *
	 * @since 4.1.0
	 *
	 * @param bool $force_tokenization whether tokenization should be forced
	 * @return bool
	 */
	public function maybe_force_tokenization( $force_tokenization ) {

		$pay_page_pre_order = false;

		// pay page with pre-order?
		if ( $this->get_gateway()->is_pay_page_gateway() ) {

			$order_id = $this->get_gateway()->get_checkout_pay_page_order_id();

			if ( $order_id && ywpo_order_has_pre_order( $order_id ) && ywpo_is_upon_release_cart() ) {

				// always tokenize the card for pre-orders that are charged upon release.
				$force_tokenization = true;
			}
		}

		return $force_tokenization;
	}


	/**
	 * Adds pre-orders data to the order object.
	 *
	 * Filtered onto SV_WC_Payment_Gateway::get_order()
	 *
	 * @see SV_WC_Payment_Gateway::get_order()
	 *
	 * @since 4.1.0
	 *
	 * @param \WC_Order $order the order
	 * @return \WC_Order
	 */
	public function get_order( $order ) {

		// bail if order doesn't contain a pre-order
		if ( ! ywpo_order_has_pre_order( $order ) ) {
			return $order;
		}

		if ( ywpo_order_will_need_payment_token( $order ) ) {

			// normally a guest user wouldn't be assigned a customer id, but for a pre-order requiring tokenization, it might be.
			if ( 0 == $order->get_user_id() && false !== ( $customer_id = $this->get_gateway()->get_guest_customer_id( $order ) ) ) {
				$order->customer_id = $customer_id;
			}

			// zero out the payment total since we're just tokenizing the payment method
			$order->payment_total = '0.00';

		} elseif ( ywpo_order_has_payment_token( $order ) && ! is_checkout_pay_page() ) {

			// if this is a pre-order release payment with a tokenized payment method, get the payment token to complete the order

			// retrieve the payment token
			$order->payment->token = $this->get_gateway()->get_order_meta( $order, 'payment_token' );

			// retrieve the optional customer id
			$order->customer_id = $this->get_gateway()->get_order_meta( $order, 'customer_id' );

			// set token data on order
			if ( $this->get_gateway()->get_payment_tokens_handler()->user_has_token( $order->get_user_id(), $order->payment->token ) ) {

				// an existing registered user with a saved payment token
				$token = $this->get_gateway()->get_payment_tokens_handler()->get_token( $order->get_user_id(), $order->payment->token );

				// account last four
				$order->payment->account_number = $token->get_last_four();
				if ( $this->get_gateway()->is_credit_card_gateway() ) {
					$order->payment->card_type = $token->get_card_type();
					$order->payment->exp_month = $token->get_exp_month();
					$order->payment->exp_year  = SV_WC_Payment_Gateway_Helper::format_exp_year( $token->get_exp_year() );
				} elseif ( $this->get_gateway()->is_echeck_gateway() ) {
					// account type (checking/savings)
					$order->payment->account_type = $token->get_account_type();
				}
			} else {
				// a guest user means that token data must be set from the original order

				// account number
				$order->payment->account_number = $this->get_gateway()->get_order_meta( $order, 'account_four' );

				if ( $this->get_gateway()->is_credit_card_gateway() ) {
					// card type
					$order->payment->card_type = $this->get_gateway()->get_order_meta( $order, 'card_type' );

					// expiry date
					if ( $expiry_date = $this->get_gateway()->get_order_meta( $order, 'card_expiry_date' ) ) {

						list( $exp_year, $exp_month ) = explode( '-', $expiry_date );

						$order->payment->exp_month = $exp_month;
						$order->payment->exp_year  = SV_WC_Payment_Gateway_Helper::format_exp_year( $exp_year );
					}
				} elseif ( $this->get_gateway()->is_echeck_gateway() ) {
					// account type
					$order->payment->account_type = $this->get_gateway()->get_order_meta( $order, 'account_type' );
				}
			}
		}

		return $order;
	}


	/**
	 * Handle the pre-order initial payment/tokenization, or defer back to the normal payment
	 * processing flow
	 *
	 * @since 4.1.0
	 * @see SV_WC_Payment_Gateway::process_payment()
	 * @param boolean $result the result of this pre-order payment process.
	 * @param int     $order_id the order identifier.
	 * @return true|array true to process this payment as a regular transaction, otherwise
	 *         return an array containing keys 'result' and 'redirect'
	 */
	public function process_payment( $result, $order_id ) {
		if ( ywpo_order_has_pre_order( $order_id ) && ywpo_order_will_need_payment_token( $order_id ) ) {
			$order = $this->get_gateway()->get_order( $order_id );
			try {
				// using an existing tokenized payment method.
				if ( isset( $order->payment->token ) && $order->payment->token ) {
					// save the tokenized card info for completing the pre-order in the future.
					$this->get_gateway()->add_transaction_data( $order );
				} else {
					// otherwise, tokenize the payment method.
					$order = $this->get_gateway()->get_payment_tokens_handler()->create_token( $order );
				}

				YITH_Pre_Order_Orders_Manager::set_as_pre_order_pending_payment( $order );

				// empty cart.
				WC()->cart->empty_cart();

				// redirect to thank you page.
				$result = array(
					'result'   => 'success',
					'redirect' => $this->get_gateway()->get_return_url( $order ),
				);

			} catch ( SV_WC_Plugin_Exception $e ) {
				// translators: %s: payment method title.
				$this->get_gateway()->mark_order_as_failed( $order, sprintf( __( 'Pre-order tokenization attempt failed (%s)', 'woocommerce-plugin-framework' ), $this->get_gateway()->get_method_title(), $e->getMessage() ) );

				$result = array(
					'result'  => 'failure',
					'message' => $e->getMessage(),
				);
			}
		}

		return $result;
	}


	/**
	 * Completes a pre-order payment by marking the order as Pre-Ordered.
	 *
	 * @internal
	 *
	 * @since 5.0.0
	 *
	 * @param WC_Order $order order object.
	 */
	public function complete_payment( $order ) {

		if ( ywpo_order_has_pre_order( $order ) && ywpo_order_will_need_payment_token( $order ) ) {
			YITH_Pre_Order_Orders_Manager::set_as_pre_order_pending_payment( $order );
		}
	}


	/**
	 * Processes a pre-order payment when the pre-order is released.
	 *
	 * @since 4.1.0
	 *
	 * @param WC_Order $order original order containing the pre-order.
	 * @throws SV_WC_Payment_Gateway_Exception
	 */
//	public function process_release_payment( $order ) {
//		try {
//			// set order defaults.
//			$order = $this->get_gateway()->get_order( $order );
//
//			// translators: %1$s: site name, %2$s: order number.
//			$order->description = sprintf( __( '%1$s - Pre-Order Release Payment for Order %2$s', 'woocommerce-plugin-framework' ), esc_html( SV_WC_Helper::get_site_name() ), $order->get_order_number() );
//
//			// token is required.
//			if ( ! $order->payment->token ) {
//				throw new SV_WC_Payment_Gateway_Exception( __( 'Payment token missing/invalid.', 'woocommerce-plugin-framework' ) );
//			}
//
//			// perform the transaction.
//			if ( $this->get_gateway()->is_credit_card_gateway() ) {
//
//				if ( $this->get_gateway()->perform_credit_card_charge( $order ) ) {
//					$response = $this->get_gateway()->get_api()->credit_card_charge( $order );
//				} else {
//					$response = $this->get_gateway()->get_api()->credit_card_authorization( $order );
//				}
//			} elseif ( $this->get_gateway()->is_echeck_gateway() ) {
//				$response = $this->get_gateway()->get_api()->check_debit( $order );
//			}
//
//			// success! update order record.
//			if ( $response->transaction_approved() ) {
//
//				$last_four = substr( $order->payment->account_number, -4 );
//
//				// order note based on gateway type.
//				if ( $this->get_gateway()->is_credit_card_gateway() ) {
//					$message = sprintf(
//						// translators: %1$s: payment method title, %2$s: Authorization or Charge, %3$s: payment type, %4$s: last four card digits, %5$s: card expiration date.
//						__( '%1$s %2$s Pre-Order Release Payment Approved: %3$s ending in %4$s (expires %5$s)', 'woocommerce-plugin-framework' ),
//						$this->get_gateway()->get_method_title(),
//						$this->get_gateway()->perform_credit_card_authorization( $order ) ? 'Authorization' : 'Charge',
//						SV_WC_Payment_Gateway_Helper::payment_type_to_name( ( ! empty( $order->payment->card_type ) ? $order->payment->card_type : 'card' ) ),
//						$last_four,
//						( ! empty( $order->payment->exp_month ) && ! empty( $order->payment->exp_year ) ? $order->payment->exp_month . '/' . substr( $order->payment->exp_year, -2 ) : 'n/a' )
//					);
//
//				} elseif ( $this->get_gateway()->is_echeck_gateway() ) {
//					// account type (checking/savings) may or may not be available, which is fine.
//					// translators .
//					$message = sprintf( __( '%s eCheck Pre-Order Release Payment Approved: %s ending in %s', 'woocommerce-plugin-framework' ), $this->get_gateway()->get_method_title(), SV_WC_Payment_Gateway_Helper::payment_type_to_name( ( ! empty( $order->payment->account_type ) ? $order->payment->account_type : 'bank' ) ), $last_four );
//
//				}
//
//				// adds the transaction id (if any) to the order note
//				if ( $response->get_transaction_id() ) {
//					$message .= ' ' . sprintf( __( '(Transaction ID %s)', 'woocommerce-plugin-framework' ), $response->get_transaction_id() );
//				}
//
//				$order->add_order_note( $message );
//			}
//
//			if ( $response->transaction_approved() || $response->transaction_held() ) {
//
//				// add the standard transaction data
//				$this->get_gateway()->add_transaction_data( $order, $response );
//
//				// allow the concrete class to add any gateway-specific transaction data to the order
//				$this->get_gateway()->add_payment_gateway_transaction_data( $order, $response );
//
//				// if the transaction was held (ie fraud validation failure) mark it as such
//				if ( $response->transaction_held() || ( $this->get_gateway()->supports( SV_WC_Payment_Gateway::FEATURE_CREDIT_CARD_AUTHORIZATION ) && $this->get_gateway()->perform_credit_card_authorization( $order ) ) ) {
//
//					$this->get_gateway()->mark_order_as_held( $order, $this->get_gateway()->supports( SV_WC_Payment_Gateway::FEATURE_CREDIT_CARD_AUTHORIZATION ) && $this->get_gateway()->perform_credit_card_authorization( $order ) ? __( 'Authorization only transaction', 'woocommerce-plugin-framework' ) : $response->get_status_message(), $response );
//
//					// reduce stock for held orders, but don't complete payment (pass order ID so WooCommerce fetches fresh order object with reduced_stock meta set on order status change)
//					wc_reduce_stock_levels( $order->get_id() );
//
//				} else {
//
//					// otherwise complete the order
//					$order->payment_complete();
//				}
//
//			} else {
//
//				// failure
//				throw new SV_WC_Payment_Gateway_Exception( sprintf( '%s: %s', $response->get_status_code(), $response->get_status_message() ) );
//
//			}
//
//		} catch ( SV_WC_Plugin_Exception $e ) {
//
//			// Mark order as failed
//			$this->get_gateway()->mark_order_as_failed( $order, sprintf( __( 'Pre-Order Release Payment Failed: %s', 'woocommerce-plugin-framework' ), $e->getMessage() ) );
//
//		}
//	}
}
