<?php

use PayrexxPaymentGateway\Helper\SubscriptionHelper;
use PayrexxPaymentGateway\Helper\PaymentHelper;

abstract class WC_Payrexx_Gateway_SubscriptionBase extends WC_Payrexx_Gateway_Base
{
	/**
	 * Subscriptions enabled
	 *
	 * @var string
	 */
	public $subscriptions_enabled = 'yes';

	/**
	 * Subscriptions user description
	 *
	 * @var string
	 */
	public $subscriptions_user_desc = '';

	public function __construct()
	{
		parent::__construct();
	}

	/**
	 * @return void
	 */
	public function init_form_fields()
	{
		parent::init_form_fields();
		$subscription_form_fields = include(PAYREXX_PLUGIN_DIR . '/includes/settings/payrexx_subscription_pm_settings.php');
		$this->form_fields = array_merge($this->form_fields, $subscription_form_fields);
	}

	/**
	 * Init settings
	 *
	 * @return void
	 */
	public function init_settings() {
		parent::init_settings(); // TODO: Change the autogenerated stub!

		$this->subscriptions_enabled   = $this->get_option( 'subscriptions_enabled' );
		$this->subscriptions_user_desc = $this->get_option( 'subscriptions_user_desc' );

		if ( 'yes' === $this->subscriptions_enabled ) {
			$this->supports = array_merge(
				$this->supports,
				SubscriptionHelper::get_supported_features()
			);

			$isSubscription = false;
			if ( SubscriptionHelper::isPaymentMethodChange() ) {
				try {
					$isSubscription = new \WC_Subscription( (int) $_GET['change_payment_method'] );
				} catch (Exception $e) {}
			}

			if ( $isSubscription || SubscriptionHelper::isSubscription( WC()->cart ) ) {
				add_filter( 'woocommerce_gateway_description', array( $this, 'gateway_subscription_checkbox' ), 20, 2 );
			}
		}
	}

	/**
	 * Payment method subscription checkbox.
	 *
	 * @param string $description description text.
	 * @param int    $payment_id  payment method id.
	 * @return string
	 */
	public function gateway_subscription_checkbox( $description, $payment_id ) {
		if ( $payment_id === $this->id ) {
			$name  = 'payrexx-allow-recurring-' . $payment_id;
			$html  = '<label for="' . $name . '">';
			$html .= '<input type="checkbox" checked name="' . $name . '" id="' . $name . '" value="1" />';

			$description .= '</br>' . $html . $this->subscriptions_user_desc . '</label>'; // Append buffered content.
		}
		return $description;
	}

	/**
	 * @return void
	 */
	public function register_hooks() {
		parent::register_hooks();

		if (class_exists('WC_Subscriptions_Order')) {
			add_action(
				'woocommerce_scheduled_subscription_payment_' . $this->id,
				[
					$this,
					'scheduled_subscription_payment'
				],
				10,
				2
			);
		}
	}


	/**
	 * Payment processing
	 *
	 * @param int $order_id order id.
	 * @return array
	 */
	public function process_payment( $order_id ): array {
		$cart  = WC()->cart;
		$order = new \WC_Order( $order_id );

		$isPaymentMethodChange = SubscriptionHelper::isPaymentMethodChange();
		$isSubscription = SubscriptionHelper::isSubscription( $cart );

		// Case 1: Not a subscription or payment method change
		if ( ! $isPaymentMethodChange && ! $isSubscription ) {
			return parent::process_payment( $order_id );
		}

		if ( $isPaymentMethodChange ) {
			$subscription = new \WC_Subscription( $order_id );
			$order        = new \WC_Order( $subscription->get_last_order() );
		}

		// Fix: Restrict gateway creation if order is not exist to the subscription.
		if ( class_exists( \Automattic\WooCommerce\Utilities\OrderUtil::class ) ) {
			if ( ! \Automattic\WooCommerce\Utilities\OrderUtil::is_order( $order->get_id(), [ 'shop_order' ] ) ) {
				return array(
					'result' => 'failure',
				);
			}
		} else {
			$post_type = get_post_type( $order->get_id() );
			if ( $post_type !== 'shop_order' ) {
				return array(
					'result' => 'failure',
				);
			}
		}
		$total_amount                 = floatval( $order->get_total( 'edit' ) );
		$prefix                       = get_option( PAYREXX_CONFIGS_PREFIX . 'prefix' );
		$data['reference']            = $prefix ? $prefix . '_' . $order_id : $order_id;
		$data['success_redirect_url'] = $this->get_return_url( $order );
		$data['cancel_redirect_url']  = PaymentHelper::getCancelUrl( $order );
		$data['language']             = $this->get_gateway_lang();

		$charge_on_auth = false;
		$pre_auth       = true;

		$allow_recurring_key  = 'payrexx-allow-recurring-' . $this->id;
		if ( isset( $_POST['payrexx_allow_recurring_block'] )
			&& $_POST['payrexx_allow_recurring_block'] === 'payrexx-allow-recurring-' . $this->id
		) {
			$_POST[$allow_recurring_key] = 'yes';
		}

		if ( empty( $_POST[$allow_recurring_key] ) ) { // manually renewal.
			// Set all subscriptions connected to this order to manual.
			if ( function_exists( 'wcs_get_subscriptions_for_order' ) ) {
				$subscriptions = wcs_get_subscriptions_for_order(
					$order->get_id(),
					array( 'order_type' => 'parent' )
				);
				foreach ( $subscriptions as $subscription ) {
					$subscription->set_requires_manual_renewal( true );
					$subscription->save();
				}
			}
			// In case of manual subscription and no amount, the order is completed.
			if ( ! $total_amount ) {
				$order->payment_complete();
				WC()->cart->empty_cart();
				return array(
					'result'   => 'success',
					'redirect' => $this->get_return_url( $order ),
				);
			}
			$pre_auth = false;
		} else {
			$charge_on_auth = !!$total_amount; // auto renewal.
		}

		if ( $isPaymentMethodChange ) {
			$charge_on_auth = false;
			$pre_auth = true;
			$data['cancel_redirect_url'] = '';
			$data['success_redirect_url'] = $subscription->get_view_order_url();
		}

		$gateway = $this->payrexxApiService->createPayrexxGateway(
			$order,
			$cart,
			$total_amount,
			$this->pm,
			$data,
			$pre_auth,
			$charge_on_auth,
			$isPaymentMethodChange ? $subscription : null
		);

		if ( ! $gateway ) {
			return array(
				'result' => 'failure',
			);
		}

		if ( $subscription ) {
			$subscription->update_meta_data( 'payrexx_gateway_id', $gateway->getId() );
			$subscription->save();
		}

		return $this->process_redirect( $gateway, $order, $isPaymentMethodChange );
	}

	/**
	 * @param float $amount
	 * @param \WC_Order $renewal
	 */
	public function scheduled_subscription_payment($amount, $renewal)
	{
		$subscriptions = wcs_get_subscriptions_for_order($renewal, array('order_type' => 'any'));

		foreach ($subscriptions as $subscription) {

			// Get tokenization from the subscription (new way)
			$tokenizationId = intval($subscription->get_meta( 'payrexx_auth_transaction_id', true ) );

			if (!$tokenizationId) {
				// Get tokenization id from the last order except this renewal (old way)
				$related_orders = $subscription->get_related_orders('ids');

				foreach ($related_orders as $order_id) {
					if ($order_id === $renewal->get_id()) continue;
					$last_order_id = $order_id;
					break;
				}
				$order = wc_get_order( $last_order_id );
				$tokenizationId = intval( $order->get_meta( 'payrexx_auth_transaction_id' , true ) );

				$subscription->update_meta_data('payrexx_auth_transaction_id', $tokenizationId);
				$subscription->save();
			}

			// Both must be given to do a valid recurring transaction
			if ($this->payrexxApiService->chargeTransaction($tokenizationId, $amount)) {
				continue;
			}

			// Recurring payment failed if we reach this point
			$subscription->payment_failed();
		}
	}
}
