<?php
/**
 * PeachPay Extension Trait.
 *
 * @package PeachPay
 */

defined( 'ABSPATH' ) || exit;

require_once PEACHPAY_ABSPATH . 'core/traits/trait-peachpay-extension.php';

trait PeachPay_Payment_Integration {
	use PeachPay_Extension {
		internal_hooks as private parent_internal_hooks;
	}

	/**
	 * Gateway class list.
	 *
	 * @var array $payment_gateways
	 */
	private $payment_gateways = array();

	/**
	 * .
	 *
	 * @param boolean $enabled If the extension is enabled.
	 */
	private function internal_hooks( $enabled ) {
		$this->parent_internal_hooks( $enabled );

		$extension = $this;
		add_filter(
			'woocommerce_payment_gateways',
			function ( $gateways ) use ( $extension ) {
				return array_merge( $gateways, $extension->payment_gateways );
			}
		);

		add_action(
			'woocommerce_blocks_loaded',
			function () use ( $extension ) {
				if ( class_exists( 'Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType' ) ) {
					$extension->woocommerce_blocks_loaded();
				}
			}
		);

		// Fallback: Inject gateways if the filter ran before our gateways were populated.
		// This handles cases where themes/plugins access WC()->payment_gateways too early.
		add_action(
			'woocommerce_init',
			function () use ( $extension ) {
				$extension->maybe_inject_gateways();
			},
			99
		);
	}

	/**
	 * Injects gateways directly into WooCommerce if they weren't registered via the filter.
	 * This is a fallback for when themes/plugins access WC()->payment_gateways before woocommerce_init.
	 */
	public function maybe_inject_gateways() {
		// Nothing to inject.
		if ( empty( $this->payment_gateways ) ) {
			return;
		}

		// Ensure WooCommerce is available.
		if ( ! function_exists( 'WC' ) || ! WC()->payment_gateways ) {
			return;
		}

		$wc_gateways = WC()->payment_gateways;

		// Build list of already registered gateway IDs.
		$existing_ids = array();
		if ( ! empty( $wc_gateways->payment_gateways ) && is_array( $wc_gateways->payment_gateways ) ) {
			foreach ( $wc_gateways->payment_gateways as $gateway ) {
				if ( is_object( $gateway ) && isset( $gateway->id ) ) {
					$existing_ids[] = $gateway->id;
				}
			}
		}

		// Inject any gateways that are missing from WooCommerce's registry.
		foreach ( $this->payment_gateways as $gateway_class ) {
			$gateway = null;

			if ( is_string( $gateway_class ) && class_exists( $gateway_class ) ) {
				$gateway = new $gateway_class();
			} elseif ( is_object( $gateway_class ) ) {
				$gateway = $gateway_class;
			}

			if ( $gateway && isset( $gateway->id ) && ! in_array( $gateway->id, $existing_ids, true ) ) {
				$wc_gateways->payment_gateways[] = $gateway;
				$existing_ids[]                  = $gateway->id;
			}
		}
	}

	/**
	 * Determines if a gateway belongs to this integration.
	 *
	 * @param string $gateway_id The gateway to test for.
	 */
	abstract public static function is_payment_gateway( $gateway_id );

	/**
	 * Gets a array of this integrations payment gateway instances. If WC has not loaded the classes
	 * yet this function will return an empty array.
	 */
	public static function get_payment_gateways() {
		$gateways = array();

		foreach ( WC()->payment_gateways->payment_gateways() as $gateway ) {
			if ( self::is_payment_gateway( $gateway->id ) ) {
				$gateways[] = $gateway;
			}
		}

		usort(
			$gateways,
			function ( $a, $b ) {
				return $a->settings_priority - $b->settings_priority;
			}
		);

		return $gateways;
	}

	/**
	 * Takes all payment gateways for the provider and will check if at least one is true.
	 *
	 * @return bool provider_enabled
	 */
	public static function has_gateway_enabled() {
		// Note: I've decided to copy this snippet from the above function
		// instead of using the function as there is no reason for a sort to run here,
		// so this will avoid that and do a single loop.
		foreach ( WC()->payment_gateways->payment_gateways() as $gateway ) {
			if ( self::is_payment_gateway( $gateway->id ) && $gateway->get_option( 'enabled' ) === 'yes' ) {
				return true;
			}
		}

		// If no active payment gateway found, return false.
		return false;
	}

	/**
	 * This method is called when the "woocommerce_blocks_loaded" action is trigged.
	 */
	protected static function woocommerce_blocks_loaded() {
	}
}
