<?php
/**
 * Braintree Cart and Checkout Blocks Support
 *
 * @package WC-Braintree/Gateway/Blocks-Support
 */

namespace WC_Braintree;

use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;

/**
 * Braintree Blocks integration
 *
 * @since 3.0.0
 */
abstract class WC_Gateway_Braintree_Blocks_Support extends AbstractPaymentMethodType {
	/**
	 * Name of the payment method.
	 *
	 * @var string
	 */
	protected $name;

	/**
	 * Path to assets
	 *
	 * @var string
	 */
	protected $asset_path;

	/**
	 * URL of script
	 *
	 * @var string
	 */
	protected $script_url;

	/**
	 * Additional script dependencies to be added to the main script.
	 *
	 * @var string[]
	 */
	protected array $additional_dependencies = array();

	/**
	 * Initializes the payment method type.
	 */
	public function initialize() {
		$this->settings = get_option( 'woocommerce_' . $this->name . '_settings', array() );
	}

	/**
	 * Returns if this payment method should be active. If false, the scripts will not be enqueued.
	 *
	 * @return boolean
	 */
	public function is_active() {
		$gateway = $this->get_gateway();

		if ( ! $gateway ) {
			return false;
		}

		return $gateway->is_available();
	}

	/**
	 * Returns an array of scripts/handles to be registered for this payment method.
	 *
	 * @return array
	 */
	public function get_payment_method_script_handles() {
		wp_register_script(
			'braintree-js-client',
			'https://js.braintreegateway.com/web/' . WC_Braintree::BRAINTREE_JS_SDK_VERSION . '/js/client.min.js',
			[],
			WC_Braintree::VERSION,
			true
		);

		$asset_path   = $this->asset_path;
		$version      = WC_Braintree::VERSION;
		$script_name  = 'wc-' . $this->name . '-blocks-integration';
		$dependencies = array_merge( array( 'braintree-js-client' ), $this->additional_dependencies );
		if ( file_exists( $asset_path ) ) {
			$asset        = require $asset_path;
			$version      = is_array( $asset ) && isset( $asset['version'] )
				? $asset['version']
				: $version;
			$dependencies = is_array( $asset ) && is_array( $asset['dependencies'] ?? null )
				? array_merge( $dependencies, $asset['dependencies'] )
				: $dependencies;
		}
		wp_register_script(
			$script_name,
			$this->script_url,
			$dependencies,
			$version,
			true
		);
		wp_set_script_translations(
			$script_name,
			'woocommerce-gateway-paypal-powered-by-braintree'
		);

		$this->enqueue_block_styles( $version );

		return array( $script_name );
	}

	/**
	 * Enqueues shared styles for Braintree Blocks payment methods.
	 *
	 * Registers and enqueues the stylesheet that powers the "Test" pill and the
	 * test-mode notice (test amount field + copyable card number). The stylesheet
	 * is shared across every Braintree Blocks gateway because the TestBadge is
	 * rendered in each gateway's payment method label.
	 *
	 * @since 3.11.0
	 *
	 * @param string $version Asset version string.
	 */
	protected function enqueue_block_styles( string $version ): void {
		$handle = 'wc-braintree-blocks-test-mode';

		if ( ! wp_style_is( $handle, 'registered' ) ) {
			wp_register_style(
				$handle,
				WC_Braintree::instance()->get_plugin_url() . '/assets/css/blocks/wc-braintree-test-mode.css',
				array(),
				$version
			);
		}

		wp_enqueue_style( $handle );
	}

	/**
	 * Returns an array of key=>value pairs of data made available to the payment methods script.
	 *
	 * @return array
	 */
	public function get_payment_method_data() {
		return array(
			'title'               => $this->get_setting( 'title' ),
			'description'         => $this->get_setting( 'description' ),
			'supports'            => $this->get_supported_features(),
			'ajax_url'            => admin_url( 'admin-ajax.php' ),
			'show_saved_cards'    => $this->get_show_saved_cards(),
			'show_save_option'    => $this->get_show_save_option(),
			'tokenization_forced' => $this->tokenization_forced(),
		);
	}

	/**
	 * Returns an array of supported features.
	 *
	 * @return string[]
	 */
	public function get_supported_features() {
		$gateway = $this->get_gateway();

		if ( ! $gateway ) {
			return array();
		}

		return $gateway->supports;
	}

	/**
	 * Determine if store allows save payment information to be saved during checkout.
	 *
	 * @return bool True if merchant allows shopper to save payment information during checkout.
	 */
	private function get_show_saved_cards() {
		$payment_form = $this->get_payment_form_instance();
		if ( $payment_form ) {
			return $payment_form->tokenization_allowed();
		}
		return false;
	}

	/**
	 * Determine if the checkbox to enable the user to save their payment method should be shown.
	 *
	 * @return bool True if the save payment checkbox should be displayed to the user.
	 */
	private function get_show_save_option() {
		return $this->get_show_saved_cards() && ! $this->tokenization_forced();
	}

	/**
	 * Determine if tokenization is forced.
	 *
	 * @return bool True if tokenization is forced.
	 */
	private function tokenization_forced() {
		$payment_form = $this->get_payment_form_instance();
		if ( $payment_form ) {
			return $payment_form->tokenization_forced();
		}
		return false;
	}

	/**
	 * Returns the payment form instance.
	 *
	 * @return WC_Braintree_Payment_Form|null
	 */
	protected function get_payment_form_instance() {
		$gateway = $this->get_gateway();

		if ( ! $gateway ) {
			return null;
		}

		return $gateway->get_payment_form_instance();
	}

	/**
	 * Returns the payment gateway instance for this instance.
	 *
	 * @since 3.8.0
	 *
	 * @return WC_Gateway_Braintree|null
	 */
	protected function get_gateway() {
		$gateways = WC()->payment_gateways->payment_gateways();

		return $gateways[ $this->name ] ?? null;
	}
}
