<?php

namespace WeeConnectPay\Integrations;

use WeeConnectPay\Environment;
use WeeConnectPay\WordPress\Plugin\includes\WeeConnectPayUtilities;

class PaymentFields {


	/**
	 * Registers the needed scripts for the payment fields. The web-component
	 * bundle self-registers `<wcp-payment-fields>` and bundles React+ReactDOM.
	 * The host adapter wires WC Classic's jQuery `checkout_place_order` and
	 * `ajaxSuccess` events to the element's `tokenize()` / `runThreeDs()`
	 * imperative methods.
	 *
	 * @since 2.0.0
	 * @updated 4.3.0
	 */
	public function registerScripts(): PaymentFields {
		$cloverSdkUrl = Environment::getCloverSdkUrl();
		wp_register_script( 'weeconnectpay-clover-sdk', $cloverSdkUrl, [], null, false );
		wp_register_script( 'weeconnectpay-payment-fields-sdk', WEECONNECTPAY_PLUGIN_URL . 'packages/payment-fields/dist/web-component/index.js', array( 'weeconnectpay-clover-sdk' ), WEECONNECT_VERSION, false );
		wp_register_script( 'weeconnectpay-payment-fields-wc-classic', WEECONNECTPAY_PLUGIN_URL . 'dist/js/wc-classic.js', array( 'weeconnectpay-payment-fields-sdk', 'jquery' ), WEECONNECT_VERSION, false );

		if ( GoogleRecaptcha::isEnabledAndReady() ) {
			wp_register_script( 'weeconnectpay-google-recaptcha', GoogleRecaptcha::getSdkSrc() );
		}
		return $this;
	}

	/**
	 * Makes WordPress localized data available for the scripts needed in for the payment fields
	 * @since 2.0.0
	 */
	public function localizeData( array $script_data ): PaymentFields {
		wp_localize_script( 'weeconnectpay-payment-fields-wc-classic', 'WeeConnectPayPaymentFieldsData', $script_data );
		return $this;
	}

	/**
	 * Registers the CSS used by the payment fields
	 * @since 2.0.0
	 */
	public function registerStyles(): PaymentFields {
		wp_register_style( 'weeconnectpay-payment-fields-css', WEECONNECTPAY_PLUGIN_URL . 'site/css/weeconnect-public.css', array(), WEECONNECT_VERSION );
		return $this;
	}

	/**
	 * Enqueues the SDK web-component bundle + WC Classic adapter. Both bundles
	 * are ESM, so the `script_loader_tag` filter rewrites their tags to
	 * `type="module"` for the browser parser.
	 *
	 * @since 2.0.0
	 * @updated 4.3.0
	 */
	public function enqueueVueScriptsAndStyles(): PaymentFields {
		wp_enqueue_script( 'weeconnectpay-clover-sdk' );
		wp_enqueue_script( 'weeconnectpay-payment-fields-sdk', '', array( 'weeconnectpay-clover-sdk' ), WEECONNECT_VERSION );
		wp_enqueue_script( 'weeconnectpay-payment-fields-wc-classic', '', array( 'weeconnectpay-payment-fields-sdk', 'jquery' ), WEECONNECT_VERSION );
		self::registerModuleScriptFilter();

		if ( GoogleRecaptcha::isEnabledAndReady() ) {
			wp_enqueue_script( 'weeconnectpay-google-recaptcha' );
		}
		wp_enqueue_style( 'weeconnectpay-payment-fields-css', '', array( 'weeconnectpay-clover-sdk' ), WEECONNECT_VERSION );
		return $this;
	}

	/**
	 * Check if Google Pay is enabled and ready
	 * @since 3.15.5
	 * @return bool
	 */
	public static function isGooglePayEnabled(): bool {
		try {
			$integrationSettings = new IntegrationSettings();
			return $integrationSettings->getGooglePayOrDefault() === '1';
		} catch ( \Exception $e ) {
			return false;
		}
	}

	/**
	 * Check if the 3-D Secure beta opt-in is currently on for this merchant.
	 * When true, the SDK loads Clover's 3DS sdk URL and surfaces the cardholder
	 * iframe fields so Visa's required cardholder data flows into the token.
	 */
	public static function isThreeDSecureBetaEnabled(): bool {
		try {
			$integrationSettings = new IntegrationSettings();
			return $integrationSettings->getThreeDSecureBetaOrDefault() === '1';
		} catch ( \Exception $e ) {
			return false;
		}
	}

	/**
	 * Script handles emitted as ES modules. The SDK web-component bundle and
	 * the host adapters are built as native ESM, so the browser needs
	 * `<script type="module">` to parse the `import` syntax at runtime.
	 *
	 * @since 4.3.0
	 */
	private const MODULE_SCRIPT_HANDLES = array(
		'weeconnectpay-payment-fields-sdk',
		'weeconnectpay-payment-fields-wc-classic',
		'weeconnectpay-blocks-payment-fields-js',
	);

	/**
	 * Registers the WP `script_loader_tag` filter that rewrites the ESM-handle
	 * tags to `type="module"`. Idempotent (`has_filter` guard) so Classic and
	 * Blocks can both call it in the same request.
	 *
	 * @since 4.3.0
	 */
	public static function registerModuleScriptFilter(): void {
		if ( has_filter( 'script_loader_tag', array( self::class, 'rewriteAsModuleTag' ) ) ) {
			return;
		}
		add_filter( 'script_loader_tag', array( self::class, 'rewriteAsModuleTag' ), 10, 3 );
	}

	/**
	 * Rewrites a `<script src>` to `<script type="module" src>` for handles
	 * registered as ESM. Returns the original tag for all other handles.
	 *
	 * @param string $tag    The default-built tag.
	 * @param string $handle The script handle WP is rendering.
	 * @param string $src    The resolved src URL.
	 * @return string
	 * @since 4.3.0
	 */
	public static function rewriteAsModuleTag( string $tag, string $handle, string $src ): string {
		if ( ! in_array( $handle, self::MODULE_SCRIPT_HANDLES, true ) ) {
			return $tag;
		}
		return sprintf(
			'<script type="module" src="%s" id="%s-js"></script>' . "\n",
			esc_url( $src ),
			esc_attr( $handle )
		);
	}

	/**
	 * Output the `<wcp-payment-fields>` web component plus the hidden inputs
	 * the PHP gateway's process_payment() reads from `$_POST`. The element
	 * bootstraps itself from its attributes plus the
	 * `WeeConnectPayPaymentFieldsData` global localized on the adapter handle.
	 *
	 * The trust footer (lock icon + secured-by logos) renders inside the web
	 * component via the SDK's own `<TrustFooter>` sub-component, so there is
	 * no duplicate PHP-side footer block.
	 *
	 * @since 2.0.0
	 * @updated 4.3.0
	 */
	public function outputElements(): PaymentFields {
		try {
			$integrationSettings = new IntegrationSettings();
			$pakmsKey            = $integrationSettings->getPublicAccessKey();
			$threeDSecureEnabled = $integrationSettings->getThreeDSecureBetaOrDefault() === '1';
			$merchantId          = '';
			try {
				$merchant = $integrationSettings->getCloverMerchant();
				if ( $merchant && method_exists( $merchant, 'getUuid' ) ) {
					$merchantId = (string) $merchant->getUuid();
				}
			} catch ( \Exception $e ) {
				$merchantId = '';
			}
		} catch ( \Exception $e ) {
			// Settings unavailable — render nothing. The gateway-level error UI will surface.
			return $this;
		}

		$features  = wp_json_encode( array(
			'googlePay'    => self::isGooglePayEnabled(),
			'threeDSecure' => $threeDSecureEnabled,
		) );
		$endpoints = wp_json_encode( array(
			'threeDsFinalize' => rest_url( 'weeconnectpay/v1/woocommerce/3ds/finalize' ),
		) );

		global $woocommerce;
		$cartTotalCents = isset( $woocommerce->cart ) ? (int) round( $woocommerce->cart->total * 100 ) : 0;

		?>
		<wcp-payment-fields
			id="weeconnectpay-wc-fields"
			pakms-key="<?php echo esc_attr( $pakmsKey ); ?>"
			merchant-id="<?php echo esc_attr( $merchantId ); ?>"
			locale="<?php echo esc_attr( WeeConnectPayUtilities::getLocale() ); ?>"
			cart-total="<?php echo esc_attr( (string) $cartTotalCents ); ?>"
			currency="<?php echo esc_attr( get_woocommerce_currency() ); ?>"
			clover-sdk-url="<?php echo esc_url( Environment::getCloverSdkUrl() ); ?>"
			<?php if ( $threeDSecureEnabled ) : ?>
			clover-3ds-sdk-url="<?php echo esc_url( Environment::getClover3DSSdkUrl() ); ?>"
			<?php endif; ?>
			features='<?php echo esc_attr( $features ); ?>'
			endpoints='<?php echo esc_attr( $endpoints ); ?>'
			lock-icon-src="<?php echo esc_url( WEECONNECTPAY_PLUGIN_URL . 'site/img/lock.svg' ); ?>"
			trust-logos-src="<?php echo esc_url( WEECONNECTPAY_PLUGIN_URL . 'site/img/secured-by-logos.png' ); ?>"
			trust-text="<?php echo esc_attr__( 'Payment secured by', 'weeconnectpay' ); ?>"
		></wcp-payment-fields>
		<?php /* Decoy target for Clover's SDK — if absent, Clover injects its own footer at body end, breaking the page layout. See commit 4409e9a (WCP-730). */ ?>
		<div class="clover-footer"></div>
		<input type="hidden" value="" name="token" id="wcp-token"/>
		<input type="hidden" value="" name="card-brand" id="wcp-card-brand"/>
		<input type="hidden" value="" name="card-last4" id="wcp-card-last4"/>
		<input type="hidden" value="" name="card-exp-month" id="wcp-card-exp-month"/>
		<input type="hidden" value="" name="card-exp-year" id="wcp-card-exp-year"/>
		<input type="hidden" value="" name="recaptcha-token" id="wcp-recaptcha-token"/>
		<input type="hidden" value="" name="tokenized-zip" id="wcp-tokenized-zip"/>
		<input type="hidden" value="" name="hp-feedback-required" id="wcp-hp-feedback-required" autocomplete="off"/>
		<input type="hidden" value="" name="wcp-3ds-browser-info" id="wcp-3ds-browser-info" autocomplete="off"/>
		<?php
		return $this;
	}

	/**
	 * @param array $script_data
	 *
	 * @since 2.0.0
	 * @return void
	 */
	public function init( array $script_data ) {
		$this->outputElements()
		     ->registerScripts()
		     ->localizeData( $script_data )
		     ->registerStyles()
		     ->enqueueVueScriptsAndStyles();
	}
}
