<?php

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

use PaychefPaymentGateway\Helper\SubscriptionHelper;
use PaychefPaymentGateway\Helper\PaymentHelper;

abstract class PayChef_Gateway_SubscriptionBase extends PayChef_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(PAYCHEF_PLUGIN_DIR . '/includes/settings/paychef_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()
			);

            if (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 = 'paychef-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 ) {
        // Verify nonce for checkout form submission (only for classic checkout)
        // Skip nonce check for: admin context, REST API (block checkout), and payment method changes
        if ( ! is_admin() &&
             ! defined( 'REST_REQUEST' ) &&
             ! SubscriptionHelper::isPaymentMethodChange() &&
             isset( $_POST['woocommerce-process-checkout-nonce'] ) ) {
            if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['woocommerce-process-checkout-nonce'] ) ), 'woocommerce-process_checkout' ) ) {
                wc_add_notice( __( 'Security verification failed. Please try again.', 'paychef-payments-for-woocommerce' ), 'error' );
                return array(
                    'result' => 'failure',
                );
            }
        }

        $cart = WC()->cart;
        $order = new \WC_Order($order_id);

        if (!SubscriptionHelper::isSubscription($cart)) {
            return parent::process_payment($order_id);
        }
        if (SubscriptionHelper::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_id, [ 'shop_order' ] ) ) {
				return array(
					'result' => 'failure',
				);
			}
		} else {
			$post_type = get_post_type( $order_id );
			if ( $post_type !== 'shop_order' ) {
				return array(
					'result' => 'failure',
				);
			}
		}
        $total_amount = floatval($order->get_total('edit'));
        $reference = (get_option(PAYCHEF_CONFIGS_PREFIX . 'prefix') ? get_option(PAYCHEF_CONFIGS_PREFIX . 'prefix') . '_' : '') . $order_id;

        $success_redirect_url = $this->get_return_url($order);
        $cancel_redirect_url = PaymentHelper::getCancelUrl($order);

        $charge_on_auth = false;
        $pre_auth = true;

		if ( isset( $_POST['paychef_allow_recurring_block'] )
		     && sanitize_text_field( wp_unslash( $_POST['paychef_allow_recurring_block'] ) ) === 'paychef-allow-recurring-' . $this->id
		) {
			$_POST['paychef-allow-recurring-' . $this->id] = 'yes';
		}

        if (SubscriptionHelper::isPaymentMethodChange()) {
            $cancel_redirect_url = wp_nonce_url(
                add_query_arg(array('change_payment_method' => $subscription->get_id()), $subscription->get_checkout_payment_url())
            );
        } elseif (empty(sanitize_text_field( wp_unslash( $_POST['paychef-allow-recurring-' . $this->id] ?? '' ) ))) { // 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.
        }

        $gateway = $this->paychefApiService->createPaychefGateway(
            $order,
            $cart,
            $total_amount,
            $this->pm,
            $reference,
            $success_redirect_url,
            $cancel_redirect_url,
            $pre_auth,
            $charge_on_auth
        );

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

    /**
     * @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('paychef_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('paychef_auth_transaction_id', true));

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

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

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