<?php

use Automattic\WooCommerce\Blocks\Utils\CartCheckoutUtils;

/**
 * Routes checkout requests to greenpay.js (classic) or greenpay-blocks.js (blocks).
 *
 * Blocks when the checkout block is on the page; otherwise classic.
 */
final class WC_GreenPay_Checkout_Assets
{
	public const CONTEXT_CLASSIC = 'classic';
	public const CONTEXT_BLOCKS  = 'blocks';

	public const MODE_AUTO    = 'auto';
	public const MODE_CLASSIC = 'classic';
	public const MODE_BLOCKS  = 'blocks';

	private const CHECKOUT_BLOCK = 'woocommerce/checkout';
	private const CHECKOUT_SHORTCODE = 'woocommerce_checkout';

	public static function register_hooks(): void
	{
		add_action('wp_enqueue_scripts', array(__CLASS__, 'apply_checkout_assets'), 100);
		add_action('woocommerce_before_checkout_form', array(__CLASS__, 'apply_classic_assets'), 1);
		add_action('woocommerce_pay_order_before_submit', array(__CLASS__, 'apply_classic_assets'), 1);
		add_action('wp_print_scripts', array(__CLASS__, 'apply_checkout_assets'), 999);
	}

	/**
	 * Enqueue the bundle that matches the detected checkout context.
	 */
	public static function apply_checkout_assets(): void
	{
		if (!self::is_checkout_related_request()) {
			return;
		}

		if (self::is_blocks_checkout_context()) {
			self::dequeue_classic_assets();
			return;
		}

		self::apply_classic_assets();
	}

	/**
	 * Force classic assets (classic form render, Elementor, order-pay fallback).
	 */
	public static function apply_classic_assets(): void
	{
		self::dequeue_blocks_assets();
		self::dequeue_classic_assets();
		WC_GreenPay_Payments::enqueue_scripts_helper();
	}

	public static function get_checkout_mode_setting(): string
	{
		$settings = get_option('gmpg_settings', array());

		if (!isset($settings['gmpg_checkout_mode'])) {
			return self::MODE_AUTO;
		}

		$mode = $settings['gmpg_checkout_mode'];

		if (!in_array($mode, array(self::MODE_AUTO, self::MODE_CLASSIC, self::MODE_BLOCKS), true)) {
			return self::MODE_AUTO;
		}

		return $mode;
	}

	public static function store_uses_block_checkout(): bool
	{
		$checkout_page_id = self::get_checkout_page_id();

		if ($checkout_page_id && self::post_has_checkout_block($checkout_page_id)) {
			return true;
		}

		return class_exists(CartCheckoutUtils::class) && CartCheckoutUtils::is_checkout_block_default();
	}

	/**
	 * @return string|null self::CONTEXT_CLASSIC, self::CONTEXT_BLOCKS, or null.
	 */
	public static function get_checkout_context($post = null): ?string
	{
		if (self::is_classic_checkout_form_rendering()) {
			return self::CONTEXT_CLASSIC;
		}

		if (!self::is_checkout_related_request($post)) {
			return null;
		}

		if (
			(function_exists('is_checkout_pay_page') && is_checkout_pay_page())
			|| WC_GreenPay_Payments::is_elementor_checkout()
		) {
			return self::CONTEXT_CLASSIC;
		}

		$mode = self::get_checkout_mode_setting();

		if ($mode === self::MODE_CLASSIC) {
			return self::CONTEXT_CLASSIC;
		}

		if ($mode === self::MODE_BLOCKS) {
			return self::CONTEXT_BLOCKS;
		}

		return self::is_blocks_checkout_request($post) ? self::CONTEXT_BLOCKS : self::CONTEXT_CLASSIC;
	}

	public static function is_blocks_checkout_context($post = null): bool
	{
		return self::get_checkout_context($post) === self::CONTEXT_BLOCKS;
	}

	public static function is_classic_checkout_context($post = null): bool
	{
		return self::get_checkout_context($post) === self::CONTEXT_CLASSIC;
	}

	public static function is_checkout_related_request($post = null): bool
	{
		if (function_exists('is_checkout') && is_checkout()) {
			return true;
		}

		if (function_exists('is_checkout_pay_page') && is_checkout_pay_page()) {
			return true;
		}

		$post = self::resolve_post($post);

		if (self::post_has_checkout_shortcode($post)) {
			return true;
		}

		return self::post_has_checkout_block($post);
	}

	public static function is_blocks_checkout_request($post = null): bool
	{
		$post = self::resolve_post($post);

		if (self::post_has_checkout_shortcode($post)) {
			return false;
		}

		if (self::post_has_checkout_block($post)) {
			return true;
		}

		$checkout_page_id = self::get_checkout_page_id();

		if (!$checkout_page_id || !self::post_has_checkout_block($checkout_page_id)) {
			return false;
		}

		return (function_exists('is_checkout') && is_checkout())
			|| ($post && (int) $post->ID === (int) $checkout_page_id);
	}

	private static function is_classic_checkout_form_rendering(): bool
	{
		return did_action('woocommerce_before_checkout_form')
			|| did_action('woocommerce_pay_order_before_submit');
	}

	private static function resolve_post($post = null)
	{
		if ($post !== null) {
			return $post;
		}

		global $post;

		return $post;
	}

	private static function get_checkout_page_id(): int
	{
		return function_exists('wc_get_page_id') ? (int) wc_get_page_id('checkout') : 0;
	}

	private static function post_has_checkout_shortcode($post): bool
	{
		if ($post && isset($post->post_content) && has_shortcode($post->post_content, self::CHECKOUT_SHORTCODE)) {
			return true;
		}

		$checkout_page_id = self::get_checkout_page_id();

		if (!$checkout_page_id) {
			return false;
		}

		$checkout_post = get_post($checkout_page_id);

		return $checkout_post
			&& isset($checkout_post->post_content)
			&& has_shortcode($checkout_post->post_content, self::CHECKOUT_SHORTCODE);
	}

	private static function post_has_checkout_block($post): bool
	{
		if (!$post || !function_exists('has_block')) {
			return false;
		}

		return has_block(self::CHECKOUT_BLOCK, $post);
	}

	public static function dequeue_blocks_assets(): void
	{
		wp_dequeue_style('wc-greenpay-blocks-style');
		wp_deregister_style('wc-greenpay-blocks-style');
		wp_dequeue_script('wc-greenpay-blocks-script');
		wp_deregister_script('wc-greenpay-blocks-script');
	}

	public static function dequeue_classic_assets(): void
	{
		wp_dequeue_style('wc-greenpay-payments-style');
		wp_deregister_style('wc-greenpay-payments-style');
		wp_dequeue_script('wc-greenpay-payments-script');
		wp_deregister_script('wc-greenpay-payments-script');
	}
}
