<?php
/**
 * Handles the Northmill Checkout payment gateways.
 *
 * @package flo-checkout
 */

namespace Flo_Checkout;

use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
use Flo_Checkout\Gateways\Credorax_CC_Pay;
use Flo_Checkout\Gateways\Helpers\Gateway_Blocks_Support;
use Flo_Checkout\Gateways\Helpers\Gateway_Helpers;
use Flo_Checkout\Gateways\Helpers\Interface_Flo_WC_Payment_Gateway;
use Flo_Checkout\Gateways\Moreflo_Invoice_Pay;
use Flo_Checkout\Gateways\NMI_Pay;
use Flo_Checkout\Gateways\Northmill_BNPL;
use Flo_Checkout\Gateways\Resurs_Invoice_Pay;
use Flo_Checkout\Gateways\Shift4_Apple_Pay;
use Flo_Checkout\Gateways\Swish_Pay;
use WC_Payment_Gateway;
use WP_Error;
use WP_REST_Request;

/**
 * Gateways class.
 */
class Gateways {

	/**
	 * Names of the plugin's gateway classes.
	 *
	 * @var string[]
	 */
	protected static array $gateway_classes = array(
		'swish'           => Swish_Pay::class,
		'resurs'          => Resurs_Invoice_Pay::class,
		'nmi'             => NMI_Pay::class,
		'moreflo_invoice' => Moreflo_Invoice_Pay::class,
		'finaro'          => Credorax_CC_Pay::class,
		'bnpl'            => Northmill_BNPL::class,
		// 'apple_pay'       => Shift4_Apple_Pay::class, // TODO: Enable when ready.
	);

	/**
	 * Setup all plugin gateways.
	 *
	 * @return void
	 */
	public static function setup(): void {
		if ( ! class_exists( 'WC_Payment_Gateway' ) ) {
			return;
		}

		add_action( 'update_option_woocommerce_gateway_settings', 'check_gateway_status_change', 10, 2 );

		// Registers WooCommerce Blocks integration.
		add_action( 'woocommerce_blocks_loaded', array( __CLASS__, 'woocommerce_gateway_block_support' ) );
		add_action( 'rest_api_init', array( __CLASS__, 'register_gateway_fields_rest_route' ) );

		foreach ( self::get_gateway_classes() as $gateway_class ) {
			self::setup_gateway( $gateway_class );
		}
	}

	/**
	 * Get the gateway classes.
	 *
	 * @return string[]
	 */
	public static function get_gateway_classes(): array {
		return apply_filters( 'flo_checkout_gateway_classes', self::$gateway_classes );
	}

	/**
	 * Set up a gateway.
	 *
	 * @param string $gateway_class The gateway class.
	 *
	 * @return void
	 */
	private static function setup_gateway( string $gateway_class ): void {

		if ( ! Gateway_Helpers::is_gateway_implementing_flo_interface( $gateway_class ) ) {
			return;
		}

		/**
		 * Instance of class implementing Interface_Flo_WC_Payment_Gateway.
		 *
		 * @var $gateway_class Interface_Flo_WC_Payment_Gateway
		 */

		if ( method_exists( $gateway_class, 'public_setup' ) ) {
			$gateway_class::public_setup();
		}

		if ( ! is_a( $gateway_class, WC_Payment_Gateway::class, true ) ) {
			return;
		}

		add_filter(
			'woocommerce_payment_gateways',
			function ( $methods ) use ( $gateway_class ) {
				$methods[] = $gateway_class;
				return $methods;
			}
		);
	}

	/**
	 * Check if the payment gateway status has changed and perform an action.
	 *
	 * @param mixed $old_value The old value of the option.
	 * @param mixed $value The new value of the option.
	 */
	public function check_gateway_status_change( mixed $old_value, mixed $value ): void {
		foreach ( $value as $gateway_id => $gateway_settings ) {

			// Get payment method from ID.
			$gateway = self::get_payment_method_by_id( $gateway_id );

			if (
				isset( $gateway_settings['enabled'] ) &&
				$gateway_settings['enabled'] !== $old_value[ $gateway_id ]['enabled']
			) {
				if ( 'yes' === $gateway_settings['enabled'] ) {
					// Gateway has been enabled.
					if ( method_exists( $gateway, 'on_enabled' ) ) {
						$gateway->on_enabled();
					}
				} elseif ( method_exists( $gateway, 'on_disabled' ) ) {
					// Gateway has been disabled.
					$gateway->on_disabled();
				}
			}
		}
	}

	/**
	 * Registers WooCommerce Blocks integration for the plugin's gateways.
	 */
	public static function woocommerce_gateway_block_support(): void {
		if ( ! class_exists( 'Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType' ) ) {
			return;
		}

		foreach ( self::get_gateway_classes() as $gateway_key => $gateway_class ) {

			if ( ! Gateway_Helpers::is_gateway_implementing_flo_interface( $gateway_class ) ) {
				continue;
			}

			/**
			 * Instance of class implementing Interface_Flo_WC_Payment_Gateway.
			 *
			 * @var $gateway_class Interface_Flo_WC_Payment_Gateway
			 */

			if ( ! $gateway_class::has_block_support() ) {
				continue;
			}

			add_action(
				'woocommerce_blocks_payment_method_type_registration',
				function ( PaymentMethodRegistry $payment_method_registry ) use ( $gateway_key, $gateway_class ) {
					$payment_method_registry->register(
						new Gateway_Blocks_Support( $gateway_class::get_id(), $gateway_key )
					);
				}
			);
		}
	}

	/**
	 * Checks if the current request is a REST checkout request.
	 */
	public static function is_rest_checkout(): bool {
		return is_checkout() && defined( 'REST_REQUEST' ) && REST_REQUEST;
	}

	/**
	 * Registers the REST route for fetching payment fields.
	 */
	public static function register_gateway_fields_rest_route(): void {
		register_rest_route(
			REST_API::REST_NAMESPACE . '/v1',
			'/payment-fields/(?P<gateway>[\w-]+)',
			array(
				'methods'             => 'GET',
				'callback'            => array( __CLASS__, 'get_payment_fields' ),
				'permission_callback' => '__return_true',
			)
		);
	}


	/**
	 * Retrieves the payment fields for a gateway.
	 *
	 * @param WP_REST_Request $request The request object.
	 */
	public static function get_payment_fields( WP_REST_Request $request ): WP_Error|array {
		$gateway_id = $request->get_param( 'gateway' );
		$gateways   = WC()->payment_gateways->payment_gateways();
		if ( ! isset( $gateways[ $gateway_id ] ) ) {
			return new WP_Error( 'no_gateway', __( 'Invalid gateway', 'flo-checkout-plugin' ), array( 'status' => 404 ) );
		}
		$gateway = $gateways[ $gateway_id ];

		add_filter( 'woocommerce_is_checkout', array( __CLASS__, 'filter_is_checkout' ), 10, 0 );
		ob_start();
		$gateway->payment_fields();
		$fields = ob_get_clean();
		remove_filter( 'woocommerce_is_checkout', array( __CLASS__, 'filter_is_checkout' ) );

		return array(
			'fields' => $fields,
		);
	}

	/**
	 * Filters the is_checkout function to return true.
	 *
	 * @return bool
	 */
	public static function filter_is_checkout(): true {
		return true;
	}

	/**
	 * Get a payment method by ID. Will only get Northmill Payment Methods.
	 *
	 * @param string $gateway_id The ID of the gateway.
	 *
	 * @return WC_Payment_Gateway|Interface_Flo_WC_Payment_Gateway|null
	 */
	public static function get_payment_method_by_id( string $gateway_id ): WC_Payment_Gateway|Interface_Flo_WC_Payment_Gateway|null {
		$gateways = WC()->payment_gateways->payment_gateways();
		$gateway  = $gateways[ $gateway_id ] ?? null;

		if ( ! $gateway ) {
			return null;
		}

		if ( ! Gateway_Helpers::is_gateway_implementing_flo_interface( $gateway ) ) {
			return null;
		}

		return $gateway;
	}
}
