<?php // phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase, WordPress.Files.FileName.InvalidClassFileName
/**
 * Payment Integrations Module Plugin
 *
 * @package Autoship Cloud
 * @since 2.11.0
 */

namespace Autoship\Modules\Payments;

use Autoship\Core\ModuleInterface;
use Autoship\Core\Plugin;
use Autoship\Core\ServiceContainer;
use Autoship\Modules\Payments\Services\OrderPaymentDataService;
use Autoship\Modules\Payments\Services\PaymentGatewayService;
use Autoship\Modules\Payments\Services\PaymentGatewayRegistry;
use Autoship\Modules\Payments\Services\PaymentMethodDataBuilder;
use Autoship\Modules\Payments\Services\PaymentMethodService;
use Autoship\Modules\Payments\Services\PaymentMethodTypeRegistry;
use Autoship\Modules\Payments\Services\WooPaymentsApiClient;
use Autoship\Modules\Payments\Services\WooPaymentsChargeService;
use Exception;

/**
 * Payment Gateway Module for managing all payment gateway integrations.
 *
 * @package Autoship\Modules\PaymentGateways
 * @since 2.11.0
 */
class PaymentsModule implements ModuleInterface {

	/**
	 * Register the module's services with the service container.
	 *
	 * @param ServiceContainer $container The service container.
	 * @return void
	 */
	public function register( ServiceContainer $container ): void {
		// Register the payment method type registry.
		$container->register(
			PaymentMethodTypeRegistry::class,
			function () {
				return new PaymentMethodTypeRegistry();
			}
		);

		// Register the payment gateway registry.
		$container->register(
			PaymentGatewayRegistry::class,
			function () {
				$container = Plugin::get_service_container();

				return new PaymentGatewayRegistry( $container->get( PaymentMethodTypeRegistry::class ) );
			}
		);

		// Register the payment gateway service.
		$container->register(
			PaymentGatewayService::class,
			function () {
				$container = Plugin::get_service_container();

				return new PaymentGatewayService( $container->get( PaymentGatewayRegistry::class ) );
			}
		);

		// Register the payment method data builder.
		$container->register(
			PaymentMethodDataBuilder::class,
			function () {
				$container = Plugin::get_service_container();

				return new PaymentMethodDataBuilder( $container->get( PaymentMethodTypeRegistry::class ) );
			}
		);

		// Register the payment method service.
		$container->register(
			PaymentMethodService::class,
			function () {
				$container = Plugin::get_service_container();

				return new PaymentMethodService(
					$container->get( PaymentMethodDataBuilder::class ),
					$container->get( PaymentMethodTypeRegistry::class )
				);
			}
		);

		// Register the order payment data service.
		$container->register(
			OrderPaymentDataService::class,
			function () {
				$container = Plugin::get_service_container();

				return new OrderPaymentDataService(
					$container->get( PaymentGatewayRegistry::class ),
					$container->get( PaymentMethodTypeRegistry::class )
				);
			}
		);

		// Register the WooPayments API client wrapper.
		$container->register(
			WooPaymentsApiClient::class,
			function () {
				return new WooPaymentsApiClient();
			}
		);

		// Register the WooPayments charge service (REST callback handler).
		$container->register(
			WooPaymentsChargeService::class,
			function () {
				$container = Plugin::get_service_container();

				return new WooPaymentsChargeService( $container->get( WooPaymentsApiClient::class ) );
			}
		);
	}

	/**
	 * Boots the module.
	 *
	 * @param ServiceContainer $container The service container.
	 * @return void
	 * @throws Exception Thrown when the services are not found.
	 */
	public function boot( ServiceContainer $container ): void {
		// Register type registry filters for optional gateway support.
		PaymentMethodTypeRegistry::register_filters();

		// Register WordPress hooks.
		$this->register_wordpress_hooks( $container );

		// Defer to wp_loaded (after WC_Cart_Session loads the cart at priority 20)
		// so PaymentGatewayRegistry::initialize() — which calls
		// get_available_payment_gateways() and triggers the
		// woocommerce_available_payment_gateways filter chain — does not cause
		// third-party callbacks to load the cart prematurely. Loading the cart
		// before wp_loaded fires woocommerce_get_cart_item_from_session and
		// woocommerce_cart_loaded_from_session before other plugins (e.g.
		// Booking Activities) have registered their session handlers, which
		// orphans booking metadata and later breaks checkout.
		add_action(
			'wp_loaded',
			function () use ( $container ) {
				// Initialize the registry first.
				$registry = $container->get( PaymentGatewayRegistry::class );
				$registry->initialize();

				// Register all payment hooks.
				$type_registry  = $container->get( PaymentMethodTypeRegistry::class );
				$hooks_provider = new PaymentHooksProvider( $registry, $type_registry );
				$hooks_provider->register();
			},
			30
		);
	}

	/**
	 * Register WordPress hooks and filters.
	 *
	 * @param ServiceContainer $container The service container.
	 *
	 * @return void
	 * @throws Exception Thrown when the services are not found.
	 */
	private function register_wordpress_hooks( ServiceContainer $container ): void {
		$service = $container->get( PaymentGatewayService::class );

		// Hook into WooCommerce payment token creation.
		add_action( 'woocommerce_new_payment_token', array( $service, 'handle_new_payment_token' ) );

		// Hook into payment method updates.
		add_action( 'autoship_update_payment_method_on_all_scheduled_orders', array( $service, 'update_payment_method_on_orders' ) );

		// Register payment gateway filters.
		add_filter( 'autoship_get_valid_payment_methods', array( $service, 'get_valid_payment_methods' ) );
	}

	/**
	 * Deactivate the module.
	 *
	 * @param ServiceContainer $container The service container.
	 * @return void
	 */
	public function deactivate( ServiceContainer $container ): void {
	}

	/**
	 * Uninstall the module.
	 *
	 * @param ServiceContainer $container The service container.
	 * @return void
	 */
	public function uninstall( ServiceContainer $container ): void {
	}
}
